spring@Transactional的一點理解


spring事務有7種傳播行為,分別是:

1、PROPAGATION.REQUIRED:如果當前沒有事務,就創建一個新事務,如果當前存在事務,就加入該事務,該設置是最常用的設置。

2、PROPAGATION.SUPPORTS:支持當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就以非事務執行。‘

3、PROPAGATION.MANDATORY:支持當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就拋出異常。

4、PROPAGATION.REQUIRES_NEW:創建新事務,無論當前存不存在事務,都創建新事務。

5、PROPAGATION.NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。

6、PROPAGATION.NEVER:以非事務方式執行,如果當前存在事務,則拋出異常。

7、PROPAGATION.NESTED:如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。

 

注解@Transactional默認的傳播行為是:PROPAGATION.REQUIRED

若需要設置其他傳播行為,設置方法如下:

@Transactional(propagation = Propagation.REQUIRED)
public void test() {
    //...
}
        

上面的設置的作用是:當方法test出現 “運行時異常” 時,會進行事務回滾(其實是偽回滾,只是把之前的操作改回去。比如有插入操作且是主鍵是自增長的,假設插入一條記錄的操作前,下一id的值是1,但偽回滾后,就變成2了,也就是說,下一次成功插入后,id的值是2而不是1)。

但是如果,在test方法的方法體中捕獲了異常,則不會對事務進行回滾,代碼如下:

@Transactional
public void test() {
    try{
        //...
    } catch(DataAccessException e) {
        e.printStackTrace();
    }
}

上邊的代碼,如果對多個表進行操作,有成功也有失敗的操作,但最后,成功的操作不會被回滾,因為異常被捕獲了,spring捕獲不到,也就沒辦法回滾了。

要想既捕獲異常然后做一些操作,又想對失敗的操作進行回滾,可以在捕獲異常后,再對異常拋出,即讓spring能捕獲該異常 ,示例如下:

@Transactional
public void test() {
    try{
        //...
    } catch(DataAccessException e) {
        e.printStackTrace();
        throw e;
    }
}

另外,被@Transactional注解的方法,spring不止對捕獲數據訪問異常才會進行回滾,而是只要捕獲到了運行時異常都會進行回滾,比如下面的示例:

@Transactional
public void test() {
    try{
        //...
        int [] counts = new int[]{1};
        int count = counts[1];
    } catch(RuntimeException e) {
        e.printStackTrace();
        throw e;
    }
}

上邊的代碼,會報數組下標越界的“運行時異常” ,但被捕獲了,就算之前對數據庫的操作是成功的,之前對數據庫的操作還是會被回滾。

 暫時到這里,以后遇到新問題再補充。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM