查了一些資料,感覺並不能很清晰地表達出兩者的差異。所以打算自己總結一下。
先來看一下Spring中對於事務傳播性的幾種定義
PROPAGATION_REQUIRED -- 支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。
PROPAGATION_SUPPORTS -- 支持當前事務,如果當前沒有事務,就以非事務方式執行。
PROPAGATION_MANDATORY -- 支持當前事務,如果當前沒有事務,就拋出異常。
PROPAGATION_REQUIRES_NEW -- 新建事務,如果當前存在事務,把當前事務掛起。
PROPAGATION_NOT_SUPPORTED -- 以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
PROPAGATION_NEVER -- 以非事務方式執行,如果當前存在事務,則拋出異常。
PROPAGATION_NESTED -- 如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則進行與PROPAGATION_REQUIRED類似的操作。
前六個策略類似於EJB CMT,第七個(PROPAGATION_NESTED)是Spring所提供的一個特殊變量。
它要求事務管理器或者使用JDBC 3.0 Savepoint API提供嵌套事務行為(如Spring的DataSourceTransactionManager)
其中對於PROPAGATION_REQUIRES_NEW與PROPAGATION_NESTED的理解上有些類似,關鍵在於嵌套事務的理解。
來看一下網上大神對Juergen Hoeller表述的翻譯:
PROPAGATION_REQUIRES_NEW 啟動一個新的, 不依賴於環境的 "內部" 事務. 這個事務將被完全 commited 或 rolled back 而不依賴於外部事務, 它擁有自己的隔離范圍, 自己的鎖, 等等. 當內部事務開始執行時, 外部事務將被掛起, 內務事務結束時, 外部事務將繼續執行.
另一方面, PROPAGATION_NESTED 開始一個 "嵌套的" 事務, 它是已經存在事務的一個真正的子事務. 潛套事務開始執行時, 它將取得一個 savepoint. 如果這個嵌套事務失敗, 我們將回滾到此 savepoint. 潛套事務是外部事務的一部分, 只有外部事務結束后它才會被提交.
那么繪制一個表格來表現他們的差異
定義serviceA.methodA()以PROPAGATION_REQUIRED修飾;
定義serviceB.methodB()以表格中三種方式修飾;
methodA中調用methodB
異常狀態 PROPAGATION_REQUIRES_NEW
(兩個獨立事務) PROPAGATION_NESTED
(B的事務嵌套在A的事務中) PROPAGATION_REQUIRED
(同一個事務)
methodA拋異常
methodB正常 A回滾,B正常提交 A與B一起回滾 A與B一起回滾
methodA正常
methodB拋異常 1.如果A中捕獲B的異常,並沒有繼續向上拋異常,則B先回滾,A再正常提交;
2.如果A未捕獲B的異常,默認則會將B的異常向上拋,則B先回滾,A再回滾 B先回滾,A再正常提交 A與B一起回滾
methodA拋異常
methodB拋異常 B先回滾,A再回滾 A與B一起回滾 A與B一起回滾
methodA正常
methodB正常 B先提交,A再提交 A與B一起提交 A與B一起提交