上一节中我们分析了事务的创建,这一节我们继续分析事务的回滚与提交
protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.hasTransaction()) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
"] after exception: " + ex);
//是否需要对当前异常进行回滚
if (txInfo.transactionAttribute.rollbackOn(ex)) {
try {
//回滚事务
//(*1*)
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by rollback exception", ex);
ex2.initApplicationException(ex);
throw ex2;
catch (RuntimeException ex2) {
logger.error("Application exception overridden by rollback exception", ex);
throw ex2;
catch (Error err) {
logger.error("Application exception overridden by rollback error", ex);
throw err;
else {
// We don't roll back on this exception.
// Will still roll back if TransactionStatus.isRollbackOnly() is true.
try {
//如果无需回滚,那么提交事务,在前面提到过默认回滚异常规则中,只对RuntimeException和Error做回滚
//所以会执行这一步
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by commit exception", ex);
ex2.initApplicationException(ex);
throw ex2;
catch (RuntimeException ex2) {
logger.error("Application exception overridden by commit exception", ex);
throw ex2;
catch (Error err) {
logger.error("Application exception overridden by commit error", ex);
throw err;
//(*1*)
public final void rollback(TransactionStatus status) throws TransactionException {
//判断这个事务是否已经结束,如果结束抛错
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
//目前spring中创建的事务状态都是DefaultTransactionStatus类型,所以基本上都是直接这样强转的
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
//处理回滚
//(*2*)
processRollback(defStatus);
//(*2*)
private void processRollback(DefaultTransactionStatus status) {
try {
try {
//在结束事务之前触发事务同步。
triggerBeforeCompletion(status);
//如果存在保存点,那么通过内嵌的保存点进行回滚
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Rolling back transaction to savepoint");
//回滚保存点,保存点在JDBC 3.0开始支持的
status.rollbackToHeldSavepoint();
//如果这是一个新事务,那么回滚这个事务,在PROPAGATION_REQUIRED传播行为下
//使用的事务是旧得事务,那么不会发生回滚,它的事务周期在更上一层处理
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction rollback");
doRollback(status);
//不是新事务,并且要求了内部异常也需要导致上层事务回滚,那么标记当前事务回滚,否则啥都不做
else if (status.hasTransaction()) {
if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
if (status.isDebug()) {
logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
//标记事务回滚
doSetRollbackOnly(status);
else {
if (status.isDebug()) {
logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
else {
logger.debug("Should roll back transaction but cannot - no transaction available");
catch (RuntimeException ex) {
//触发事务结束事件
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw ex;
catch (Error err) {
//触发事务结束事件
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw err;
//触发事务结束事件
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
finally {
//清理事务信息,恢复被挂起的事务
cleanupAfterCompletion(status);
回滚前后置处理triggerBeforeCompletion,
public static void triggerBeforeCompletion() {
//我们可以实现自己的同步器,这样在spring进行事务的提交,回滚等操作时可以通知到我们自定义的同步器,然后做一些特殊的处理
for (TransactionSynchronization synchronization : TransactionSynchronizationManager.getSynchronizations()) {
try {
synchronization.beforeCompletion();
catch (Throwable tsex) {
logger.error("TransactionSynchronization.beforeCompletion threw exception", tsex);
private void triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus) {
if (status.isNewSynchronization()) {
List<TransactionSynchronization> synchronizations = TransactionSynchronizationManager.getSynchronizations();
if (!status.hasTransaction() || status.isNewTransaction()) {
if (status.isDebug()) {
logger.trace("Triggering afterCompletion synchronization");
// No transaction or new transaction for the current scope ->
// invoke the afterCompletion callbacks immediately
//直接调用TransactionSynchronization的AfterCompletion方法
invokeAfterCompletion(synchronizations, completionStatus);
else if (!synchronizations.isEmpty()) {
// Existing transaction that we participate in, controlled outside
// of the scope of this Spring transaction manager -> try to register
// an afterCompletion callback with the existing (JTA) transaction.
//处理存在的事务,一般用于jta,不是jta的话直接调用TransactionSynchronization的AfterCompletion方法
registerAfterCompletionWithExistingTransaction(status.getTransaction(), synchronizations);
回滚操作很简单,就是我们属性的调用Connect的rollback方法
protected void doRollback(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
try {
con.rollback();
catch (SQLException ex) {
throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
回滚完毕后,如果存在挂起的事务资源,那么还需要对挂起的资源进行回滚
private void cleanupAfterCompletion(DefaultTransactionStatus status) {
//设置事务状态为结束
status.setCompleted();
if (status.isNewSynchronization()) {
//清空所有信息
TransactionSynchronizationManager.clear();
if (status.isNewTransaction()) {
//(*1*)
doCleanupAfterCompletion(status.getTransaction());
//如果存在挂起的资源,恢复
if (status.getSuspendedResources() != null) {
if (status.isDebug()) {
logger.debug("Resuming suspended transaction after completion of inner transaction");
//恢复被挂起的资源
resume(status.getTransaction(), (SuspendedResourcesHolder) status.getSuspendedResources());
//(*1*)
protected void doCleanupAfterCompletion(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
// Remove the connection holder from the thread, if exposed.
if (txObject.isNewConnectionHolder()) {
//如果新创建的连接,那么可以再次解绑
TransactionSynchronizationManager.unbindResource(this.dataSource);
// Reset connection.
Connection con = txObject.getConnectionHolder().getConnection();
try {
//恢复自动提交
if (txObject.isMustRestoreAutoCommit()) {
con.setAutoCommit(true);
//(*2*)
DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel());
catch (Throwable ex) {
logger.debug("Could not reset JDBC Connection after transaction", ex);
if (txObject.isNewConnectionHolder()) {
if (logger.isDebugEnabled()) {
logger.debug("Releasing JDBC Connection [" + con + "] after transaction");
//释放connection
//调用connect.close()
DataSourceUtils.releaseConnection(con, this.dataSource);
txObject.getConnectionHolder().clear();
//(*2*)
public static void resetConnectionAfterTransaction(Connection con, Integer previousIsolationLevel) {
Assert.notNull(con, "No Connection specified");
try {
// Reset transaction isolation to previous value, if changed for the transaction.
if (previousIsolationLevel != null) {
if (logger.isDebugEnabled()) {
logger.debug("Resetting isolation level of JDBC Connection [" +
con + "] to " + previousIsolationLevel);
//恢复隔离级别
con.setTransactionIsolation(previousIsolationLevel);
// Reset read-only flag.
//恢复只读标记
if (con.isReadOnly()) {
if (logger.isDebugEnabled()) {
logger.debug("Resetting read-only flag of JDBC Connection [" + con + "]");
con.setReadOnly(false);
catch (Throwable ex) {
logger.debug("Could not reset JDBC Connection after transaction", ex);
protected final void resume(Object transaction, SuspendedResourcesHolder resourcesHolder)
throws TransactionException {
if (resourcesHolder != null) {
//获取被挂起的资源
Object suspendedResources = resourcesHolder.suspendedResources;
if (suspendedResources != null) {
//(*1*)
doResume(transaction, suspendedResources);
List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;
//如果存在事务同步,不管集合是否为空,但最起码这个事务是支持事务同步的
//那么进行同步状态的恢复
if (suspendedSynchronizations != null) {
TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);
TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);
TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);
doResumeSynchronization(suspendedSynchronizations);
//(*1*)
protected void doResume(Object transaction, Object suspendedResources) {
ConnectionHolder conHolder = (ConnectionHolder) suspendedResources;
//将挂起的数据库连接重新绑定到当前线程中
TransactionSynchronizationManager.bindResource(this.dataSource, conHolder);
事务的提交
protected void commitTransactionAfterReturning(TransactionInfo txInfo) {
if (txInfo != null && txInfo.hasTransaction()) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
//调用事务管理器提交事务
//(*1*)
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
//(*1*)
public final void commit(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
//如果内部继承本事务的方法发生了异常,比如PROPAGATION_REQUIRED这种类型传播属性
//并被标记回滚,那么进行回滚,回滚的逻辑我们在上面已经分析过了,不再赘述
if (defStatus.isLocalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Transactional code has requested rollback");
processRollback(defStatus);
return;
//用于jta的事务回滚
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
processRollback(defStatus);
// Throw UnexpectedRollbackException only at outermost transaction boundary
// or if explicitly asked to.
if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
throw new UnexpectedRollbackException(
"Transaction rolled back because it has been marked as rollback-only");
return;
//(*2*)
processCommit(defStatus);
//(*2*)
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
boolean beforeCompletionInvoked = false;
try {
//由子类实现
prepareForCommit(status);
//提交前置处理,调用同步器beforeCommit
triggerBeforeCommit(status);
//事务结束前置处理,调用同步器beforeCompletion
triggerBeforeCompletion(status);
beforeCompletionInvoked = true;
boolean globalRollbackOnly = false;
if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
globalRollbackOnly = status.isGlobalRollbackOnly();
//释放保存点
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Releasing transaction savepoint");
status.releaseHeldSavepoint();
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction commit");
//(*3*)
doCommit(status);
// Throw UnexpectedRollbackException if we have a global rollback-only
// marker but still didn't get a corresponding exception from commit.
if (globalRollbackOnly) {
throw new UnexpectedRollbackException(
"Transaction silently rolled back because it has been marked as rollback-only");
catch (UnexpectedRollbackException ex) {
// can only be caused by doCommit
//触发事务同步的AfterCompletion方法
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
throw ex;
catch (TransactionException ex) {
// can only be caused by doCommit
if (isRollbackOnCommitFailure()) {
doRollbackOnCommitException(status, ex);
else {
//触发事务同步的AfterCompletion方法
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw ex;
catch (RuntimeException ex) {
if (!beforeCompletionInvoked) {
//触发事务同步的AfterCompletion方法
triggerBeforeCompletion(status);
doRollbackOnCommitException(status, ex);
throw ex;
catch (Error err) {
if (!beforeCompletionInvoked) {
//触发事务同步的AfterCompletion方法
triggerBeforeCompletion(status);
doRollbackOnCommitException(status, err);
throw err;
// Trigger afterCommit callbacks, with an exception thrown there
// propagated to callers but the transaction still considered as committed.
try {
//触发事务同步的AfterCommit方法
triggerAfterCommit(status);
finally {
//触发事务同步的afterCompletion方法
triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
finally {
//和回滚是一样的操作,进行连接的释放,挂起事务的恢复
cleanupAfterCompletion(status);
//(*3*)
protected void doCommit(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Committing JDBC transaction on Connection [" + con + "]");
try {
con.commit();
catch (SQLException ex) {
throw new TransactionSystemException("Could not commit JDBC transaction", ex);
好了,关于事务的分析就到此结束。