上一讲我们讲到事务状态创建,我们这章继续上次事务,讲一讲事务的回滚、清理及提交
事务回滚
事务回滚由具体的db客户端实现类实现,如下他们的继承关系如下:
具体的回滚代码以dataSourceTransactionManager为例说明:
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);
}
}
就是获取当前事务的链接,执行回滚,这个链接在创建事务信息的时候已说明。具体到con.rollback()可以以mysql的链接客户端代码为例,即通过链接io发送rollback的命令到服务器端来实现回滚,如下代码:
private void rollbackNoChecks() throws SQLException {
if ((getUseLocalTransactionState()) && (versionMeetsMinimum(5, 0, 0)) &&
(!this.io.inTransactionOnServer())) {
return;
}
execSQL(null, "rollback", -1, null, 1003, 1007, false, this.database, null, false);
}
一个execSQL语句就是通过io链接想服务器提交sql语句的过程。
事务清理
事务清理,比较简单,如下代码:
protected void cleanupTransactionInfo(TransactionInfo txInfo) {
if (txInfo != null) {
txInfo.restoreThreadLocalStatus();
}
}
private void restoreThreadLocalStatus() {
// Use stack to restore old transaction TransactionInfo.
// Will be null if none was set.
transactionInfoHolder.set(this.oldTransactionInfo);
}
只是将事务信息里面transactionInfoHolder重新设置为oldTransactionInfo而已。
事务提交
事务提交完成最后有一段方法是cleanupAfterCompletion,这个代码如下:
private void cleanupAfterCompletion(DefaultTransactionStatus status) {
status.setCompleted();
if (status.isNewSynchronization()) {
TransactionSynchronizationManager.clear();
}
if (status.isNewTransaction()) {
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());
}
}
在之前的事务状态信息创建的时候也提到,红色代码是对挂起事务的还原,具体的resume如下:
protected final void resume(Object transaction, SuspendedResourcesHolder resourcesHolder)
throws TransactionException {
if (resourcesHolder != null) {
Object suspendedResources = resourcesHolder.suspendedResources;
if (suspendedResources != null) {
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);
}
}
}
主要是将挂起资源信息取出还原到当前同步线程中,并且把整个事务资源信息注册进去,如下:
public static void registerSynchronization(TransactionSynchronization synchronization)
throws IllegalStateException {
Assert.notNull(synchronization, "TransactionSynchronization must not be null");
if (!isSynchronizationActive()) {
throw new IllegalStateException("Transaction synchronization is not active");
}
synchronizations.get().add(synchronization);
}