![](/img/trans.png)
[英]Propagation.REQUIRES_NEW does not create a new transaction in Spring with JPA
[英]Spring Propagation.REQUIRES_NEW
在我的理解中,以下代碼中的newPrint
方法應該創建一個新事務,但顯然它打印出與oldPrint
方法中使用的相同的事務狀態對象。 我從另一個班級打電話給oldPrint。 是因為使用this
來調用newPrint嗎? 如果是,那么什么時候會創建新的交易? 如果我從另一個類調用這兩個方法,則無論如何都會創建兩個單獨的事務,因為在類級別使用了@Transactional
。
@Transactional
public class Unsubcriber {
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void newPrint() {
System.out.println(TransactionAspectSupport.currentTransactionStatus());
}
public void oldPrint() {
System.out.println(TransactionAspectSupport.currentTransactionStatus());
newPrint();
}
輸出:
org.springframework.transaction.support.DefaultTransactionStatus@3bacd0e7
org.springframework.transaction.support.DefaultTransactionStatus@3bacd0e7
當Propagation.REQUIRES_NEW
工作時會出現什么情況?
假設geoand的編輯說明是正確的,那么您的問題的答案是Spring使用AOP代理來應用事務限制。 因此,當來自外部的調用進入您的Unsubscriber時,這將會起作用,然后可以截取它並且可以應用事務邊界。 如果你是在課堂上調用它,正如你所說,使用'this',那么就沒有代理可以完成,因此你的@Transactional不會發揮作用。
這里有一些值得一提的@Transactional規則
1. @ Transactional注釋僅適用於公共方法。 如果你有一個帶有這個注釋的私有或受保護的方法,那么Spring AOP沒有(簡單的)方法來查看注釋。 嘗試找到它們並不瘋狂,因此請確保所有帶注釋的方法都是公開的。
2.只有在通過Spring代理調用正確注釋(見上文)方法時才會創建事務邊界。 這意味着您需要直接通過@Autowired bean調用帶注釋的方法,否則事務將永遠不會啟動。 如果在未注釋的@Autowired bean上調用一個方法,該方法本身會調用一個注釋的公共方法,那么您的注釋就會被忽略。 這是因為Spring AOP僅在首次輸入@Autowired代碼時檢查注釋。
來源 - http://blog.timmattison.com/archives/2012/04/19/tips-for-debugging-springs-transactional-annotation/
你所看到的是對Spring AOP的一種誤解。
由於newPrint()
是從同一個類內的方法調用的,因此不會觸發任何建議,因此不會對事務進行處理。
如果您在類外部調用newPrint()
方法,則無論調用者是否已參與事務,都將創建一個新事務。
由於您在類上使用了@Transactional
,因此每個方法都是默認的@Transactional
設置,這就是您實際擁有事務的原因。
看一下Spring參考文檔的這一部分,詳細討論AOP如何在Spring中運行。
讓您的代碼按預期運行的完全破解如下:
((Unsubcriber ) AopContext.currentProxy()).newPrint();
在這個 SO帖子中提到了這個解決方案。
從類中調用方法(使用this
)意味着它不會通過Spring的代理對象中包含的事務初始化。 由於this
關鍵字是指向原始對象實例的指針,而不是事務感知的增強型Spring對象。
注釋將在以下場景中按預期工作:
object1.oldPrint();
object1.newPrint();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.