spring事務的配置以及事務傳播機制和相關的測試demo

在實際項目中爲了保證數據的一致性,事務是非常重要的,而spring對事務的支持方便了我們對事務相關操作的開發.

 

事務的配置方式


spring支持編程式事務管理和聲明式事務管理兩種方式。
   編程式事務管理使用TransactionTemplate或者直接使用底層的PlatformTransactionManager。對於編程式事務管理,spring推薦使用TransactionTemplate。
  聲明式事務管理建立在AOP之上的。其本質是對方法前後進行攔截,然後在目標方法開始之前創建或者加入一個事務,在執行完目標方法之後根據執行情況提交或者回滾事務。
  聲明式事務管理也有兩種常用的方式,一種是基於tx和aop名字空間的xml配置文件,另一種就是基於@Transactional註解。顯然基於註解的方式更簡單易用,更清爽。

 

 

事務傳播機制

標題
名稱 作用
REQUIRED
支持當前事務,如果當前沒有事務,則新建事務;
如果當前存在事務,則加入當前事務,合併成一個事務

 

SUPPORTS
如果當前存在事務,則加入事務。 
如果當前不存在事務,則以非事務方式運行,這個和不寫沒區別
REQUIRES_NEW
新建事務,如果當前存在事務,則把當前事務掛起
這個方法會獨立提交事務,不受調用者的事務影響,父級異常,它也是正常提交
NOT_SUPPORTED
該傳播機制不支持事務,如果外層存在事務則掛起,執行完當前代碼,則恢復外層事務,無論是否異常都不會回滾當前的代碼
NEVER 該傳播機制不支持外層事務,即如果外層有事務就拋出異常
MANDATORY 與NEVER相反,如果外層沒有事務,則拋出異常
NESTED

如果當前存在事務,它將會成爲父級事務的一個子事務,方法結束後並沒有提交,只有等父事務結束才提交
如果當前沒有事務,則新建事務
如果它異常,父級可以捕獲它的異常而不進行回滾,正常提交(這點驗證失敗)
但如果父級異常,它必然回滾,這就是和 REQUIRES_NEW 的區別

 

 

 

 

 

 

 

 

 

 

 

 

相關的測試

1、REQUIRED

a、如果inserA(有事務)當inserA調用inserB(無事務)時,inserB的是否有事務?

運行結果如下:

  結果:如果inserA(有事務)當inserA調用inserB(無事務)時,他會給inserB創建一個事務,並合併成一個事務.

b、如果當inserA(無事務)調用insertB(有事務)時,那麼insertB的事務會執行嗎?

運行結果:

結果:如果當inserA(無事務)調用insertB(有事務)時,insertB的事務是不會執行的事務回滾的,即insertB的事務不起作用

結論:

支持當前事務,如果當前沒有事務,則新建事務;
如果當前存在事務,則加入當前事務,合併成一個事務

 

 

2、SUPPORTS

1、如果當inserA(required)調用insertB(supports)時,insertB的事務會回滾嗎?

執行結果:

結果:如果當inserA(required)調用insertB(supports)時,insertB的事務會回滾.

b、如果當inserA(無事務)調用insertB(supports)時,insertB的事務會回滾嗎?

結果如下:

結論:如果當inserA(無事務)調用insertB(supports)時,insertB的事務不會回滾

 

c、如果當inserA(supports)調用insertB(supports)時,insertB的事務會回滾嗎?

結果如下:

結果:如果當inserA(supports)調用insertB(supports)時,insertB的事務不會回滾

 

d、如果當inserA(supports)調用insertB(required)時,insertB的事務會回滾嗎?

結果如下:

結果:如果當inserA(supports)調用insertB(supports)時,insertB的事務不會回滾

 

結論

如果當前存在事務,則加入事務。
如果當前不存在事務,則以非事務方式運行,這個和不寫沒區別

 

REQUIRES_NEW

a、如果當insertLog(無事務)調用insertLogB(事務REQUIRES_NEW)時,會怎樣?

結果如下:

結果:

如果當insertLog(無事務)調用insertLogB(事務REQUIRES_NEW)時,insertLogB創建了事務,並且insertLogB回滾事務,只有user的數據插入成功.

 

b、如果當insertLog(事務REQUIRES_NEW)調用insertLogB(無事務)時,會怎樣?

結果如下:

結果:如果當insertLog(事務REQUIRES_NEW)調用insertLogB(無事務)時,insertLog創建了事務,並且insertLogB也創建了事務,併合並的了事務,且因報錯,而回滾數據了.

 

c、如果當insertLog(事務REQUIRES)調用insertLogB(事務REQUIRES_NEW)時,會怎樣?

結果如下:

結果:如果當insertLog(事務REQUIRES)調用insertLogB(事務REQUIRES_NEW)時,insertLogB獨立提交事務,不受調用者的事務影響,父級異常,它也是正常提交

 

總結

新建事務,如果當前存在事務,則把當前事務掛起

這個方法會獨立提交事務,不受調用者的事務影響,父級異常,它也是正常提交

 

NOT_SUPPORTED

a、如果當insertLog(無事務)調用insertLogB(無事務NOT_SUPPORTED)時,會怎樣?

結果如下:

結果:  如果當insertLog(無事務)調用insertLogB(無事務NOT_SUPPORTED)時,以非事務方式運行

 

b、如果當insertLog(事務)調用insertLogB(無事務NOT_SUPPORTED)時,會怎樣?

結果如下:

結果:如果當前存在事務,則把當前事務掛起

總結

以非事務方式運行

如果當前存在事務,則把當前事務掛起

 

NEVER

a、如果當insertLog(無事務)調用insertLogB(事務NEVER)時,會怎樣?

結果如下:

結果:如果當insertLog(無事務)調用insertLogB(事務NEVER)時,會正常執行,

 

b、如果當insertLog(有事務)調用insertLogB(事務NEVER)時,會怎樣?

結果如下:

結果:如果當insertLog(required)調用insertLogB(事務NEVER)時,使用事務NEVER會報異常,並且會回滾數據.

總結

該傳播機制不支持外層事務,即如果外層有事務就拋出異常

 

 

MANDATORY

a、如果當insertLog(有事務)調用insertLogB(事務MANDATORY)時,會怎樣?

結果如下:

結果:正常執行

 

 

b、如果當insertLog(無事務)調用insertLogB(事務MANDATORY)時,會怎樣?

結果如下:

結果:如果當insertLog(無事務)調用insertLogB(事務MANDATORY)時 ,會報異常

結論:

與NEVER相反,如果外層沒有事務,則拋出異常

 

NESTED

  

a、如果當insertLog(無事務)調用insertLogB(事務NESTED)時,會怎樣?

結果如下:

結果:如果當insertLog(無事務)調用insertLogB(事務NESTED)時,如果當前沒有事務,則新建事務,並且insertLogB回滾了數據

b、如果當insertLog(有事務,有異常)調用insertLogB(事務NESTED)時,會怎樣?

結果如下:

結果: 如果當insertLog(有事務)調用insertLogB(事務NESTED)時,說明數據回滾了,即自方法正常,父方法有異常的情況下,全部回滾

c、如果當insertLog(有事務)調用insertLogB(事務NESTED,有異常)時,會怎樣?

 

結果如下:

結果:如果當insertLog(有事務)調用insertLogB(事務NESTED,有異常)時,數據全部回滾.

 

總結

如果當前存在事務,它將會成爲父級事務的一個子事務,方法結束後並沒有提交,只有等父事務結束才提交
如果當前沒有事務,則新建事務
如果它異常,父級可以捕獲它的異常而不進行回滾,正常提交
但如果父級異常,它必然回滾,這就是和 REQUIRES_NEW 的區別

 

測試源碼在GitHub上spring-framework下mySpring項目的com.lquan.trans包下(歡迎大家多多給意見,謝謝)

 

可參考,方便記憶

https://www.cnblogs.com/libin2015/p/12556163.html

 

 

 

 

 

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