spring @Transaction事務回滾失敗

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

通過調試代碼發現就是兩個緣由致使的spring

第1、在catch中處理了捕獲的異常,沒有向上拋出異常,事務不能回滾spa

分析:代理

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

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

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

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

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

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

    ③指定異常—— 默認配置下,事務只會對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();語句,手動回滾,這樣上層就無需去處理異常

第2、在catch中異常拋出Exception,並非RuntimeException,致使也沒有回滾

解決方法:

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

② 在catch添加語句

catch (Exception e) {  
          e.printStackTrace();     
          TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//就是這一句了,加上以後若是異常後會回滾的  
     }  
相關文章
相關標籤/搜索