2010-06-25 986 views

回答

83

http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html

Spring團隊的建議是,你只標註具體的類與@Transactional註解,而不是註釋的接口。您當然可以將@Transactional註釋放置在一個接口(或一個接口方法)上,但這隻會在您使用基於接口的代理服務器時發揮預期效果。註釋不是繼承這一事實意味着,如果您使用的是基於類的代理,那麼事務設置將不會被基於類的代理基礎架構識別,並且該對象將不會被包裝在事務代理中(這將是決定性的)。所以,請務必採納Spring團隊的建議,並僅使用@Transactional註釋來註釋具體類(以及具體類的方法)。

注意:由於此機制基於代理,因此只有通過代理進入的「外部」方法調用纔會被攔截。這意味着即使被調用的方法被標記爲@Transactional,「自調用」(即調用目標對象的某個其他方法的目標對象內的方法)也不會導致實際的事務在運行時發生!

(着重號的第一句話,其他重點從原來的。)

+0

大+1順便說一句,我冒昧地把報價做成了一個引號,所以人們不會感到困惑,並且將原文中的斜體等加回來。 – 2010-06-26 06:26:21

+0

@ T.J。 Crowder - 驚人的其他答案如何改變。 thx,NP – 2010-06-26 15:02:17

+0

我已經在Spring docu中閱讀過這條語句,但我仍然不明白爲什麼_transaction設置不會被基於類的代理架構_識別出來?我個人認爲,這只是Spring實現的限制,而不是底層代理基礎架構的問題。 – 2010-09-26 12:53:38

0

把它的接口是罰款,只要有關TX數據的IFC照顧到所有的可預見的實施者(交易不是問題只是數據庫處理)。如果該方法不關心TX(但是你需要把它放在Hibernate或其他地方),把它放在impl上。

而且,它可能是一個好一點的地方@Transactional上的接口中的方法:

public interface FooService { 
    @Transactional(readOnly = true) 
    void doSmth(); 
} 
7

你可以把它們的界面上,但被警告說,交易可能不會最終在某些情況下發生的。看到春天文檔的Secion 10.5.6第二提示:

春建議您只用@Transactional註解註釋具體的類(和具體類的方法),而不是註釋的接口。您當然可以將@Transactional註釋放在一個接口(或一個接口方法)上,但是這隻在您使用基於接口的代理時纔會如您所期望的那樣工作。 Java註釋不是從接口繼承的事實意味着,如果您使用的是基於類的代理(proxy-target-class =「true」)或基於織造的方面(mode =「aspectj」),則事務設置爲沒有被代理和編織基礎架構認可,並且該對象不會被封裝在事務代理中,這肯定會很糟糕。

我會建議把它們放在執行中,因爲這個原因。

另外,對我來說,事務看起來像一個實現細節,所以他們應該在實現類。想象一下,使用不需要事務處理的記錄或測試實現(模擬)的包裝實現。

6

Spring的recommendation是你標註具體實現,而不是一個接口。在界面上使用註釋並不正確,只能濫用該功能並無意中繞過@Transaction聲明。

如果你已經在接口中標記了事務性的東西,然後在Spring的其他地方引用其實現類之一,那麼彈簧創建的對象將不會遵守@Transactional註釋並不是很明顯。

在實踐中,它看起來是這樣的:

public class MyClass implements MyInterface { 

    private int x; 

    public void doSomethingNonTx() {} 

    @Transactional 
    public void toSomethingTx() {} 

} 
2

關於具體的類:

我更喜歡在3個部分構建一個解決方案:API,Im請求和Web(如果需要)。我盡我所能通過最小化依賴關係儘可能地將API保持爲輕/簡單/ POJO。如果您在分佈式/集成環境中播放它,您必須分享這些API,這一點尤其重要。

把@Transactional要求API部分中的Spring庫,恕我直言,這是不有效的。所以我更願意將它添加到正在運行事務的實現中。

相關問題