關於Spring 事務管理傳播屬性的配置及做用-嵌套事務

先了解事務的7種傳播屬性:java

PROPAGATION_REQUIRED -- 支持當前事務,若是當前沒有事務,就新建一個事務。這是最多見的選擇。 
PROPAGATION_SUPPORTS -- 支持當前事務,若是當前沒有事務,就以非事務方式執行。 
PROPAGATION_MANDATORY -- 支持當前事務,若是當前沒有事務,就拋出異常。 
PROPAGATION_REQUIRES_NEW -- 新建事務,若是當前存在事務,把當前事務掛起。 
PROPAGATION_NOT_SUPPORTED -- 以非事務方式執行操做,若是當前存在事務,就把當前事務掛起。 
PROPAGATION_NEVER -- 以非事務方式執行,若是當前存在事務,則拋出異常。 
PROPAGATION_NESTED -- 若是當前存在事務,則在嵌套事務內執行。若是當前沒有事務,則進行與PROPAGATION_REQUIRED相似的操做。 
前六個策略相似於EJB CMT,第七個(PROPAGATION_NESTED)是Spring所提供的一個特殊變量。 
它要求事務管理器或者使用JDBC 3.0 Savepoint API提供嵌套事務行爲(如Spring的DataSourceTransactionManager)

 

問題產生場景:spa

 1.在 DemoServiceA.java中有方法 demoMethodA().其中嵌套DemoServiceB.java中demoMethodB()。當demoMethodA事務發生rollback時, demoMethodB 事務也能夠rollback或是commit。設計

如圖:code

public class DemoServiceA {
    
    public void demoMethodA() {
        
        demoServiceB.demoMethodB();//Insert對象B 操做
} }

 

常看法決方案: 對象

public class DemoServiceA {
    
    /** 
     * 新建事務
     * 事務屬性配置爲 PROPAGATION_REQUIRED 
     */  
    @Transactional(propagation=Propagation.REQUIRED)
    public void demoMethodA() {
        //操做...
        
        /** 
         * 1.事務屬性配置爲 PROPAGATION_REQUIRES_NEW ;
         * A. DemoServiceA 事務commit與rollback,與 DemoServiceB無任何關係,DemoServiceB 不屬於事務 DemoServiceA的子事務。
         *    PROPAGATION_REQUIRES_NEW 啓動一個新的, 不依賴於環境的 "內部" 事務. 這個事務將被徹底 commited 
         *    或 rolled back 而不依賴於外部事務, 它擁有本身的隔離範圍, 本身的鎖, 當內部事務開始執行時, 
         *    外部事務將被掛起, 內務事務結束時, 外部事務將繼續執行. 
         * B. 能夠起到分支執行的效果。service方法雖然嵌套可是事務之間狀態相互無影響
         *  
         *  
         *     
         * 2.事務屬性配置爲 PROPAGATION_NESTED;
         * PROPAGATION_NESTED 開始一個 "嵌套的" 事務,  它是已經存在事務的一個真正的子事務. 
         * 潛套事務開始執行時,  它將取得一個 savepoint. 若是這個嵌套事務失敗, 
         * 咱們將回滾到此 savepoint. 潛套事務是外部事務的一部分, 只有外部事務結束後它纔會被提交. 
         * 
         */   
        demoServiceB.demoMethodB();//Insert對象B 操做
        //操做...
        
    }
}

 

下面詳細介紹7種事務傳播屬性在示例中的做用:blog

1: REQUIRED

加入當前正要執行的事務不在另一個事務裏,那麼就起一個新的事務

好比說,DemoServiceB.demoMethodB的事務級別定義爲REQUIRED, 那麼因爲執行DemoServiceA.demoMethodA的時候,

DemoServiceA.demoMethodA已經起了事務,這時調用DemoServiceB.demoMethodB,DemoServiceB.demoMethodB看到本身已經運行在DemoServiceA.demoMethodA

的事務內部,就再也不起新的事務。而假如DemoServiceA.demoMethodA運行的時候發現本身沒有在事務中,他就會爲本身分配一個事務。

這樣,在DemoServiceA.demoMethodA或者在DemoServiceB.demoMethodB內的任何地方出現異常,事務都會被回滾。即便DemoServiceB.demoMethodB的事務已經被

提交,可是DemoServiceA.demoMethodA在接下來fail要回滾,DemoServiceB.demoMethodB也要回滾

2: SUPPORTS

若是當前在事務中,即以事務的形式運行,若是當前再也不一個事務中,那麼就以非事務的形式運行

3: MANDATORY

必須在一個事務中運行。也就是說,他只能被一個父事務調用。不然,他就要拋出異常

4: REQUIRES_NEW

這個就比較繞口了。 好比咱們設計DemoServiceA.demoMethodA的事務級別爲REQUIRED,DemoServiceB.demoMethodB的事務級別爲REQUIRES_NEW,

那麼當執行到DemoServiceB.demoMethodB的時候,DemoServiceA.demoMethodA所在的事務就會掛起,DemoServiceB.demoMethodB會起一個新的事務,等待DemoServiceB.demoMethodB的事務完成之後,

他才繼續執行。他與REQUIRED 的事務區別在於事務的回滾程度了。由於DemoServiceB.demoMethodB是新起一個事務,那麼就是存在

兩個不一樣的事務。若是DemoServiceB.demoMethodB已經提交,那麼DemoServiceA.demoMethodA失敗回滾,DemoServiceB.demoMethodB是不會回滾的。若是DemoServiceB.demoMethodB失敗回滾,

若是他拋出的異常被DemoServiceA.demoMethodA捕獲,DemoServiceA.demoMethodA事務仍然可能提交。

5: NOT_SUPPORTED

當前不支持事務。好比DemoServiceA.demoMethodA的事務級別是REQUIRED ,而DemoServiceB.demoMethodB的事務級別是NOT_SUPPORTED ,

那麼當執行到DemoServiceB.demoMethodB時,DemoServiceA.demoMethodA的事務掛起,而他以非事務的狀態運行完,再繼續DemoServiceA.demoMethodA的事務。

6: NEVER

不能在事務中運行。假設DemoServiceA.demoMethodA的事務級別是REQUIRED, 而DemoServiceB.demoMethodB的事務級別是NEVER ,

那麼DemoServiceB.demoMethodB就要拋出異常了。

7: NESTED

理解Nested的關鍵是savepoint。他與REQUIRES_NEW的區別是,REQUIRES_NEW另起一個事務,將會與他的父事務相互獨立,

而Nested的事務和他的父事務是相依的,他的提交是要等和他的父事務一塊提交的。也就是說,若是父事務最後回滾,他也要回滾的。
相關文章
相關標籤/搜索