SPRING 事務控制 (PROPAGATION_NESTED)
SPRING 事務控制 (PROPAGATION_NESTED)
2017年07月27日 16:56:13 OkidoGreen 閱讀數:2587更多
個人分類: 事務
-
在 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();
-
}}}