因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享
点击关注#互联网架构师公众号,领取架构师全套资料 都在这里
上一篇:Docker+Jenkins+Nginx 自动化部署SpringBoot项目
大家好,我是互联网架构师!
上周,一同事看到我去年写的一些代码,@Transactional 加上了 rollbackFor,就问我为什么。我当时和他解释了一番,这里我分享出来,希望能够帮助到更多的人。
彻底弄懂@Transactional
和@Transactional(rollbackFor = Exception.class)
的区别到底在哪里!
准备数据
首先我在 Mysql 中准备了一条数据,如下所示:
![9538ae2634001eb823e954df02aabf29.jpeg](https://i-blog.csdnimg.cn/blog_migrate/62b1d369ed56a3e46aab283168c6edff.jpeg)
开始测试
下面我们就开始简单粗暴的测试了。
我们的目的是需要把
delflag
修改为 0,简单的准备一下 sql。
<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
说明更新成功,别着急咱们继续断点往下面走。
![80c9d92ab251c96eb39607bc60c6aa8b.jpeg](https://i-blog.csdnimg.cn/blog_migrate/4a453735169f83b8102ec198512190d4.jpeg)
果然不出所料,执行到第 54 行的时候报错了。出现了
java.lang.ArithmeticException: /by zero
细心的同学会发现
ArithmeticException
这个异常类是继承了RuntimeException
类的
当我们在使用@Transactional
且不加rollbackFor
,然后抛出上面的异常时,数据库回滚了。
原因是:@Transactional
默认回滚的的异常就RuntimeException
类型的。只要是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();
}
ok 直接,抛出的异常是我们指定的java.lang.Exception
异常。我们去看看数据库:另外,搜索公众号互联网架构师后台回复“9”,获取一份惊喜礼包。
数据库被更新成0了,说明@Transactional
并不能回滚Exception
异常。
总结一下
@Transactional
只能回滚RuntimeException
和RuntimeException
下面的子类抛出的异常,不能回滚Exception
异常。
如果需要支持回滚Exception
异常请用@Transactional(rollbackFor = Exception.class)
。
这里如果是增删改的时候我建议大家都使用@Transactional(rollbackFor = Exception.class)
。
补充一下@Transactional(rollbackFor = Exception.class)
一些失效的场景。
不是用
public
修饰try catch
捕获了异常(没有在catch
里面手动抛出异常)没有加
@Service
(也就是没有被Spring
管理)。。。
具体有好几种,我历史文章中有过详细的介绍,这里就不在细说了。
相关阅读:
· END ·
最后,关注公众号互联网架构师,在后台回复:2T,可以获取我整理的 Java 系列面试题和答案,非常齐全。
如果这篇文章对您有所帮助,或者有所启发的话,帮忙扫描下发二维码关注一下,您的支持是我坚持写作最大的动力。
求一键三连:点赞、转发、在看。