Spring 事務的七種傳播行爲

Spring事務傳播行爲

spring特有的事務傳播行爲,spring支持7種事務傳播行爲,確定客戶端和被調用端的事務邊界(說得通俗一點就是多個具有事務控制的service的相互調用時所形成的複雜的事務邊界控制)下圖所示爲7鍾事務傳播機制。

傳播行爲 含義
REQUIRED 表示當前方法必須在一個具有事務的上下文中運行,如有客戶端有事務在進行,那麼被調用端將在該事務中運行,否則的話重新開啓一個事務。(如果被調用端發生異常,那麼調用端和被調用端事務都將回滾
SUPPORTS 表示當前方法不必需要具有一個事務上下文,但是如果有一個事務的話,它也可以在這個事務中運行
MANDATORY 表示當前方法必須在一個事務中運行,如果沒有事務,將拋出異常
NESTED 表示如果當前方法正有一個事務在運行中,則該方法應該運行在一個嵌套事務中,被嵌套的事務可以獨立於被封裝的事務中進行提交或者回滾。如果封裝事務存在,並且外層事務拋出異常回滾,那麼內層事務必須回滾,反之,內層事務並不影響外層事務。如果封裝事務不存在,則同REQUIRED的一樣
NEVER 表示當方法務不應該在一個事務中運行,如果存在一個事務,則拋出異常
REQUIRES_NEW 表示當前方法必須運行在它自己的事務中。一個新的事務將啓動,而且如果有一個現有的事務在運行的話,則這個方法將在運行期被掛起,直到新的事務提交或者回滾才恢復執行。
NOT_SUPPORTED 表示該方法不應該在一個事務中運行。如果有一個事務正在運行,他將在運行期被掛起,直到這個事務提交或者回滾才恢復執行

 

調用關係

類 ServiceA 的方法 methodA() 調用了類 ServiceB 的方法 methodB()。

class ServiceA {
	public void methodA() {
		serviceB.methodB();
	}
}

class ServiceB {
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.XXX)
	public void methodB() {
		// ...
	}
}

 

例子講解以上七中事務傳播機制

REQUIRED

如果B的方法methodB()的事務傳播特性是: REQUIRED
A.methodA()調用B的methodB()方法,那麼如果A的方法包含事務,則B的方法則不重新開啓事務

  1. 如果B的methodB()拋出異常,A的methodB()沒有捕獲,則A和B的事務都會回滾;
  2. 如果B的methodB()運行期間異常會導致B的methodB()的回滾,A如果捕獲了異常,並正常提交事務,則會發生Transaction rolled back because it has been marked as rollback-only的異常。
  3. 如果A的methodA()運行期間異常,則A和B的Method的事務都會被回滾

 

SUPPORTS

如果B的方法methodB()的事務傳播特性是: SUPPORTS

A.methodA()調用B的methodB()方法,那麼如果A的方法包含事務,則B運行在此事務環境中,如果A的方法不包含事務,則B運行在非事務環境;

  1. 如果A沒有事務,則A和B的運行出現異常都不會回滾。
  2. 如果A有事務,A的method方法執行拋出異常,B.methodB和A.methodA都會回滾。
  3. 如果A有事務,B.method拋出異常,B.methodB和A.methodA都會回滾,如果A捕獲了B.method拋出的異常,則會出現異常Transactionrolled back because it has been marked as rollback-only。

 

MANDATORY

如果B的方法methodB()的事務傳播特性是: MANDATORY

表示當前方法必須在一個事務中運行,如果沒有事務,將拋出異常

  1. 如果A的methodA()方法沒有事務運行環境,則B的methodB()執行的時候會報如下異常:No existingtransaction found for transaction marked with propagation ‘mandatory’
  2. 如果A的MethodA()方法有事務並且執行過程中拋出異常,則A.methodA()和B.methodB()執行的操作被回滾;
  3. 如果A的methodA()方法有事務,則B.methodB()拋出異常時,A的methodA()和B.methodB()都會被回滾;如果A捕獲了B.method拋出的異常,則會出現異常Transaction rolled back because ithas been marked as rollback-only。

 

NESTED

如果B的方法methodB()的事務傳播特性是: NESTED

  1. 如果A的MethodA()不存在事務,則B的methodB()運行在一個新的事務中,B.method()拋出的異常,B.methodB()回滾,但A.methodA()不回滾;如果A.methodA()拋出異常,則A.methodA()和B.methodB()操作不回。
  2. 如果A的methodA()存在事務,則A的methodA()拋出異常,則A的methodA()和B的MethodB()都會被回滾;
  3. 如果A的MethodA()存在事務,則B的methodB()拋出異常,B.methodB()回滾,如果A不捕獲異常,則A.methodA()和B.methodB()都會回滾,如果A捕獲異常,則B.methodB()回滾,A不回滾;

 

NEVER

如果B的方法methodB()的事務傳播特性是: NEVER, 則如果A.methodA()方法存在事務,則會出現異常Existingtransaction found for transaction marked with propagation ‘never’。

 

REQUIRES_NEW

如果B的方法methodB()的事務傳播特性是: REQUIRES_NEW

表示事務傳播特性定義爲 REQUIRES_NEW 的方法需要運行在一個新的事務中。

  1. 如果A存在事務,A.methodA()拋出異常,A.methodA()的事務被回滾,但B.methodB()事務不受影響;如果B.methodB()拋出異常,A不捕獲的話,A.methodA()和B.methodB()的事務都會被回滾。如果A捕獲的話,A.methodA()的事務不受影響但B.methodB()的事務回滾。

 

NOT_SUPPORTED

如果B的方法methodB()的事務傳播特性是: NOT_SUPPORTED

表示該方法不應該在一個事務中運行。如果有一個事務正在運行,他將在運行期被掛起,直到這個事務提交或者回滾才恢復執行。

  1. 如果A.methodA()存在事務,如果B.methodB()拋出異常,A.methodA()不捕獲的話,A.methodA()的事務被回滾,而B.methodB()出現異常前數據庫操作不受影響。如果A.methodA()捕獲的話,則A.methodA()的事務不受影響,B.methodB()異常拋出前的數據操作不受影響。

 

實際場景中的七大事務傳播行爲的使用

  1. 在一個話費充值業務處理邏輯中,有如下圖所示操作
    在這裏插入圖片描述

業務需要扣款操作和創建訂單操作同成功或者失敗,因此,charger()和order()的事務不能相互獨立,需要包含在chargeHandle()的事務中;

通過以上需求,可以給charge()和order()的事務傳播行爲定義成:MANDATORY

只要charge()或者order()拋出異常整個chargeHandle()都一起回滾,即使chargeHandle()捕獲異常也沒用,不允許提交事務。

 

  1. 如果業務需求沒接受到一次請求到要記錄日誌到數據庫,如下圖:
    在這裏插入圖片描述

因爲log()的操作不管扣款和創建訂單成功與否都要生成日誌,並且日誌的操作成功與否不影響充值處理,所以log()方法的事務傳播行爲可以定義爲:REQUIRES_NEW

 

  1. 在訂單的售後處理中,更新完訂單金額後,需要自動統計銷售報表,如下圖所示:
    在這裏插入圖片描述

根據業務可知,售後是已經處理完訂單的充值請求後的功能,是對訂單的後續管理,統計報表report()方法耗時較長,因此,我們需要設置report()的事務傳播行爲爲:NEVER,表示不適合在有事務的操作中調用,因爲report()太耗時。

 

  1. 在銀行新增銀行卡業務中,需要執行兩個操作,一個是保存銀行卡信息,一個是登記新創建的銀行卡信息,其中登記銀行卡信息成功與否不影響銀行卡的創建。
    在這裏插入圖片描述
    由以上需求,我們可知對於regster()方法的事務傳播行爲,可以設置爲 NESTED,action()事務的回滾,regster()保存的信息就沒意義,也就需要跟着回滾,而regster()的回滾不影響action()事務;insert()的事務傳播行爲可以設置爲 REQUIRED, MANDATORY,即insert()回滾事務,action()的事務必須跟着回滾。

 

Reference

發佈了159 篇原創文章 · 獲贊 28 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章