Spring AOP事務管理

前兩篇寫了將Spring AOP應用與入參校驗和攔截方法進行日誌打印。本篇繼續應用三AOP應用於事務管理,順便把事務相關技術點統一Review一遍。(同樣基於case)

一、事務管理回顧

基於用戶支付成功後,創建支付訂單和支付記錄(兩個表的insert操作)來回顧事務管理。一共涉及3個方法

1)創建pay支付記錄邏輯 2)創建order支付訂單邏輯 3)組合方法:調用方法1、2,同步創建支付記錄和支付訂單

下表case默認(表1)

1、保證事務的均採用Required傳播屬性。

2、執行方法2先,1後,因爲都在1中寫的業務異常測試 

 

組合

Method1

Method2

執行結果

是否有事務

throw

12均成功,後拋出異常

 

throw

(業務異常)

2成功,1失敗

 

throw

(業務異常)

12均失敗

 

throw

12均失敗

1)分析:pay方法執行便立即提交commit,order同理。即便最後拋出異常,結果照樣正常入庫。

2)分析:同上,pay方法執行insert後立即執行commit請求,支付記錄入庫。而創建訂單邏輯報錯,創建失敗。

3)分析:儘管pay、order分別存在兩個事務,但當組合方法增加事務管理時,在執行pay事務後,並未執行commit請求,而是等着order執行成功後,一併commit。所以在order邏輯報錯後,事務回滾,表現就是pay和order均未創建。

4)分析:雖然12邏輯正常,組合方法最後設置拋出異常操作,故組合方法commit不執行,直接rollback

結論

1、當組合方法不添加事務管理時,無論單個方法是否包含事務,也無論報錯是原於單個方法中邏輯問題錯誤,還是兩個事務邏輯正常手動拋exeption的異常,背後都是先執行邏輯沒問題即刻提交commit,先執行先成功。組合方法無原子性。

2、當組合方法添加事務管理時,無論何種異常,都校驗到事務中所有操作均成功後,再提價組合事務commit操作,期間有一個失敗,則兩單個事務都入庫失敗。事務性無關單個方法事務,由組合方法事務保證原子性。

注意:

在case3時犯了一個很低級的錯誤,創建order內部異常時,由於代碼主動catch了異常,雖然是三個方法都設置了required事務,但由於catch了第一個方法異常,第二個方法仍會順序執行,最後一起commit組合方法的提交。所以表象看起來好像外層保證了原子性,但結果確實一張表失敗,一張表insert成功。

所以雖然是配置事務傳播屬性,但還跟代碼具體寫法相關。尤其是錯誤處理是否throw出來異常,還是catch住接下來的邏輯正常執行。這個得配合具體業務場景設計。

二、Spring事務傳播屬性

以下所有表格case默認:有事務表示case中均採用要驗證的傳播屬性,例如本case驗證Required,有則表示都設置成的傳播Required。非默認傳播屬性會特別標明。(表2)

1、Required 

 

組合

Method1

Method2

執行結果

是否有事務

無throw

12均成功

 

無throw

有(異常)

1成功,2失敗

 

有throw

無(異常)

12均失敗

 

有throw

有(異常)

12均失敗

1)1、2required加入到無事務中,自啓事務保證commit操作

2)由於組合方法無事務,當2事務異常,1仍執行成功,表明required所起的新事務,僅保證自身方法原子性。而不保證整個組合方法原子性(否則因爲2異常失敗,1也該失敗)。注意外部無事務保證。

3)組合方法有事務保證,被調起的12無事務,因2的異常,導致組合方法整個事務回滾,12均失敗。

4)組合有事務保證,1的required會新起事務,保證1執行成功。2由於異常,失敗。但1並未回滾,驗證了2)中的說法。

其實“表1”跟“表2”的case基本重合,都驗證了兩點。

1、當外部操作有事務時,被調起的方法若傳播屬性是Required,則直接加入到外部事務,即便先執行被調起方法也不會commit,而是由外部事務統一控制commit操作。即在執行被調用方法後,若外部事務執行異常,被調起的方法隨外部事務一起回滾。簡言之:原操作有事務,加入到原事務中,統一由原事務管理,失敗一併回滾。

2、當外部方法無事務保證時,被調起required事務傳播屬性的事務方法,若原操作無事務,required事務方法將自啓事務,但注意!!新起的事務僅保證自身即被調起方法的事務執行,成功即提交,原操作執行失敗,被調起事務也不會回滾。即表2中第二行case,1成功2失敗。

2、Surport

被調用爲sruppot傳播屬性時,如果原操作有保證事務,即以事務的形式運行,如果原操作無保證事務,那麼就以非事務的形式運行

 

組合

Method1

Method2

執行結果

是否有事務

無throw

無(異常)

1成功,2失敗

 

有throw

無(異常)

12均失敗

 

Surport throw

無(異常)

1成功,2失敗

1) 組合方法無事務保證,1以sup,則直接按無事務執行,1成功,2有異常失敗

2) 組合方法有事務保證(設置爲Required),1以sup,此時加入到組合方法事務中執行,當2異常時,1也回滾,兩個操作均失敗

3) 組合方法有事務保證(設置爲sup),因爲程序入口爲Test不保證事務,則組合方法便按無事務順序執行,1也是sup,同理。故1成功,2異常失敗。

3、MANDATORY

必須在一個事務中運行。也就是說,他只能被一個父事務調用。否則,他就要拋出異常

.

組合

Method1

Method2

執行結果

是否有事務

12均成功

結果並未拋異常!Check

4、REQUIRES_NEW

 

組合

Method1

Method2

執行結果

是否有事務

Re

有Re_New

12均成功

 

Re

有Re_New

無(異常)

1成功,2失敗

 

Re

有Re_New(異常)

1失敗,2成功

 1)組合方法事務級別爲REQUIRED,到1時,1會新起事務,組合方法事務掛起,等待1事務執行結果後,執行2,12均無異常,均成功。

2)此時若2異常,1在新事務中執行成功,由於2異常組合事務執行失敗回滾。而由於1在全新的事務中已commit,故1不會回滾,成功執行。

3)此時如果1異常,回滾。組合中catch住1的異常後,掛起的事務繼續執行2,2無異常,組合事務正常commit。

5、NESTED

NESTED與REQUIRES_NEW的區別是,REQUIRES_NEW另起一個事務,將會與他的父事務(組合方法中的事務)相互獨立,而Nested的事務和它的父事務是相依的,需要等父事務一塊提交的。如果父事務最後回滾,Nested也將回滾不執行commit操作。

6、NOT_SUPPORTED

被調用的方法採用該傳播屬性時表示我不支持事務。如遇源操作配置需保證事務處理,則原操作執行到調用方法時,事務會被掛起,等待被調用方法順序執行完畢後,再繼續執行原操作的事務。

 

組合

Method1

Method2

執行結果

是否有事務

Re

有(異常)

1異常被catch後,執行2成功

 

Re

有(異常)

無(異常)

1、2均打印異常,2由異常失敗

1)組合方法已有事務保證,執行到1時,事務掛起,1中異常(使用trycatch打印日誌),catch完後,2正常執行

2)當2中也發生異常時,2也失敗回滾。

7、NEVER

被調用的方法不能在事務中運行。如遇源操作配置需保證事務處理,則原操作執行到調用方法時,被調用方法直接拋異常。

 

組合

Method1

Method2

執行結果

是否有事務

Re throw

12均成功

1) 在required事務裏裏,1也沒有拋異常,不起作用(未完待續)

Spring AOP事務管理配置



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