Spring 声明式事务管理,捕获异常不抛出就不会回滚

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhen_6137/article/details/82052024

  一个方法发生异常,另一个方法的事务是不会回滚的 

if(userSave){          
    try {         
        userDao.save(user);          
        userCapabilityQuotaDao.save(capabilityQuota);         
     } catch (Exception e) {          
        logger.info("能力开通接口,开户异常,异常信息:"+e);         
     }         
 }  

  一个方法发生异常,另一个方法可以回滚 

if(userSave){         
     try {          
        userDao.save(user);          
        userCapabilityQuotaDao.save(capabilityQuota);         
       } catch (Exception e) {         
        logger.info("能力开通接口,开户异常,异常信息:"+e);          
        throw new RuntimeException();         
     }          
}  

  或

if(userSave){          
    try {          
        userDao.save(user);          
        userCapabilityQuotaDao.save(capabilityQuota);          
    } catch (Exception e) {          
        logger.info("能力开通接口,开户异常,异常信息:"+e);          
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();         
    }         
 }  

默认Spring事务只在发生未被捕获的 RuntimeException时才回滚,而发生检查异常是不会回滚的,

同时,在对方法进行try...catch异常捕获时,没有显示的在catch块中抛出RuntimeException异常(显示的抛出 Exception异常也不会回滚),也不会回滚。  
 

Spring AOP  异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样AOP 代理才能捕获到方法的异常,才能进行回滚,默认情况下aop只捕获RuntimeException的异常,但可以通过配置来捕获特定的异常并回滚  
换句话说在service的方法中不使用try catch 或者在catch中最后加上throw new RuntimeExcetpion(),这样程序异常时才能被AOP捕获进而回滚


解决方案: 
  方案1.例如service层处理事务,那么service中的方法中不做异常捕获,或者在catch语句中最后增加throw new RuntimeException()语句,以便让aop捕获异常再去回滚,并且在service上层(webservice客户端,view层action)要继续捕获这个异常并处理
  方案2.在service层方法的catch语句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常(现在项目的做法)

另外,还发现一个问题。

同一个类中,A方法调用B方法,B上加@Transactional, B手工抛RuntimeException异常, 发现事务没有回滚。但是如果把A方法放在另一个类中,调用B方法,B的事务就会正常工作。不知道是啥问题导致的?

猜你喜欢

转载自blog.csdn.net/zhen_6137/article/details/82052024
今日推荐