@Transactional 注解rollbackFor 范围问题以及同一个类方法之间调用事务问题

spring Transactional 注解rollbackFor 范围问题

我们首先看下面一组代码

代码1

    @Transactional
    public String testInnerInvodeTransactional(Integer id) throws Exception {



        testMapper.deleteById(id);
        if(true){
            throw new RuntimeException("测试异常");
        }
        return "SUCCESS";

    }

代码2 

    @Transactional
    public String testInnerInvodeTransactional(Integer id) throws Exception {



        testMapper.deleteById(id);
        if(true){
            throw new Exception("测试异常");
        }
        return "SUCCESS";

    }

原数据库数据如下

 

代码1 执行结果

代码2 执行结果

 

 

两个代码主要区别是抛出异常一个是RuntimeException ,一个是Exception,可以看出代码1回滚了而代码2没有回滚,为什么呢

spring Transactional 的rollbackFor 原理

spring Transactional 的rollbackFor 原理
spring Transactional 默认的rollbackFor 范围是UncheckExcetion ,也就是RuntimeException和Error
代码1 我们抛出的是RuntimeException在默认范围内
代码2 我们抛出的是Exception 属于父类excetion 并不是默认范围,因此没有回滚
一定要设置spring Transactional 的rollbackFor 范围 
比如可以直接设置为Exception.class,同时进来设置好传播范围,参考如下设置:

 解决方案:

@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)

spring 同一个类方法之间调用事务问题

我们看下面一组代码

代码1

 /**
     * 外层方法处理数据
     * */
    public String testInnerInvodeTransactional(Integer id) throws Exception {

        //内层方法处理数据
        innerInvodeTransactional(id);
        return "SUCCESS";
    }

    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public void innerInvodeTransactional(Integer id) {
        testMapper.deleteById(id);
        if(true){
            throw new RuntimeException("测试异常");
        }
    }

 代码2

 /**
     * 外层方法处理数据
     * */
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public String testInnerInvodeTransactional(Integer id) throws Exception {

        //内层方法处理数据
        innerInvodeTransactional(id);
        return "SUCCESS";
    }

    public void innerInvodeTransactional(Integer id) {
        testMapper.deleteById(id);
        if(true){
            throw new RuntimeException("测试异常");
        }
    }
原数据库数据如下


代码1执行结果


代码2执行结果 

 

上面两个方法的主要区别在于Transactional放在了入口类还是被调用类, 可以看出代码1没有回滚,而代码2回滚了,为什么呢

spring Transactional 原理

spring 会扫描带@Transactional 的方法,然后形成aop代理,执行以下流程
1.代理类会设置事务为手动提交
2.try ,catch 住要执行的方法
3.如果抛出异常,则执行catch 内的回滚代码
4.如果正常执行,则finally 中提交事务

解决方案: 

由以上可以内部方法调用问题主要在于否执行时执行的是aop代理类
如果是代理类,则会执行事务回滚
如果不是代理类,则不会执行事务回滚
所以入口的方法一定要加上事务注解,不然不会生成aop代理也就不会执行回滚操作

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

峡谷电光马仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值