2011-05-18 78 views
2

我有一個方法調用鏈,其中A調用B調用C調用D.A和D具有@Transactional註釋。但B和C沒有。這種情況下交易界限的範圍是什麼。是B和C部分的交易嗎?Spring事務邊界擴展

+0

a)A,B,C,D在同一班級嗎? b)您是否使用JDK代理(默認),CGLib(proxy-target-class = true)或AspectJ(mode = aspectj) – 2011-05-18 14:54:19

+0

否,它們處於不同的類別中。我使用默認配置的Spring。 – meisam 2011-05-18 16:02:36

+0

re默認配置:這取決於你的類是否支持接口。他們? – 2011-05-18 17:12:06

回答

5

默認情況下,A,B,C & D在同一事務中工作。事務的默認傳播級別是TX_REQUIRED,意思是如果一個新事務不存在(A開始一個,B,C,D參與),則開始一個新事務。

D可以通過將傳播級別設置爲TX_REQUIRES_NEW(如果您的環境支持它)來啓動新事務。在這種情況下,當D完成時,恢復暫停的事務。提交D不會影響事務A的結果。回滾A不會回滾D(已提交),因爲它們是單獨的事務。

此外,很多開發人員忘記只有公有方法可能被標記爲@Transactional,因爲Spring使用代理來管理事務(私有/受保護的方法在「this」上被調用 - 因此代理沒有機會去做它的魔法)。如果使用字節碼注入而不是代理,這並不是必需的。

如果你想了解更多關於交易設計模式,我強烈建議下面的電子書(免費! - 需要註冊):http://www.infoq.com/minibooks/JTDS。這是一個非常簡單的閱讀。

3

這取決於@Transactional註釋的propagation參數。

默認情況下,A內發生的所有事情都是單個事務的一部分 - 包括直接或間接調用的所有方法。

其他傳播模式將允許D暫停當前事務並自行啓動,在嵌套事務中執行,或拋出異常,因爲它並不意味着在現有事務中使用。

+0

我的意思是,當B和C沒有任何註釋時,是否應用默認的「需要」或...? – meisam 2011-05-18 14:58:43

+0

在事務設計中有一條「簡單」的經驗規則:啓動事務的對象/方法也負責確定結果(提交/回滾)。在你的情況下,A在A完成之前調用B - > C - > D,因此它們參與A的事務。由於B&C沒有註釋,因此它們不是交易意識。 D有點不同,默認情況下它會檢查是否有活動事務並參與。否則,它會開始一個新的。 – 2011-05-18 15:06:33

+1

@meisam:你看錯了方向。事務不知道方法,而只知道如何訪問事務感知資源,如數據庫。該註釋使A在執行事務之前啓動一個事務,之後每次訪問該線程中發生的事務感知資源(無論在哪種方法中)都是事務的一部分,直到A完成並提交或回退事務爲止。 – 2011-05-18 15:34:07

2

獨立的會發生什麼:

,如果這個問題甚至出現時,你可能有嚴重的設計問題。

在95%的情況下,事務劃分應該在應用程序的入口點進行,即在內部調用所有其他代碼的服務方法中。

唯一有效的情況下,我可以想到@Transactional方法調用另一個方法時,內部方法有傳播REQUIRES_NEW。如果不是這樣:重構您的設計,以便您的代碼只通過一個@Transactional註釋。

+0

我同意100%。內部方法可能需要@Transactional的另一種情況是檢查事務處於活動狀態(TRX_MANDATORY):如果未找到任何異常,則會引發異常。我們在DAO上執行此操作,因此您無法直接調用DAO,必須通過服務層(REQUIRES_NEW | REQUIRED)。 – 2011-05-18 15:09:29

+0

@Patrick我同意TRX_MANDATORY,這是唯一的TX註釋是有道理的一個DAO – 2011-05-18 15:12:04

+0

我不同意。如果C向隊列添加任務會怎麼樣?那個任務實際上執行D?在這種情況下,您不能在同一個事務中使用它們,並且您需要爲D使用REQUIRES_NEW,儘管這不像調用DAO方法那樣直接。 – meisam 2011-05-18 16:06:39