簡體   English   中英

交易中的Spring程序化交易

[英]Spring Programmatic transaction within transaction

我在下面的代碼中編寫了以下活動,這些活動使用Spring類創建了一個事務。 插入了一行。 創建其他交易。 插入了另一行。 承諾的外部交易。 回滾內部事務。

TransactionStatus trxstsOuter= dsTrxMngr.getTransaction(null);
    jdbcTemplate.update("insert into kau_emp values(6,'xyz' )");
    TransactionStatus trxstsInner= dsTrxMngr.getTransaction(null);
        jdbcTemplate.update("insert into kau_emp values(7,'pqr' )");

dsTrxMngr.commit(trxstsOuter);
System.out.println("trxstsOuter.isCompleted()" + trxstsOuter.isCompleted());
System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());
dsTrxMngr.rollback(trxstsInner);
    System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());

我觀察到這兩行都提交給數據庫! 輸出是

trxstsOuter.isCompleted()true
trxstsInner.isCompleted()false
trxstsInner.isCompleted()true

這是正確的行為嗎? 在允許外部事務提交之前,內部事務是否應該先提交/回滾? 如果外部事務已提交,內部回滾是否應該拋出錯誤?

在您的示例事務中, Propagation.REQUIRED用作默認值,並且所有邏輯事務都映射到單個物理事務

當傳播設置為PROPAGATION_REQUIRED時,將為應用該設置的每種方法創建一個邏輯事務作用域。 每個此類邏輯事務作用域可以單獨確定僅回滾狀態,而外部事務作用域在邏輯上與內部事務作用域無關。 當然,在標准PROPAGATION_REQUIRED行為的情況下,所有這些范圍都將映射到同一物理事務。 因此,內部事務范圍中設置的僅回滾標記確實會影響外部事務實際提交的機會(正如您期望的那樣)。

因此,在您的示例中,兩個邏輯事務映射到一個物理事務。

請參閱說明文件

在當前代碼中,第二個getTransaction調用是noop。 此行為由稱為PropagationBehavior的屬性控制。 默認傳播行為是PROPAGATION_REQUIRED-這意味着如果不存在新事務,則啟動一個新事務,否則將其加入現有事務。 您的情況正在發生什么。

如果將第二個事務的傳播行為屬性更改為PROPAGATION_REQUIRES_NEW-您將獲得預期的行為。 一旦內部事務被提交/回滾,外部事務將被掛起並創建新的事務,外部事務將自動恢復。 我已經修改了您的代碼以合並這種行為,當您嘗試在內部事務之前提交外部事務時,應該現在得到一個異常。 如果您修復順序,則提交將獨立發生。

TransactionStatus trxstsOuter= dsTrxMngr.getTransaction(null);
jdbcTemplate.update("insert into kau_emp values(6,'xyz' )");
    // start a new transaction.
    DefaultTransactionDefinition nestedTransDef = new DefaultTransactionDefinition();
    nestedTransDef.setPropagationBehavior(             
           TransactionDefinition.PROPAGATION_REQUIRES_NEW);
    TransactionStatus trxstsInner= dsTrxMngr.getTransaction(nestedTransDef);
     System.out.println("trxstsInner.isNewTransaction()"+ trxstsInner.isNewTransaction());  
        jdbcTemplate.update("insert into kau_emp values(7,'pqr' )");

dsTrxMngr.commit(trxstsOuter);
    System.out.println("trxstsOuter.isCompleted()" + trxstsOuter.isCompleted());
    System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());
    dsTrxMngr.rollback(trxstsInner);
    System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());

順便說一句,您應該使用注釋來管理事務-這是在代碼中合並事務的更簡潔/更好的方法。 程序化交易僅適用於您需要更多控制的罕見情況。 另外,在進行程序化事務時,建議使用TransactionTemplate。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM