spring 中的事務 - Transactional 詳細解析

分類

聲明式事務

建立在aop之上的,我們常用的事務

聲明式事務是編程式事務 + AOP 技術包裝


編程式事務

基於pojo的事務,我們用的較少

我們需要在代碼中顯式調用 beginTransaction()、commit()、rollback() 等事務管理相關的方法,這就是編程式事務管理。



隔離級別 - isolation


類似於數據庫中的事務隔離級別

通過設置Transactional的屬性isolation 來設置


1、Isolation.DEFAULT

事務默認的隔離級別,使用數據庫默認的隔離級別。


2、Isolation.READ_UNCOMMITTED

這是事務最低的隔離級別,它充許別外一個事務可以看到這個事務未提交的數據。

這種隔離級別會產生髒讀,不可重複讀和幻讀。


3、Isolation.READ_COMMITTED

保證一個事務修改的數據提交後才能被另外一個事務讀取。

另外一個事務不能讀取該事務未提交的數據。這種事務隔離級別可以避免髒讀出現,但是可能會出現不可重複讀和幻讀。


4、Isolation.REPEATABLE_READ

這種事務隔離級別可以防止髒讀,不可重複讀。但是可能出現幻讀。


5、Isolation.SERIALIZABLE

這是花費最高代價但是最可靠的事務隔離級別。事務被處理爲順序執行。除了防止髒讀,不可重複讀外,還避免了幻讀。



傳播行爲 - propagation

在SpringBoot中通過Transactional的propagation屬性來指定

7種傳播行爲,常用的爲前兩種


1、REQUIRED

默認,如果調用者沒有事務,則開啓事務,如果調用者有事務,則加入該事務

例如:a調用b,如果a有事務,b回滾了,a也會回滾


2、REQUIRES_NEW

開啓一個自己獨立的事務,調用者有事務也會先掛起

例如:a調用b,a事務回滾,b不會回滾,但是b異常回滾了,a也會回滾


3、SUPPORTS

如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行。

用於非核心業務,即使報錯也不需要回滾的代碼(看調用者的事務必要性)。

例如:a調用b,a存在事務,b加入;如果a沒有事務,b也以非事務方式執行。


4、NOT_SUPPORTED

以非事務方式運行,如果當前存在事務,則把當前事務掛起。

它可以幫助將事務極可能的縮小,因爲一個事務越大,它存在的風險也就越多,所以在處理事務的過程中,要保證儘可能的縮小範圍。

例如:a調用b,b中以非事物狀態運行,b報錯了,a事務也不會回滾


5、NEVER

以非事務方式運行,如果當前存在事務,則拋出拋出Runtime 異常,強制停止執行。

例如:a調用b,如果a有事務,直接拋出Runtime異常


6、MANDATORY

如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。也就是說,MANDATORY 要求上下文中必須要存在事務,否則就會拋出異常。

例如:a調用b,如果a沒有事務,b直接拋異常


7、NESTED

如果當前存在事務,則創建一個事務作爲當前事務的嵌套事務(子事務)來運行;如果當前沒有事務,則該取值等價於 REQUIRED

例如:a調用b,a回滾,b也跟着你回滾,但是b回滾,不會影響a和其他子事務



其他屬性

1、timeout

事務的超時時間,單位爲秒


2、readOnly

該屬性用於設置當前事務是否爲只讀事務,設置爲true表示只讀,false則表示可讀寫,默認值爲false

如果一個事務只涉及到只讀,可以設置爲true


3、rollbackFor 屬性

用於指定能夠觸發事務回滾的異常類型,可以指定多個異常類型

默認是在RuntimeExceptionError上回滾


4、noRollbackFor

拋出指定的異常類型,不回滾事務,也可以指定多個異常類型



失效情況

我們討論的是基於默認的事務傳播級別:REQUIRED

1、mysql的數據庫引擎是MyISAM

2、註解加的方法的訪問修飾符不是public

3、事務中異常被捕捉處理,沒有拋出

4、同類方法調用,a調用b方法,b方法事務失效

爲什麼此時事務失效?

其實原因很簡單,Spring在掃描Bean的時候會自動爲標註了@Transactional註解的類生成一個代理類(proxy),當有註解的方法被調用的時候,實際上是代理類調用的,代理類在調用之前會開啓事務,執行事務的操作,但是同類中的方法互相調用,相當於this.B(),此時的B方法並非是代理類調用,而是直接通過原有的Bean直接調用,所以註解會失效。

5、如果使用了Spring + MVC,則 context:component-scan 重複掃描問題可能會引起事務失效



站在巨人的肩膀上學習和整理,如有紕漏,歡迎大家指出交流!

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