巢狀事務被提交的情況

2021-09-20 03:06:28 字數 1241 閱讀 2561

class servicea

邏輯 a2

邏輯 a3

}}class serviceb

}class servicec

}

現狀

servicea.method_a本身有事務,裡面呼叫serviceb.method_b,另起新事務。 執行邏輯a3時,更新表a2失敗。只回滾了serviceb裡面的更新表b,無法回滾更新表a1及儲存過程c。

目的

業務場景中的目的是,無論邏輯a3報什麼錯,都不能影響邏輯a1、a2

只要在邏輯a2後,手動提交事務即可【已解決】

疑問

邏輯a1為什麼會被儲存過程一起commit了,無法再回滾?

分析

spring事務管理是通過jdk動態**的方式進行實現的(另一種是使用cglib動態**實現的),也正是因為動態**的特性造成了上述方法中的新開事務失效!只有**物件proxy直接呼叫的那個方法才是真正的走**的,巢狀的方法實際上就是 直接把巢狀的**移動到**的方法裡面。所以,巢狀的事務都不能生效。故呼叫servicec.method_c其實沒有產生新事務,儲存過程在顯示執行commit時,直接提交了servicea.method_a的事務,後面無法再回滾。

只有來自外部的方法呼叫才會被aop**捕捉,類內部方法呼叫類內部的其他方法,子方法並會不引起事務行為,即使被呼叫的方法上使用有@transactional註解。

類內部方法呼叫內部的其他方法,被呼叫的方法體中如果有try catch,則catch中必須用throw new exception(),否則即使主方法上加上@transactional註解,如果被呼叫的子方法出錯也不會丟擲異常,不會引起事務起作用。

解決方案

參考驗證效果

專案中本來邏輯b的儲存過程就是在另乙個service類中實現的,屬於呼叫外部方法

獲取**物件呼叫內嵌方法【報錯aspectj-autoproxy 迴圈依賴報錯has been injected into other beans】

【多個動態**導致迴圈依賴報錯問題解決】

從上下文物件獲取物件呼叫 【我的專案中無效】    

結論

疑問暫未解決,待後續完善。

事務巢狀的問題

使用 transactionscope 的過程中,如果存在巢狀事務,比如,bll 層使用了事務,而所呼叫的 dal 內方法也使用了事務的話。假設我們吃掉了 dal 的異常,那麼,外部事務會不會成功?測試 如下 using var ts new transactionscope catch ts.co...

事務巢狀的問題

使用 transactionscope 的過程中,如果存在巢狀事務,比如,bll 層使用了事務,而所呼叫的 dal 內方法也使用了事務的話。假設我們吃掉了 dal 的異常,那麼,外部事務會不會成功?測試 如下 using var ts new transactionscope catch ts.co...

事務的開啟和提交

顯然,這個程式非常簡單,我們非常自信地編譯它,但是,出乎意料的結果使我們的成就感頓時煙消雲散 error cs1501 過載 sqltransaction 方法未獲取 0 引數 是什麼原因呢?注意到我們初始化的 sqltransaction mytran new sqltransaction 顯然,...