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工具類;