前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >@Transactional加不加rollbackFor=Exception.class的区别?

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

作者头像
公众号 IT老哥
发布2022-12-17 15:09:42
1.6K0
发布2022-12-17 15:09:42
举报
文章被收录于专栏:用户7621540的专栏

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

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

准备数据

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

开始测试

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

  1. 我们的目的是需要把delflag修改为 0,简单的准备一下 sql。
代码语言:javascript
复制
 <update id="test">
        UPDATE tbl_users set delflag='0' where account='admin'
 </update>
  1. 接着我们先来测试一下@Transactional代码如下。大家都知道2/0必会抛出异常
代码语言:javascript
复制
@Override
@Transactional
public Ret test(){
    int i = articleMapper.test();
    int a = /;
    if(i > ){
        ResultUtil.success();
    }
    return ResultUtil.error();
}
  1. 执行测试。

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

  1. 果然不出所料,执行到第 54 行的时候报错了。出现了java.lang.ArithmeticException: /by zero
  1. 细心的同学会发现ArithmeticException这个异常类是继承了RuntimeException类的

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

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

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

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

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

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

下面我们再试试@Transactional不能回滚的异常。代码如下:

我们直接先用try catch来捕获异常,然后在catch里面自定义抛出Exception异常。

代码语言:javascript
复制
@Override
@Transactional
public Ret test() throws Exception {
    int i = articleMapper.test();

    try {
        int a =  / ;
    } catch (Exception e) {
        throw new Exception();
    }
    if (i > ) {
        ResultUtil.success();
    }
    return ResultUtil.error();
}

ok 直接,抛出的异常是我们指定的java.lang.Exception异常。我们去看看数据库:

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

总结一下:@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. 。。。

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-09-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT老哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 准备数据
  • 开始测试
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档