@Transactional注解的使用以及try-catch捕獲異常導致@Transactional注解失效的問題


1、事務管理是應用系統開發中必不可少的一部分。在spring boot 中,使用事務非常簡單,只要直接在方法上面加入@Transactional 就可以實現。

2、SpringBoot項目會自動配置一個 DataSourceTransactionManager,所以我們只需在方法(或者類)加上 @Transactional 注解,就自動納入 Spring 的事務管理了。

如下在方法加上 @Transactional 注解:

@Transactional
public void insertUser() {
    User user = new User("張三");
    userMapper.insertOneUser(user);          //向數據庫插入一條記錄
    throw new RuntimeException("發生異常");   //手動模擬拋出異常
}

拋出異常之后,事務會自動回滾,數據不會插入到數據庫。

  • 當Transaction內發生unchecked exception的時候,會自動rollback,但是當Transaction內發生checked exception時,是不會自動rollback的。
  • 如果使用try-catch捕獲異常,則該事務不會回滾。

3、默認spring事務只在發生未被捕獲的 RuntimeException 時才回滾。

spring aop異常捕獲原理:被攔截的方法需顯式拋出異常,並不能經任何處理,這樣aop代理才能捕獲到方法的異常,才能進行回滾,默認情況下aop只捕獲RuntimeException的異常,但可以通過配置來捕獲特定的異常並回滾。
換句話說在service的方法中不使用try catch或者在catch中最后加上throw new runtimeexcetpion(),這樣程序異常時才能被aop捕獲進而回滾。

解決方案:

  • 方案1.例如service層處理事務,那么service中的方法中不做異常捕獲,或者在catch語句中最后增加throw new RuntimeException()語句,以便讓aop捕獲異常再去回滾,並且在service上層(webservice客戶端,view層action)要繼續捕獲這個異常並處理。

  • 方案2.在service層方法的catch語句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();語句,手動回滾,這樣上層就無需去處理異常。

例如

catch (Exception e)
{
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//手動回滾
    result.put("status", 0);
    result.put("msg",msg);
    return result;
}

4、總結:如果是try-catch捕獲異常引起的@Transactional注解失效,只要手動拋出RuntimeException()或者在catch中使用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();語句就可以解決。

5、參考博客:


免責聲明!

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



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