一个方法发生异常,另一个方法的事务是不会回滚的
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的事务就会正常工作。不知道是啥问题导致的?