本文轉自「天河聊技術」微信公衆號spring
說在前面數據庫
@Transactional實現,接着上篇文章繼續微信
正文ide
事務回滾源碼解析this
上次解析到這個方法org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction的這一行debug
執行事務方法code
retVal = invocation.proceedWithInvocation();
catch (Throwable ex) { // target invocation exception 執行業務方法異常 completeTransactionAfterThrowing(txInfo, ex); throw ex; }
進入到這個方法orm
org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowing事務
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) { if (txInfo != null && txInfo.getTransactionStatus() != null) { if (logger.isTraceEnabled()) { logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "] after exception: " + ex); } // 有指定的異常回滾,異常類型是檢查異常或者是非檢查異常,非檢查性異常自動回滾 if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) { try { // 事務回滾 txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus()); } catch (TransactionSystemException ex2) { logger.error("Application exception overridden by rollback exception", ex); ex2.initApplicationException(ex); throw ex2; } catch (RuntimeException | Error ex2) { logger.error("Application exception overridden by rollback exception", ex); throw ex2; } } else { // We don't roll back on this exception. // Will still roll back if TransactionStatus.isRollbackOnly() is true. try { txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); } catch (TransactionSystemException ex2) { logger.error("Application exception overridden by commit exception", ex); ex2.initApplicationException(ex); throw ex2; } catch (RuntimeException | Error ex2) { logger.error("Application exception overridden by commit exception", ex); throw ex2; } } } }
事務回滾 txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
進入到這個方法ip
org.springframework.transaction.support.AbstractPlatformTransactionManager#rollback
@Override 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"); } DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status; // 執行事務回滾 processRollback(defStatus, false); }
private void processRollback(DefaultTransactionStatus status, boolean unexpected) { try { boolean unexpectedRollback = unexpected; try { // 事務資源解綁 triggerBeforeCompletion(status); // 事務是否有回滾點 if (status.hasSavepoint()) { if (status.isDebug()) { logger.debug("Rolling back transaction to savepoint"); } // 事務狀態回退到回滾點 status.rollbackToHeldSavepoint(); } else if (status.isNewTransaction()) { if (status.isDebug()) { logger.debug("Initiating transaction rollback"); } doRollback(status); } else { // Participating in larger transaction參與更大的交易 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"); } // Unexpected rollback only matters here if we're asked to fail early若是咱們被要求提早失敗,那麼意外的回滾就很重要了。 if (!isFailEarlyOnGlobalRollbackOnly()) { unexpectedRollback = false; } } } catch (RuntimeException | Error ex) { triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); throw ex; } triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); // Raise UnexpectedRollbackException if we had a global rollback-only marker若是咱們有一個僅用於全局回滾的標記,那麼就會引起unexpected tedrollbackexception if (unexpectedRollback) { throw new UnexpectedRollbackException( "Transaction rolled back because it has been marked as rollback-only"); } } finally { cleanupAfterCompletion(status); } }
事務狀態回退到回滾點 status.rollbackToHeldSavepoint();
public void rollbackToHeldSavepoint() throws TransactionException { Object savepoint = getSavepoint(); if (savepoint == null) { throw new TransactionUsageException( "Cannot roll back to savepoint - no savepoint associated with current transaction"); } // 事務回滾到事務回滾點 getSavepointManager().rollbackToSavepoint(savepoint); // 釋放事務回滾點 getSavepointManager().releaseSavepoint(savepoint); setSavepoint(null); }
返回到這個方法
org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollback這行
事務回滾 doRollback(status);
@Override 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); } }
事務提交源碼解析
返回到這個方法org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowing這行
事務提交
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
進入到這個方法org.springframework.transaction.support.AbstractPlatformTransactionManager#commit
@Override 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; // 若是是本地事務回滾 if (defStatus.isLocalRollbackOnly()) { if (defStatus.isDebug()) { logger.debug("Transactional code has requested rollback"); } // 事務回滾 processRollback(defStatus, false); return; } // 全局事務回滾 if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) { if (defStatus.isDebug()) { logger.debug("Global transaction is marked as rollback-only but transactional code requested commit"); } // 事務回滾 processRollback(defStatus, true); return; } // 事務提交 processCommit(defStatus); }
// 事務提交 processCommit(defStatus);
private void processCommit(DefaultTransactionStatus status) throws TransactionException { try { boolean beforeCompletionInvoked = false; try { boolean unexpectedRollback = false; // 準備提交 prepareForCommit(status); // 出發提交以前回調 triggerBeforeCommit(status); triggerBeforeCompletion(status); beforeCompletionInvoked = true; if (status.hasSavepoint()) { if (status.isDebug()) { logger.debug("Releasing transaction savepoint"); } unexpectedRollback = status.isGlobalRollbackOnly(); status.releaseHeldSavepoint(); } else if (status.isNewTransaction()) { if (status.isDebug()) { logger.debug("Initiating transaction commit"); } unexpectedRollback = status.isGlobalRollbackOnly(); // 事務提交 doCommit(status); } else if (isFailEarlyOnGlobalRollbackOnly()) { unexpectedRollback = status.isGlobalRollbackOnly(); } // Throw UnexpectedRollbackException if we have a global rollback-only若是咱們只進行全局回滾,那麼將拋出unexpected tedrollbackexception // marker but still didn't get a corresponding exception from commit.可是仍然沒有從commit獲得相應的異常。 if (unexpectedRollback) { throw new UnexpectedRollbackException( "Transaction silently rolled back because it has been marked as rollback-only"); } } catch (UnexpectedRollbackException ex) { // can only be caused by doCommit只能由doCommit引發嗎 triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); throw ex; } catch (TransactionException ex) { // can only be caused by doCommit只能由doCommit引發嗎 if (isRollbackOnCommitFailure()) { doRollbackOnCommitException(status, ex); } else { triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); } throw ex; } catch (RuntimeException | Error ex) { if (!beforeCompletionInvoked) { triggerBeforeCompletion(status); } doRollbackOnCommitException(status, ex); throw ex; } // Trigger afterCommit callbacks, with an exception thrown there觸發afterCommit回調,並在其中拋出一個異常 // propagated to callers but the transaction still considered as committed.傳播到調用者,但事務仍然被認爲是提交的。 try { triggerAfterCommit(status); } finally { triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED); } } finally { cleanupAfterCompletion(status); } }
說到最後
本次解析僅表明我的看法,僅供參考。