Spring事务异常回滚

默认 spring 事务只在发生未被捕获的 RuntimeExcetpion 时才会回滚。

  • 类似这样的方法不会回滚:
    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 aop 异常捕获原理

被拦截的方法需显式抛出异常,并不能经任何处理,这样 aop 代理才能捕获到方法的异常,才能进行回滚,默认情况下 aop 只捕获 RuntimeException 的异常,但可以通过配置来捕获特定的异常并回滚。

换句话说在 service 的方法中不使用 try{}catch{} 或者在 catch 中最后加上 throw new RuntimeExcetpion();,这样程序异常时才能被 aop 捕获进而回滚。

解决方案:

  1. 例如:service 层处理事务,那么 service 中的方法中不做异常捕获,或者在 catch 语句中最后增加 throw new RuntimeException() 语句,以便让 aop 捕获异常再去回滚,并且在 service 上层(controller 层)要继续捕获这个异常并处理。
  2. 在 service 层方法的 catch 语句中增加:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

手动回滚,这样上层就无需去处理异常。

你可能感兴趣的:(Spring事务异常回滚)