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

相关文章
|
8月前
|
XML Java 关系型数据库
@Transactional注解的失效场景
@Transactional注解的失效场景
125 1
|
Java Spring
java spring事务父方法、子方法各自回滚问题处理
java spring事务父方法、子方法各自回滚问题处理
java spring事务父方法、子方法各自回滚问题处理
|
7天前
|
Java 开发者 Spring
理解和解决Spring框架中的事务自调用问题
事务自调用问题是由于 Spring AOP 代理机制引起的,当方法在同一个类内部自调用时,事务注解将失效。通过使用代理对象调用、将事务逻辑分离到不同类中或使用 AspectJ 模式,可以有效解决这一问题。理解和解决这一问题,对于保证 Spring 应用中的事务管理正确性至关重要。掌握这些技巧,可以提高开发效率和代码的健壮性。
34 13
|
5月前
|
存储 NoSQL Java
工作 6 年,@Transactional 注解用的一塌糊涂
工作 6 年,@Transactional 注解用的一塌糊涂
|
6月前
|
Java 数据库连接 API
Spring事务管理嵌套事务详解 : 同一个类中,一个方法调用另外一个有事务的方法
Spring事务管理嵌套事务详解 : 同一个类中,一个方法调用另外一个有事务的方法
438 1
|
8月前
|
Java 编译器 Spring
@transactional注解失效情况
@transactional注解失效情况
|
8月前
|
数据库
Spring5源码(49)-@Transactional声明式事物(七)嵌套事物回滚
Spring5源码(49)-@Transactional声明式事物(七)嵌套事物回滚
54 0
|
Java 数据库 Spring
@Transactional 注解失效问题
@Transactional 注解失效问题
119 0
|
SQL 消息中间件 JavaScript
我在项目里用@Transactional注解控制事务,结果完全不生效,纳尼?
我在项目里用@Transactional注解控制事务,结果完全不生效,纳尼?
|
存储 Oracle 安全