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的标识!

  • 相关阅读:
    背包问题
    基本TCP套接字编程
    P中值选址问题的整数规划求解
    Leapms + cplex解决 混合整数规划问题
    如何用整数规划求解NP完全问题
    用Leapms建摸 / 用 CPLEX 求解 旅行商问题 整数规划问题
    用线性规划建模(确定参数)关键路径法
    流水车间调度算法分析的简单+Leapms实践--混合整数规划的启发式建模
    Wolsey "强整数规划“ 建模的+Leapms实践——无产能批量问题
    Wolsey“强整数规划模型”经典案例之一单源固定费用网络流问题
  • 原文地址:https://www.cnblogs.com/shihaiming/p/9358792.html
Copyright © 2011-2022 走看看