@Transactional注解加不加 rollbackFor = Exception.class 的区别?
Java开发中,往往都是通过@Transactional
或者@Transactional(rollbackFor = Exception.class)
来表示一个事务操作;
所谓事务,就是将单个操作单元中的多个SQL操作作为一个整体,一起进行提交,要么全部成功,要么全部失败;一旦任意一个步骤出现异常,需要将本次操作单元的数据回滚到操作之前的状态;
但两种写法的注解,虽然说只有一个参数的区别,却对最终的事务回滚效果有着特别大的影响,下面就一起来看看:
一、准备
首先我在Mysql中准备了一条数据
二、开始测试
简单的准备一下sql
目的是需要把delflag修改为0
<update id="test">
UPDATE tbl_users set delflag='0' where account='admin'
</update>我们先来测试一下
@Transactional
代码如下 大家都知道2/0必会抛出异常@Override
@Transactional
public Ret test(){
int i = articleMapper.test();
int a = 2/0;
if(i > 0){
ResultUtil.success();
}
return ResultUtil.error();
}执行测试 i=1说明更新成功 别着急咱们继续断点往下面走
果然不出所料 执行到第54行的时候报错了 出现了
java.lang.ArithmeticException: /by zero
细心的同学会发现
ArithmeticException
这个异常类是继承了RuntimeException
的而
@Transactional
默认回滚的的异常就是RuntimeException
我们在点进去
RuntimeException
这个类里面一探究竟 我们发现RuntimeException
又是继承Exception
的而所有的异常类基本都是继承
RuntimeException
包括刚才上面的java.lang.ArithmeticException
异常所以只要是
RuntimeException
和RuntimeException
下面的子类抛出的异常@Transactional
都可以回滚的这个时候我们去看一下数据库的值到底有没有修改成功 很显然数据是被回滚了 并没有修改成0
三、不回滚的事务
在一些特殊的场景下,会有事务不回滚的情况;下面我们在试试@Transactional
不能回滚的异常 代码如下
我们直接先用
try catch
来捕获异常 然后在catch里面自定义抛出Exception
异常@Override
@Transactional
public Ret test() throws Exception {
int i = articleMapper.test();
try {
int a = 2 / 0;
} catch (Exception e) {
throw new Exception();
}
if (i > 0) {
ResultUtil.success();
}
return ResultUtil.error();
}执行之后,可以看到正常抛出了
java.lang.Exception
异常 ,由于默认情况下,@Transactional
只会回滚RuntimeException
异常,所以这里的回滚将会失效;去看看数据库,发现数据已经成功更新;确实并没有发生回滚;
默认访问符修饰的方法
@Transactional
void update() {
int i = articleMapper.update();
if(i<=0){
throw new RuntimeException("err");
}
}这里的方法是使用的默认访问修饰符,Spring在扫描
@Transactional
注解信息的过程,如果方法不是public
修饰,将不会对Bean进行代理对象的创建以及代理方法的调用;内部方法的调用
@Transactional
public void update() {
int i = articleMapper.update();
if(i<=0){
throw new RuntimeException("err");
}
}
public void test(){
update();
}以上代码,当直接调用
test()
,事务将不会生效,原因也比较容易理解,Spring的事务,是通过代理对象来调用并提交/回滚,直接通过内部的方法调用并没有走代理方法调用,最终导致事务失效;
四、总结一下
@Transactional
只能回滚RuntimeException
和RuntimeException
下面的子类抛出的异常 不能回滚Exception
异常如果需要支持回滚
Exception
异常请用@Transactional(rollbackFor = Exception.class)
这里如果是增删改的时候我建议大家都使用
@Transactional(rollbackFor = Exception.class)
特殊场景下,事务回失效,在开发过程中,需要特别注意。
参考:blog.csdn.net/weixin_42169734/
article/details/117122084
END
精品资料,超赞福利,免费领
最近开发整理了一个用于速刷面试题的小程序;其中收录了上千道常见面试题及答案(包含基础、并发、JVM、MySQL、Redis、Spring、SpringMVC、SpringBoot、SpringCloud、消息队列等多个类型),欢迎您的使用。
👇👇