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

简介: @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代理也就不会执行回滚操作

相关文章
|
6月前
|
Java 编译器 数据库
@Transactional中指定rollbackFor,弊端以及不能回滚的时候
@Transactional中指定rollbackFor,弊端以及不能回滚的时候
185 3
|
6月前
Spring5源码(45)-@Transactional声明式事物(三)事物创建
Spring5源码(45)-@Transactional声明式事物(三)事物创建
70 0
|
Java Spring
java spring事务父方法、子方法各自回滚问题处理
java spring事务父方法、子方法各自回滚问题处理
java spring事务父方法、子方法各自回滚问题处理
|
4月前
|
Java 数据库连接 API
Spring事务管理嵌套事务详解 : 同一个类中,一个方法调用另外一个有事务的方法
Spring事务管理嵌套事务详解 : 同一个类中,一个方法调用另外一个有事务的方法
260 1
|
6月前
|
数据库
Spring5源码(49)-@Transactional声明式事物(七)嵌套事物回滚
Spring5源码(49)-@Transactional声明式事物(七)嵌套事物回滚
45 0
|
6月前
|
Java 数据库 Spring
Spring5源码(48)-@Transactional声明式事物(六)嵌套事物处理
Spring5源码(48)-@Transactional声明式事物(六)嵌套事物处理
56 0
|
SQL 消息中间件 JavaScript
我在项目里用@Transactional注解控制事务,结果完全不生效,纳尼?
我在项目里用@Transactional注解控制事务,结果完全不生效,纳尼?
|
存储 Oracle 安全
需要在Transactional注解指定rollbackFor或者在方法中显示的rollback
由Java阿里巴巴规范提示得,今日探究其原因 1. 先看异常的分类 error是一定会回滚的 这里Exception是异常,他又分为运行时异常RuntimeException和非运行时异常 可查的异常(checked exceptions):Exception下除了RuntimeException外的异常 不可查的异常(unchecked exceptions):RuntimeException及其子类和错误(Error) 如果不对运行时异常进行处理,那么出现运行时异常之后,要么是线程中止,要么是主程序终止。
3618 0