回到上上一章的invokeWithinTransaction方法扬虚,我們來看看事物的提交方法commitTransactionAfterReturning
protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
}
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
}
點(diǎn)進(jìn)commit方法
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");
}
///如果在事務(wù)鏈中已經(jīng)被標(biāo)記回滾,那不會(huì)嘗試提交事務(wù)买羞,直接回滾
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;
}
// 如果沒有被標(biāo)記回滾之類的珍语,這里才真正判斷是否提交
processCommit(defStatus);
可以看到事務(wù)不是立刻提交的,還是要做一些校驗(yàn)。
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
boolean beforeCompletionInvoked = false;
try {
boolean unexpectedRollback = false;
prepareForCommit(status);
triggerBeforeCommit(status);
triggerBeforeCompletion(status);
beforeCompletionInvoked = true;
// 判斷是否有savePoint
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Releasing transaction savepoint");
}
unexpectedRollback = status.isGlobalRollbackOnly();
// 不提交合蔽,僅僅是釋放savePoint
status.releaseHeldSavepoint();
}
// 判斷是否是新事務(wù)
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
// marker but still didn't get a corresponding exception from 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
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
throw ex;
}
catch (TransactionException ex) {
// can only be caused by 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
// propagated to callers but the transaction still considered as committed.
try {
triggerAfterCommit(status);
}
finally {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
}
}
// 清空記錄的資源并將掛起的資源恢復(fù)
finally {
cleanupAfterCompletion(status);
}
}
status.hasSavepoint()如果status有savePoint介返,說明此時(shí)的事務(wù)是嵌套事務(wù)NESTED拴事,這個(gè)事務(wù)外面還有事務(wù),這里不提交圣蝎,只是釋放保存點(diǎn)刃宵。這里也可以看出來NESTED的傳播行為了。
status.isNewTransaction()如果是新的事務(wù)徘公,才會(huì)提交Iぁ!关面,這里如果是子事務(wù)坦袍,只有PROPAGATION_NESTED狀態(tài)才會(huì)走到這里提交十厢,也說明了此狀態(tài)子事務(wù)提交和外層事務(wù)是隔離的
在最后的提交流程,Spring會(huì)將事務(wù)提交的操作引導(dǎo)至底層數(shù)據(jù)庫連接的API键闺,進(jìn)行事務(wù)提交寿烟。
直接看processCommit方法中的doCommit方法
@Override
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 {
//數(shù)據(jù)庫的提交方法
con.commit();
}
catch (SQLException ex) {
throw new TransactionSystemException("Could not commit JDBC transaction", ex);
}
}
從提交的邏輯看,只有status是新事務(wù)辛燥,才會(huì)進(jìn)行提交
所以事務(wù)的提交最后依靠的還是數(shù)據(jù)庫的事務(wù)提交方法