Spring 事務管理

在 SPRING 中一共定義了六種事務傳播屬性
 
PROPAGATION_REQUIRED -- 支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。 
PROPAGATION_SUPPORTS -- 支持當前事務,如果當前沒有事務,就以非事務方式執行。 
PROPAGATION_MANDATORY -- 支持當前事務,如果當前沒有事務,就拋出異常。 
PROPAGATION_REQUIRES_NEW -- 新建事務,如果當前存在事務,把當前事務掛起。 
PROPAGATION_NOT_SUPPORTED -- 以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。 
PROPAGATION_NEVER -- 以非事務方式執行,如果當前存在事務,則拋出異常。 
PROPAGATION_NESTED -- 如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則進行與PROPAGATION_REQUIRED類似的操作。 
 
最容易弄混淆的其實是PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 
 
PROPAGATION_REQUIRES_NEW 啓動一個新的, 不依賴於環境的 "內部" 事務. 這個事務將被完全 
commited 或 rolled back 而不依賴於外部事務,它擁有自己的隔離範圍, 自己的鎖, 等等. 
當內部事務開始執行時, 外部事務將被掛起, 內務事務結束時, 外部事務將繼續執行. 
PROPAGATION_REQUIRES_NEW常用於日誌記錄,或者交易失敗仍需要留痕
 
另一方面, PROPAGATION_NESTED 開始一個 "嵌套的" 事務,  它是已經存在事務的一個真正
的子事務. 潛套事務開始執行時,  它將取得一個 savepoint.
如果這個嵌套事務失敗, 我們將回滾到此 savepoint. 潛套事務是外部事務的一部分,
 只有外部事務結束後它纔會被提交. 
由此可見, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大區別在於, 
PROPAGATION_REQUIRES_NEW 完全是一個新的事務, 而 PROPAGATION_NESTED 
則是外部事務的子事務, 如果外部事務 commit, 潛套事務也會被 commit,
 這個規則同樣適用於 roll back. 
 
幾個例子理解REQUIRED、REQUIRES_NEW、NESTED 的使用注意事項(TRY...CATCH配合使用)
 
1、REQUIRED的使用注意項
 
1.1 REQUIRED保證其處理過程同一個事務,如果調用的同一個類的配置的REQUIRED的方法,且此方法存在TRY CATCH
代碼塊, 如果此代碼塊出現異常,程序可以繼續執行。
 
1.2 但如果調用的其他類的配置REQUIRED方法,且TRY CATCH住,則全部的提交全部回滾,且報出異常:
Transaction rolled back because it has been marked as rollback-only
因爲事務報出異常後要全部回滾,包括父類的調用。
 
1.3 如果service中包含多個dao的方法,其都屬於同一個事務,其中報錯全部回滾,try catch住不影響程序代碼的繼續執行.
 
 
class A{
   //PROPAGATION_REQUIRED
     void methodA() {
        try{
          methodB(); //可以繼續執行,因爲是同一個類
        }catch(Exception ex){
          ex.printStrace();
        }
        
        try{
          methodC(); //報錯Transaction rolled back because it has been marked as rollback-only
                     //因爲回滾整個事務,不能用try catch住.當然通過不會try catch一個事務的部分代碼
        }catch(Exception ex){
          ex.printStrace();
        }
   }
   
   //PROPAGATION_REQUIRED
   void methodB() {
   
   }
}
 
class B{
   
   //PROPAGATION_REQUIRED
   void methodC() {
   
   }
}
 
2、NESTED的具體用途如下:
在此方法出現異常時,通過TRY CATCH 代碼塊包含住, 繼續往下執行或者執行CATCH中的處理.
此點REUQIRED做不到, REQUIRED_NEW能做到, 但它是單獨的事務,不與父類一塊提交的。
 
ServiceA { 
/**
 
* 事務屬性配置爲 PROPAGATION_REQUIRED
 
*/
 
void methodA() {
 
try {
 
//savepoint
 
ServiceB.methodB(); //PROPAGATION_NESTED 級別
 
} catch (SomeException) {
 
// 執行其他業務, 如 ServiceC.methodC();
}}}

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