對Spring事務的一些誤解

來源:互聯網
上載者:User

標籤:nal   tac   調用   thread   create   提交   系統   llb   失敗   

  提起spring事務,就會讓人聯想起四大基本特徵,五個隔離等級,七大傳播特性。相信大多數人都知道這些東西,但是知道是一回事情,能用好真的是另一回事了。在使用Spring事務的時候,我曾遇到過幾個比較嚴肅的問題,在這裡我做一個自我總結。 問題一、 propagation.NESTED和propagation.REQUIRED_NEW有什麼區別?

  當調用方不存在事務的時候,兩者的效果是一致的。所以這裡討論問題的前提是調用方存在事務。PROPAGATION_REQUIRES_NEW 啟動一個新的, 不依賴於環境的 "內部" 事務. 這個事務將被完全 commited 或 rolled back 而不依賴於外部事務, 它擁有自己的隔離範圍, 自己的鎖, 等等. 當內部事務開始執行時, 外部事務將被掛起, 內務事務結束時, 外部事務將繼續執行. 
另一方面, PROPAGATION_NESTED 開始一個 "嵌套的" 事務, 它是已經存在事務的一個真正的子事務. 潛套事務開始執行時, 它將取得一個 savepoint. 如果這個嵌套事務失敗, 我們將復原到此 savepoint. 潛套事務是外部事務的一部分, 只有外部事務結束後它才會被提交. 
由此可見, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大區別在於, PROPAGATION_REQUIRES_NEW 完全是一個新的事務, 而 PROPAGATION_NESTED 則是外部事務的子事務, 如果外部事務 commit, 潛套事務也會被 commit, 這個規則同樣適用於 roll back. 

 

問題二、 @Transactional為什麼會失效?

  1.調用方和被呼叫者屬於同一個component,被呼叫者的 @Transacational 註解無效

  

package com.transacational;import org.springframework.stereotype.Component;import org.springframework.transaction.annotation.Transactional;/** * Created by chenqimiao on 17/10/31. */@Componentpublic class Service {    public void test1(){        test2();    }    @Transactional//此處的註解無效    public void test2(){    }}

 

  

  2.被呼叫者不是一個public方法,被呼叫者的 @Transacational 註解無效

  

@Componentpublic class Service {    @Resource    private Service1 service1;        public void test1(){        test2();        service1.test3();    }    @Transactional//1.此處的註解無效    public void test2(){    }}
package com.transacational;import org.springframework.stereotype.Component;import org.springframework.transaction.annotation.Transactional;/** * Created by chenqimiao on 17/10/31. */@Componentpublic class Service1 {    @Transactional//2.此處註解無效    protected void test3(){    }}

 

  3.未開啟事務開關,如:在SpringBoot中,啟動類未使用 @EnableTransactionManagement  

 

 問題三、 如何理解@Transactional的逾時時間?

   timeout 是一個供開發人員設定逾時時間的屬性。預設值-1,逾時時間由具體的sql系統決定。

   

/** * Created by chenqimiao on 17/10/31. */@Componentpublic class Service3 {    @Resource    private AdminInfoDoMapper adminInfoDoMapper;    @Transactional(timeout = 4)//並不會逾時    public void test4(){        adminInfoDoMapper.selectNameById(1);        try {            Thread.sleep(5000);        } catch (InterruptedException e) {            e.printStackTrace();        }    }}

逾時時間具體的定義:事務開始(在該方法第一句代碼執行之前)到最後一個Statement執行完畢

所以象下面這樣寫,事務就會逾時

@Componentpublic class Service3 {    @Resource    private AdminInfoDoMapper adminInfoDoMapper;    @Transactional(timeout = 4)    public void test4(){        try {            Thread.sleep(5000);        } catch (InterruptedException e) {            e.printStackTrace();        }        adminInfoDoMapper.selectNameById(1);    }}

 

 

問題四、 @Transactional預設的復原策略?

預設情況下,只有當RuntimeException或其子類的異常被事務捕獲之後,事務才會復原,如果要讓事務能夠復原所有異常,必須手動指定 @Transactional(rollbackFor=Exception.class) ,這樣繼承Exception的子類或者Exception本身都可以讓交易回復。

 

對Spring事務的一些誤解

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.