TransactionManager的第4部分,分析commit及rollback方法。
commit
commit方法也是在AbstactPlantformTransactionManager中定义的。
可以看到commit方法的参数是TransactionStatus,前面开启事务getTransaction的返回也是这个对象。
首先判断事务状态如果是已完成的话抛异常。
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");
}
然后判断当前事务是否被设置为只能rollback,是的话调用processRollback方法回滚。否则,调用processCommit方法提交事务。
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
processCommit方法仍然在AbstractPlantformTransactionManager中。
Process an actual commit. Rollback-only flags have already been checked and applied.
Params:
status – object representing the transaction
Throws:
TransactionException – in case of commit failure执行真正的commit,如果设置了回滚标识的话则回滚事务
可见运行到processCommit之后,事务仍然有可能被回滚。
调用prepareForCommit做提交前准备,调用triggerBeforeCommit/triggerBeforeCompletion触发提交前监听。
try {
boolean beforeCompletionInvoked = false;
try {
boolean unexpectedRollback = false;
prepareForCommit(status);
triggerBeforeCommit(status);
triggerBeforeCompletion(status);
beforeCompletionInvoked = true;
查看了一下prepareForCommit,在AbstarctPlantformTransactionManager中没有任何代码实现,他的子类也没有做实现。所以这个方法可能是为了扩展预留的。
所有的提交前、提交后监听器处理,我们就不做分析了,个人认为不太重要,很少有适用的场景。
所以我们继续往下看,检查status中是否有savepoint,有的话,释放savepoint,这里需要留一个小疑问,在传播机制设置为嵌套的情况下,已开启事务会设置savepoint,代码逻辑应该会走到这里来,但是这里只是释放savepoint,后续并没有调用commit,这是不应该的。暂存疑问。
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Releasing transaction savepoint");
}
unexpectedRollback = status.isGlobalRollbackOnly();
status.releaseHeldSavepoint();
}
接下来,才调用到了真正的事务提交方法doCommit,注意status的isNewTransaction必须为true,事务才能被提交。
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction commit");
}
unexpectedRollback = status.isGlobalRollbackOnly();
doCommit(status);
}
之后就是事务提交的后处理了,判断如果发生提交时异常则回滚事务,然后还有就是提交后的监听处理,这部分就不再详细分析了。
doCommit
commit方法的最终提交真相都在这里。我们已经知道,他一定是在DataSourceTransactionManager中实现的。
到这里,该铺垫的、该准备的都已经完成了,提交方法本身反而非常简单了。
通过TransactionStatus获取事务对象transaction,在通过其持有的ConnectionHolder获取到数据库连接Connection,然后,就是Connection的commit方法。
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 translateException("JDBC commit", ex);
}
}
前面的getTransaction,以及commit方法在调用到doCommit方法之前的一堆准备操作,相当于是在弯弓搭箭,最后这一下con.commit才最终射向数据库。把最复杂的事务提交(其实还有数据开启、sql语句在事务下执行等)甩锅给数据库去处理了。
commit方法分析完毕。
rollback
其实,分析完commiit方法之后,rollback方法就没有什么秘密了。
rollback方法也是在AbstractPlatformTranactionManager中,结构与commit几乎一样,区别之处在processRollback中判断事务有保存点的话:
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Rolling back transaction to savepoint");
}
status.rollbackToHeldSavepoint();
}
调用TransactionStatus的rollbackToHeldSavepoint,回滚到保存点。
其他的代码结构就和commit几乎一样了,调用doRollback方法,之后就是回滚的后处理。
doRollback方法同样在DataSourcePlantformTransactionManager中实现,获取数据库连接并调用数据库连接的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 translateException("JDBC rollback", ex);
}
}
OK了,TransactionMnaager的3大方法:启动事务、提交事务、回滚事务分析完毕。
后面有关Spring事务管理的相关支持还有事务启用机制(@EnableTransactionManagement)以及事务控制(@Transactional),可以看过是Spring事务框架的具体应用了。
有机会再做详细分析。