zoukankan      html  css  js  c++  java
  • 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的标识!

  • 相关阅读:
    LA 2038 Strategic game(最小点覆盖,树形dp,二分匹配)
    UVA 10564 Paths through the Hourglass(背包)
    Codeforces Round #323 (Div. 2) D 582B Once Again...(快速幂)
    UVALive 3530 Martian Mining(贪心,dp)
    UVALive 4727 Jump(约瑟夫环,递推)
    UVALive 4731 Cellular Network(贪心,dp)
    UVA Mega Man's Mission(状压dp)
    Aizu 2456 Usoperanto (贪心)
    UVA 11404 Plalidromic Subsquence (回文子序列,LCS)
    Aizu 2304 Reverse Roads(无向流)
  • 原文地址:https://www.cnblogs.com/shihaiming/p/9358792.html
Copyright © 2011-2022 走看看