Spring事務為什么不會自動回滾?Spring事務怎樣才會自動回滾?事務自動回滾條件及手動回滾


原文:https://blog.csdn.net/qq_32331073/article/details/76508147

 

更多Spring事務問題請訪問鏈接:Spring事務回滾問題疑難詳解

在此,首先我們要明確RuntimeException與Exception之間的關系與他們分別的含義:

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

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

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

 

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

      我們需要注意的地方有四點: 如果你在開發當中引入Spring進行事務管理,但是事務沒能正常的自動回滾,可以對照下面四點,缺一不可!

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

                                                   攔截配置式:<tx:method />應該包含對該方法,名稱格式的定義;

                                                                       且方法需要在expression定義的范圍內;

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

                    ③指定異常——  默認配置下,事務只會對Error與RuntimeException及其子類這些UNChecked異常,做出回滾。

                                              一般的Exception這些Checked異常不會發生回滾(如果一般Exception想回滾要做出配置);

                          如果你不知道哪些是RuntimeException或者你覺得在默認配置下發生一般的Exception,事務也能如願回滾,請訪

                    問鏈接:哪些異常是RuntimeException?Sql異常屬於RuntimeException嗎?Spring下SQL異常事務回滾?                 

                    舉例:實現一般異常的回滾:

                     注解式:

 

[java]  view plain  copy
 
 
 
  1. @Transactional(rollbackFor=Exception.class)  
  2. @RequestMapping("consump")  
  3. public void insertConsumption(Customer c,Consumption s,Mygift m) throws Exception{    

                     攔截配置式:

 

[java]  view plain  copy
 
 
 
  1. @RequestMapping("consump")  
  2. public void insertConsumption(Customer c,Consumption s,Mygift m) throws Exception{        
[html]  view plain  copy
 
 
 
  1. <tx:method name="insert*" propagation="REQUIRED" rollback-for="java.lang.Exception" />  

 

                   ④異常拋出—— 即方法中出現的指定異常,只有在被事務管理器捕捉到以后,事務才會據此進行事務回滾;

                       1,不捕捉,會回滾:

 

[java]  view plain  copy
 
 
 
  1. public void insertConsumption(Customer c,Consumption s,Mygift m) throws Exception{                    
  2.         int a=consumpDao.insert(s);  
  3.         int b=customerDao.update(customer);       
  4. }  

 

                       2,如果異常被try{}捕捉到,那么事務管理器就無法再捕捉異常,所以就無法做出反應,事務不回滾;

 

[java]  view plain  copy
 
 
 
  1. public void insertConsumption(Customer c,Consumption s,Mygift m) throws Exception{  
  2.    try{  
  3.          int a=consumpDao.insert(s);  
  4.          int b=customerDao.update(customer);    
  5.       }catch(RuntimeException){  
  6.       }                      
  7. }                                           

 

                        3,如果異常被try{}捕捉了,我們還可以在Catch(){}中throw   new  RuntimeException(),手動拋出運行時異常供事務管理器捕捉;       

 

[java]  view plain  copy
 
 
 
  1. public void insertConsumption(Customer c,Consumption s,Mygift m) throws Exception{  
  2.      try{  
  3.           int a=consumpDao.insert(s);  
  4.           int b=customerDao.update(customer);    
  5.         }catch(){  
  6.           throw new RuntimeException();  
  7.         }                      
  8. }  

 

2,在實際開發中,有時並沒有異常發生,但是由於事務結果未滿足具體業務需求,所以我們不得不手動回滾事務!

          有如下兩種方法:

                    ①手動拋出異常(如果你沒有配置一般異常事務回滾,請拋出運行時異常)  

 

  1.     int a=consumpDao.insert(s);  
  2.     int b=customerDao.insert(customer);  
  3.     int d=0;//制造未被滿足的業務需求
  4.     if(a*b*d==1){  
  5.         json.put("result",0);  
  6.         json.put("msg", "購買成功");  
  7.         json.put("data", "");  
  8.     }else{  
  9.         json.put("result",-1);  
  10.         json.put("msg", "購買失敗");  
  11.         json.put("data", "");  
  12.         throw new RuntimeException();  
  13.     }  

 

                   

                    ②編程式實現手動回滾             

 

  1.     int a=consumpDao.insert(s); 
  2.     int b=customerDao.insert(customer);  
  3.     int d=0;//制造未被滿足的業務需求  
  4.     if(a*b*d==1){  
  5.         json.put("result",0);  
  6.         json.put("msg", "購買成功");  
  7.         json.put("data", "");  
  8.     }else{  
  9.         json.put("result",-1);  
  10.         json.put("msg", "購買失敗");  
  11.         json.put("data", "");  
  12.         TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();  
  13.     }  

 

          注意:盡管可以采用編程式方法回滾事務,但“回滾”只是事務的生命周期之一,所以要么編程實現事務的全部必要周期,要么仍要配置事務切點,即,將事務管理的其他周期交由Spring的標識!


免責聲明!

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



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