Spring基礎課九:事務管理下

spring 事務源碼

  1. DataSourceTransactionManager.DataSourceTransactionObject 中的 Connection,第一次是從數據源獲取的,並會綁定到了 TransactionSynchronizationManager 的 threadLocal 成員變量 resource 中,之後獲取,都是從成員變量 resource 中獲取;

  2. 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;
  1. 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;
  1. isExistingTransaction(transaction),判斷是否存在事務,判斷 transaction 中的 connHolder 是否存在,第一次應該是不存在,如果存在,按照傳播方式,加入事務或拋出異常等不同操作;
	--isExistingTransaction(transaction)
    return txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive();
  1. 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());
    }
  1. prepareSynchronization(status, definition),判斷如果是新事務,給 TransactionSynchronizationManager 設置一些標誌位,這些標誌位也都是 threadLocal 封裝的,handleExistingTransaction(definition, transaction, debugEnabled),用於處理事務的傳播方式;

  2. commit(TransactionStatus status),提交事務

	--prepareForCommit(status);
	triggerBeforeCommit(status);
	doCommit(status);
	triggerAfterCommit(status);
  1. doCommit(status),具體提交事務,rollback 和 commit 的邏輯類似;
	--doCommit(status)
	// 獲取封裝在DataSourceTransactionManager.DataSourceTransactionObject中的Connection,
	// 調用其commit來提交事務
	Connection con = txObject.getConnectionHolder().getConnection();
	con.commit();

事務使用方式

  1. 基本上底層均是使用jdbc控制事務的方式,推薦使用spring事務,更方便和通用;

  2. 儘量避免jdbc和orm框架混合操作數據庫;

  3. 推薦使用spring提供TransactionTemplate模板類和註解方式使用事務,如果需要獲取數據庫連接,需要通過DataSourceUtils工具類;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章