@Transactional注解加不加rollbackFor=Exception.class的区别?

因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享

点击关注#互联网架构师公众号,领取架构师全套资料 都在这里28e24cac79ec5d1b2ef7ab4d403c5d94.png

0、2T架构师学习资料干货分

上一篇:Docker+Jenkins+Nginx 自动化部署SpringBoot项目

大家好,我是互联网架构师!

上周,一同事看到我去年写的一些代码,@Transactional 加上了 rollbackFor,就问我为什么。我当时和他解释了一番,这里我分享出来,希望能够帮助到更多的人。

彻底弄懂@Transactional@Transactional(rollbackFor = Exception.class)的区别到底在哪里!

准备数据

首先我在 Mysql 中准备了一条数据,如下所示:

9538ae2634001eb823e954df02aabf29.jpeg

开始测试

下面我们就开始简单粗暴的测试了。

  1. 我们的目的是需要把delflag修改为 0,简单的准备一下 sql。

<update id="test">
        UPDATE tbl_users set delflag='0' where account='admin'
 </update>
  1. 接着我们先来测试一下@Transactional代码如下。大家都知道2/0必会抛出异常

@Override
@Transactional
public Ret test(){
    int i = articleMapper.test();
    int a = 2/0;
    if(i > 0){
        ResultUtil.success();
    }
    return ResultUtil.error();
}
  1. 执行测试。

i=1说明更新成功,别着急咱们继续断点往下面走。

80c9d92ab251c96eb39607bc60c6aa8b.jpeg
  1. 果然不出所料,执行到第 54 行的时候报错了。出现了java.lang.ArithmeticException: /by zero

11711c634402f2ba62d4166b798dee12.png

  1. 细心的同学会发现ArithmeticException这个异常类是继承了RuntimeException类的

当我们在使用@Transactional且不加rollbackFor,然后抛出上面的异常时,数据库回滚了。

原因是:@Transactional默认回滚的的异常就RuntimeException类型的。只要是RuntimeException类型的,和它子类型的异常,默认的都能回滚。

ed4c7b84232058685c2aca9ab9836e3b.png

  1. 我们现在点进去看RuntimeException这个类里面一探究竟。我们发现RuntimeException又是继承Exception的。

大多数自定义异常类基本都是继承RuntimeException包括刚才上面的java.lang.ArithmeticException异常。

所以只要是RuntimeExceptionRuntimeException下面的子类抛出的异常@Transactional都是可以回滚的。

07989f4e122d1d673abcddaf5ef76513.png

  1. 这个时候我们去看一下数据库的值到底有没有修改成功,很显然数据是被回滚了。并没有修改成0。

fcc1aab3089428f09fe466f0a16b9218.png

下面我们再试试@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”,获取一份惊喜礼包。

8af8c0672322ecf341983254eac2637d.png

数据库被更新成0了,说明@Transactional并不能回滚Exception异常。

15639d434ebcadf94dc975aa16912332.png

总结一下

@Transactional只能回滚RuntimeExceptionRuntimeException下面的子类抛出的异常,不能回滚Exception异常。

如果需要支持回滚Exception异常请用@Transactional(rollbackFor = Exception.class)

这里如果是增删改的时候我建议大家都使用@Transactional(rollbackFor = Exception.class)

补充一下@Transactional(rollbackFor = Exception.class)一些失效的场景。

  1. 不是用public修饰

  2. try catch捕获了异常(没有在catch里面手动抛出异常)

  3. 没有加@Service(也就是没有被Spring管理)

  4. 。。。

具体有好几种,我历史文章中有过详细的介绍,这里就不在细说了。

相关阅读:

1、Alibaba开源内网高并发编程手册.pdf

2、2T架构师学习资料干货分享

3、10000+TB 资源,阿里云盘,牛逼!!

4、基本涵盖了Spring所有核心知识点总结

  · END ·

最后,关注公众号互联网架构师,在后台回复:2T,可以获取我整理的 Java 系列面试题和答案,非常齐全。

aeed0825234de39510a745670ccfdd54.png

如果这篇文章对您有所帮助,或者有所启发的话,帮忙扫描下发二维码关注一下,您的支持是我坚持写作最大的动力。

求一键三连:点赞、转发、在看。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值