[轉帖]Spring事務傳播屬性之REQUIRES_NEW用法

济南小老虎發表於2024-04-17
https://www.jianshu.com/p/3e9267b025b2

@Transactional中可以設定以下7種事務傳播行為

  1. REQUIRED:支援當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。
  2. SUPPORTS:支援當前事務,如果當前沒有事務,就以非事務方式執行。
  3. MANDATORY:支援當前事務,如果當前沒有事務,就丟擲異常。
  4. REQUIRES_NEW:新建事務,如果當前存在事務,把當前事務掛起。
  5. NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
  6. NEVER:以非事務方式執行,如果當前存在事務,則丟擲異常。
  7. NESTED:支援當前事務,如果當前事務存在,則執行一個巢狀事務,如果當前沒有事務,就新建一個事務。

通常我們只會用到@Transactional(propagation = Propagation.REQUIRED)在特殊需求的時候需要在一個方法內部提前提交一部分事務或者是讓內部的一段程式碼處於單獨的一個事務管理的時候需要用到REQUIRES_NEW

例如下面示例中的methodA需要單獨開啟事務,不受呼叫方法事務的回滾而回滾:

@transaction    
public void testMethod(){
     dosomethingBefore...
     methodA();
     dosomgthingAfter...
} 

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodA(){
     updateSomething();
} 

假設我們在Controller直接呼叫testMethod() Spring會幫我們開啟一個事務
執行到methodA()這行的時候會掛起當前事務,然後重新建立一個事務,在methodA()中沒有發生異常的情況下,執行完methodA方法直接提交methodA的事務;後續再執行dosomgthingAfter。

總共會有4種情況:

  • dosomethingBefore發生異常,這時methodA()未執行也就沒有事務,直接回滾testMethod()的事務。
  • updateSomething發生異常,回滾methodA()的事務,此時如果testMethod()對這個異常進行了try catch捕獲,testMethod的事務照常提交。
  • updateSomething發生異常,回滾methodA()的事務,此時如果testMethod()沒有對這個異常進行try catch捕獲,那麼methodA和testMethod的事務都會回滾。
  • 前面全部正常 dosomgthingAfter 發生異常,這時methodA()事務已經提交 testMethod()所做的修改會回滾。

相關文章