spring事务-Exception居然不会回滚?

8 阅读1分钟

service方法如果抛出Exception,事务是不会回滚的

自己写代码测试一下就知道了

@Override
public void saveExcel(List<QualityMenuText> list) throws Exception {
    //先删除
    log.info("批量删除");
    qualityMenuTextDao.deleteQualityMenuTexts(list);

    //再新增
    log.info("批量新增");
    qualityMenuTextDao.batchInsertQualityMenuTexts(list);

    //抛出异常
    throw new Exception("抛出异常");
}

也就是说,sql成功,并没有回滚

那怎么解决这个问题呢?

手动显式添加回滚异常

@Transactional(rollbackFor = Exception.class)

上面同样的代码,事务就会神奇的回滚


说白了,就是指定哪个异常类可以回滚

那什么异常会回滚?

运行时异常

哪些是运行时异常?

异常的类继承图

Java中的所有异常类都继承自Throwable类。Throwable有两个主要的子类:ExceptionError

  • Throwable

    • Error

      • VirtualMachineError
      • OutOfMemoryError
      • StackOverflowError
      • 等等。
    • Exception

      • RuntimeException

        • NullPointerException
        • ArrayIndexOutOfBoundsException
        • IllegalArgumentException
        • ClassCastException
        • 等等。
      • 其他Exception(受检查异常)

        • IOException
        • SQLException
        • FileNotFoundException
        • 等等。

哪些是Exception?

那我也不可能每个方法都去手动显式指定啊?

确实不用

因为mybatis框架(dao层数据库异常)和微服务网络调用异常(springcloud feign和dubbo框架),全部都已经自动处理——所以不需要每个都手动处理

框架实现原理

说白了,就是框架已经封装了非运行时异常为运行时异常,省得你处理

比如dubbo RpcException继承了运行时异常

网络调用异常-http框架

okhttp/spring RestTemplate封装了运行时异常

okhttp功能最丰富,推荐使用

如果已经使用spring,spring RestTemplate也能满足需求,一般没有必要引入那么多框架

HttpClient没有封装运行时异常,而是Exception

自定义业务异常

一般也要继承运行时异常,避免事务失效