当前位置: 代码迷 >> 综合 >> Transactional 默认回滚策略和自定义回滚异常类型
  详细解决方案

Transactional 默认回滚策略和自定义回滚异常类型

热度:98   发布时间:2023-11-25 08:22:09.0

首先:当我们使用声明式注解事务的时候,如果你只写Transactional 的话,方法返回中有写throws Exception 的话,idea会提示你要指定对应可能出现的异常类型。
在这里插入图片描述
这个时候我就在想,这个事务的默认回滚异常类型是什么?如果我在注解中指定一个对应的回滚异常会发生什么?

想是想不出的,只能看源码!!!

随即写了个简单的测试类:
1:不在事务注解上指定回滚异常类
在这里插入图片描述
通过debug定位,定位到这个类
在这里插入图片描述
点击进去找到后你会找到RuleBasedTransactionAttribute这个类中rollbackOn 这个方法
在这里插入图片描述
点击super.rollbackOn(ex)就会发现
在这里插入图片描述

可以得出,默认是实际抛出的异常类是要属于RuntimeException子类实例或者就是RuntimeException类又或者是Error才能返回true 。返回true就是能够回滚的!

2:接下来看有在注解中指定回滚异常类的
在这里插入图片描述
还是在rollbackOn 这个方法,但是发现会停留在rule.getDepth(ex)方法上
在这里插入图片描述
this.rollbackRules其实就是你指定的异常类型,程序会先判断你是否有指定异常类型。上面的for循环是因为你有可能指定多个异常类型,所以遍历。ex是你具体程序中抛出的异常,也就是 int i=1/0;所带来的java.lang.ArithmeticException异常,接着我们看rule.getDepth(ex)方法

在这里插入图片描述
通过官方的注释可以看到,他会不断的递归调用自己方法来找到实际抛出异常到你指定回滚异常类的深度值 ,this.exceptionName 其实就是你指定的回滚异常类 。这里会有个问题,如果你实际抛出的异常类是比你指定回滚异常类“要大”(也就是实际的是你指定的父类),实际抛出的异常类 > 指定回滚的异常类,会返回-1,表示没有匹配。
在这里插入图片描述
接着往下走,得到最终的结果depth=2,这个是正确的,因为ArithmeticException是继承RuntimeException,而RuntimeException是继承Exception的。深度值确实是2。
在这里插入图片描述
在这里插入图片描述
通过上面的图也可以看出winner这个变量是不为空的,并且RollbackRuleAttribute 是winner的类型,那么会在跳到return !(winner instanceof NoRollbackRuleAttribute);这个判断,结果会返回true!!成功回滚。之前说的depth返回-1 的情况可以自己去试试,如果为-1,那么winner就null会走默认的回滚策略。

  相关解决方案