摘要:情況一方法方法強制拋一個異常情況一就是這樣,方法里面順序調用兩個方法,方法不加事務注解,方法加了事務注解。如果不了解事務的傳播性,可能會回答成功插入,插入失敗但是實際情況卻是均插入成功了。
平時我們使用spring框架,不論是springmvcv還是springboot,springCloud,絕大多數情況我們都是在方法,或者直接在類上面加一個@Transactional,將事務交給spring替我們去管理,然后并沒有具體分析一些情況,今天結合幾個例子,結合源代碼,使用偽代碼解釋一波。
1.情況一
service(){ //方法A methodA(){ insertA(); } //方法B @Transactional methodB(){ insertB(); throw new RunTimeException("強制拋一個異常"); } public void static main(String[] args){ methodA(); methodB(); } }
情況一就是這樣,main方法里面順序調用AB兩個方法,A方法不加事務注解,B方法加了事務注解。如果不了解@Transactional 事務的傳播性,可能會回答:A成功插入,B插入失敗,但是實際情況卻是A,B均插入成功了。到底是什么原因呢?這里先簡單介紹一下事務的6個傳播屬性:
PROPAGATION_REQUIRED : 支持當前事務,如果當前沒有事務,就新建一個事務,這也是最常見的
PROPAGATION_SUPPORTS : 支持當前事務,如果當前沒有事務,就以非事務的方式執行
PROPAGATION_MANDATORY: 支持當前事務,如果當前沒有事務,就拋異常
PROPAGATION_REQUIRES_NEW:新建事務,如果當前事務存在,就把當前事務掛起
PROPAGATION_NOT_SUPPORTED:以非事務的方式執行,如果存在當前事務,就把當前事務掛起
PROPAGATION_NEVER: 以非事務的方式執行,如果當前存在事務,就拋異常
PROPAGATION_NESTED:如果存在當前事務,則在嵌套事務內執行,如果當前沒有事務,則新建一個事務
前六個策略類似于EJB CMT,第七個(PROPAGATION_NESTED)是Spring所提供的一個特殊變量。
研究源碼,調試程序可以看到:
A沒有事務管理,則線程內的connection 有個autoCommit = true
B得到事務的時候,由于事務的傳播性依然生效, 得到的還是A方法的commit,其autoCommit = true,故而逐條sql進行提交,即A,B都會插入
下面我們來分析情況二:
serviceA(){ methodA(){ insertA(); } } serviceB(){ @Transactional methodB(){ insertB(); throw new RuntimeExcption("強制拋出的異常"); } } serviceC(){ @Autowired private ServiceA serviceA; @Autowired private ServiceB serviceB; public void staic main(String[] args){ serviceA.methodA(); serviceB.methodB(); } }
情況二的主要代碼和情況一一樣,都是要調用methodA和methodB,但是結果卻不同,情況二的正確結果是指揮插入A,而B會回滾,這是為什么呢?同樣是在B方法上面加了事務注解....
其實大家都知道,spring的事務是交由cglib動態代理的,而動態代理對象產生的時機就非常重要了。再回到本例子:
A:在同一個service內部,事務之間嵌套調用,普通方法和事務方法之間的嵌套調用,都不會開啟新的事務(因為shpring使用的是動態代理的方式來控制的事務,而動態代理最終都是要調用原始對象的,而原始對象在調用方法時,已存在代理對象,是不會再觸發代理了!)
B:兩個方法在不同的service里(即不同的對象,即代理對象也不是同一個),在ServiceC中,使用注入的方式將serviceA和serviceB注入,這樣即使A沒有使用事務,B也有自己的代理,會根據PROPAGATION_REQUIRED 而生成新的事務.
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/73590.html
摘要:由于的限制,無法替換被代理類已經被載入的字節碼,只能生成并載入一個新的子類作為代理類,被代理類的字節碼依然存在于中。區別于前兩者,是一種靜態代理的實現,即在編譯時或者載入類時直接修改被代理類文件的字節碼,而非運行時實時生成代理。 現象描述 上周同事發現其基于mySql實現的分布式鎖的線上代碼存在問題,代碼簡化如下: @Controller class XService { @A...
摘要:引言對于追求數據強一致性的系統,事務扮演者十分重要的角色最近在項目中遇到一個事務失效的問題,在此分享給大家。情景回放問題分析初步分析這是事務獲取鎖超時導致的錯誤,奇怪的是拋出異常但是事務沒有回滾。唯一的解釋是事務失效了。 引言 對于追求數據強一致性的系統,事務扮演者十分重要的角色.最近在項目中遇到一個事務失效的問題,在此分享給大家。 情景回放 ### Cause: com.mysql....
摘要:和事務的關系關系型數據庫某些消息隊列等產品或中間件稱為事務性資源,因為它們本身支持事務,也能夠處理事務。事務的傳播特性,,,,,,強制要求要有一個物理事務。外圍事務不會被內部事務的回滾狀態影響。不支持當前事務。 Spring和事務的關系 關系型數據庫、某些消息隊列等產品或中間件稱為事務性資源,因為它們本身支持事務,也能夠處理事務。 Spring很顯然不是事務性資源,但是它可...
摘要:聲明式事務管理的事務管理是通過代理實現的。其中的事務通知由元數據目前基于或注解驅動。代理對象與事務元數據結合產生了一個代理,它使用一個實現品配合,在方法調用前后實施事務。 JDBC事務 1.獲取連接 Connection con=DriverManager.getConnection(); 2.開啟事務 con.setAutoCommit(true/fase); 3.執行CRUD 4....
摘要:起因考慮如下一個例子定義在這個例子中我們定義了一個注解這個是一個方法注解我們的期望是當有此注解的方法被調用時需要執行指定的切面邏輯即執行方法在類中方法被所注解因此調用方法時應該會觸發方法的調用不過有一點我 起因 考慮如下一個例子: @Target(value = {ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Doc...
閱讀 1410·2021-11-22 09:34
閱讀 1382·2021-09-22 14:57
閱讀 3411·2021-09-10 10:50
閱讀 1389·2019-08-30 15:54
閱讀 3693·2019-08-29 17:02
閱讀 3476·2019-08-29 12:54
閱讀 2618·2019-08-27 10:57
閱讀 3322·2019-08-26 12:24