spring @Transaction事務回滾失敗


今天客戶提出一個新問題,出庫一批商品,提示失敗了,但是庫存數量卻減少了。看了一下代碼一頭霧水,我們的代碼加了事物,且捕獲異常。

經過調試代碼發現就是兩個原因導致的

第一、在當前方法的catch中處理了捕獲的異常,沒有向上拋出異常,事務不能回滾

分析:

1.在Java中異常的基類為Throwable,他有兩個子類Exception與Errors,同時RuntimeException就是Exception的子類;

2.RuntimeException,即運行時異常,為非受檢(UNCHECKED)異常;      

3.Exception的其他子類異常,為非運行時異常,為受檢異常(CHECKED)異常;

Spring事務回滾機制是這樣的:當所攔截的方法有指定異常拋出,事務才會自動進行回滾!

     ①被攔截方法-—— 注解式:方法或者方法所在類被@Transactional注解;

     ②異常—— 該方法的執行過程必須出現異常,這樣事務管理器才能被觸發,並對此做出處理;

    ③指定異常—— 默認配置下,事務只會對Error與RuntimeException及其子類這些UNChecked異常,做出回滾。一般的Exception這些Checked異常不會發生回滾(如果一般Exception想回滾要做出配置);

Spring的聲明式事務是基於AOP的
   spring aop  異常捕獲原理:被攔截的方法需顯式拋出異常,並不能經任何處理(如果自己捕獲就不能被聲明式事務感知),這樣aop代理才能捕獲到方法的異常,才能進行回滾,默認情況下aop只捕獲runtimeexception的異常,但可以通過 。
    
配置來捕獲特定的異常並回滾  
  換句話說在service的方法中不使用try catch 或者在catch中最后加上throw new runtimeexcetpion(),這樣程序異常時才能被aop捕獲進而回滾
  解決方案: 
  方案1.方法中不做異常捕獲,或者在catch語句中最后增加throw new RuntimeException()語句,以便讓aop捕獲異常再去回滾,並且在上層(webservice客戶端,view層action)要繼續捕獲這個異常並處理
  方案2.在方法的catch語句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();語句,手動回滾,這樣上層就無需去處理異常

第二、在catch中異常拋出Exception,並不是RuntimeException,導致也沒有回滾

解決方法:

① 拋出Exception,同時在事務聲明中加上@Transactional(rollbackFor = Exception.class)

② 在catch添加語句

catch (Exception e) {  
          e.printStackTrace();     
          TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//就是這一句了,加上之后如果異常后會回滾的  
     }  


免責聲明!

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



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