spring 事务源码
-
DataSourceTransactionManager.DataSourceTransactionObject 中的 Connection,第一次是从数据源获取的,并会绑定到了 TransactionSynchronizationManager 的 threadLocal 成员变量 resource 中,之后获取,都是从成员变量 resource 中获取;
-
transactionManager.getTransaction(transactionDefinition),用来开启一个事务,源码:
--》TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
Object transaction = doGetTransaction();
if (definition == null) {
definition = new DefaultTransactionDefinition();
}
if (isExistingTransaction(transaction)) {
return handleExistingTransaction(definition, transaction, debugEnabled);
}
// 构造一个transactionStatus
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
- doGetTransaction(),获取事务对象 transaction;
--》doGetTransaction()
DataSourceTransactionManager.DataSourceTransactionObject txObject = new
DataSourceTransactionManager.DataSourceTransactionObject();
// 设置是否允许嵌套
txObject.setSavepointAllowed(this.isNestedTransactionAllowed());
// 从TransactionSynchronizationManager的threadLocal成员变量中获取ConHolder,第一次获取应该是null
ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager
.getResource(this.obtainDataSource());
txObject.setConnectionHolder(conHolder, false);
return txObject;
- isExistingTransaction(transaction),判断是否存在事务,判断 transaction 中的 connHolder 是否存在,第一次应该是不存在,如果存在,按照传播方式,加入事务或抛出异常等不同操作;
--》isExistingTransaction(transaction)
return txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive();
- doBegin(transaction, definition),从数据源获取连接,并设置到事务对象 transaction 中;
--》doBegin(transaction, definition)
// 从数据源获取一个连接
Connection newCon = this.obtainDataSource().getConnection();
// 将连接设置到 transaction 中,并设置一些标志位,隔离级别
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
con.setAutoCommit(false);
// 如果是第一次获取到的连接,将 datasource 和 connection 的键值对,
// 设置到 TransactionSynchronizationManager 的 threadLocal 成员变量中
// 保证了同一个线程从 TransactionSynchronizationManager 获取到的 resource 是同一个,不同线程间互不干扰
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.bindResource
(this.obtainDataSource(),txObject.getConnectionHolder());
}
-
prepareSynchronization(status, definition),判断如果是新事务,给 TransactionSynchronizationManager 设置一些标志位,这些标志位也都是 threadLocal 封装的,handleExistingTransaction(definition, transaction, debugEnabled),用于处理事务的传播方式;
-
commit(TransactionStatus status),提交事务
--》
prepareForCommit(status);
triggerBeforeCommit(status);
doCommit(status);
triggerAfterCommit(status);
- doCommit(status),具体提交事务,rollback 和 commit 的逻辑类似;
--》doCommit(status)
// 获取封装在DataSourceTransactionManager.DataSourceTransactionObject中的Connection,
// 调用其commit来提交事务
Connection con = txObject.getConnectionHolder().getConnection();
con.commit();
事务使用方式
-
基本上底层均是使用jdbc控制事务的方式,推荐使用spring事务,更方便和通用;
-
尽量避免jdbc和orm框架混合操作数据库;
-
推荐使用spring提供TransactionTemplate模板类和注解方式使用事务,如果需要获取数据库连接,需要通过DataSourceUtils工具类;