@Transactional注解常見的坑


@Transaction注解失效

1、加@Transaction的方法必須是public,否則失效
2、在同一個類里,兩個@Transaction方法直接嵌套調用會失效

A方法調用B方法,B方法加上@Transaction注解,如果A,B方法在同一個類里,則方法B的@Transaction注解失效。
因為@Transaction注解實現原理是AOP,自身調用不會產生代理對象,AOP無法織入,所以會失效。
解決方法:將A,B方法放在兩個類中,或是使用AopContext.currentProxy()
https://blog.csdn.net/qq_38085240/article/details/87801025
3、繞過springboot的DataSource獲取的數據庫連接,事務管理器需要手動配置,否則失效
4、Spring是通過TransactionSynchronizationManager類中的ThreadLocal變量來獲取事務中的數據庫連接,所以如果是多線程調用失效
5、如果類和方法上同時加上@Transaction注解,方法上的定義優先
6、以下這種場景

如果在加了事務注解的A方法中,調用B方法,B方法有異常,則分為B有事務注解和沒有事務注解兩種情況:
6.1 方法B沒有事務
如果方法B中沒有事務注解,則由於方法A已經catch住了異常,所以方法A上的事務並不會感知到異常,所以方法不會回滾,並且如果方法B的數據庫操作也能順利寫入
6.2 方法B有事務
如果方法B有事務,如果默認的傳播行為,require,則TransactionState對象會傳遞到方法B上,所以會將整個TransactionState對象的rollback屬性設定為true,所以A方法也會回滾,即是在方法A中catch了異常也無用。
這里值得一提的一點是,這里TransactionDefinition會以方法B上定義的為准,如果B上的傳播特性為require_new,由於新創建了一個TransactionState,則不會影響A。
如果方法B的事務注解上配置了noRollbackFor,如果是滿足條件的異常則不會影響A。

事務超時

Spring事務超時判斷只是在執行數據庫操作時候,所以如果超時后沒有數據庫操作,則無法准確超時。

    @Transactional(timeout = 5)
    public void timeout() throws InterruptedException {
        Thread.sleep(1000000);
        insert();//會報超時異常
    }

    @Transactional(timeout = 5)
    public void timeout() throws InterruptedException {
        insert();
        Thread.sleep(1000000);//這個方法不會超時異常,因為超時后沒有數據庫操作
    }


免責聲明!

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



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