[英]Spring Boot. @Transactional method calling a @Transactional(readonly=true) method
[英]Spring @Transactional(readOnly=true) revert the properties?
只是一個帶有Car-entity的簡單問題,其持久值字段值為紅色:
00 @Transactional public class MyBean{...
01 public void test(){
02 Car c = s.find(Car.class,1);
03 c.setColor("blue");
04 test1(c);
05 System.out.println(c.getColor());
06 }
07 @Transactional(readOnly=true)
08 public void test1(Car c){
09 c.setName("black");
10 }
11 }
假設,我們處於Spring ORM TX-Transactional-Annotation環境中,具有事務語義和事務范圍的持久性上下文。
什么將打印到控制台?
假設在調用同一實例的方法和NESTED事務傳播時啟用了事務語義:這取決於持久性上下文的范圍。
假設事務范圍內的持久性上下文: black
打印到控制台。 汽車實例是分離的,因為它是在只讀事務之外獲取的,並且沒有合並到只讀事務中。 在分離的實例上調用setter是安全的(就像對setColor("blue")
的調用一樣setColor("blue")
。
假定持久性上下文的擴展范圍: black
也被打印。 來自@Transactional
的javadoc
如果
當請求只讀事務時,無法解釋只讀提示的事務管理器不會引發異常。
從JPA 2.0規范的第2.4.1.2節“派生身份映射”開始:
提供者將與該關系相對應的嵌入式id屬性視為“只讀”,也就是說,在應用程序部分對它們的任何更新都不會傳播到數據庫。
但是,如果沒有引發異常,我不確定100%。 由於color屬性不是嵌入式ID,因此行為可能會有所不同。
如果可以通過代理獲得事務性語義,請參閱Adrian Shum的答案
我相信您在春季陷入了AOP的陷阱。
Spring中的事務是通過AOP實現的,而Spring中的AOP是通過圍繞實際目標的代理實現的。
您已經為MyBean注釋了@Transactional。 假設其他人正在調用MyBean.test()
實例,實際上它不是在直接與該對象“對話”。 有一個看起來與MyBean
完全一樣的代理,但是它創建事務,然后調用實際的MyBean.test()
,然后提交/回滾。
它是這樣的:
test() test()
[Caller] -------> [MyBean Proxy] ------> [MyBean]
然而,當你調用test1()
在test()
這實際上意味着this.test1()
這意味着你是直接調用為myBean的實例:
[MyBean Proxy] [MyBean] <--
| | test1(c)
---------
如果不通過MyBean Proxy
(負責完成事務技巧),實際上對test1()
調用與Transaction無關。 這只是一個簡單的方法。
所以你知道答案。
而且,即使您設法通過代理進行調用,也不會改變故事:
-> [MyBean Proxy] [MyBean]
test1(c) | |
-------------------------
這是因為傳遞給test1()
的Car
實例是在圍繞test()
的事務(即Hibernate會話)中檢索的,無論您在test1()
更改如何,您都不會對單獨創建的Hibernate會話進行任何操作在test1()
(如果您使用REQUIRED_NEW傳播)。 您只是在更改傳入對象的狀態。因此,調用test1(c)
仍然只是普通方法調用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.