Spring事务失效的一种原因关于this调用的问题

  • PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务。如果没有事务则开启事务;
  • PROPAGATION_REQUIRES_NEW:总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起;

问题:

Spring中一个没有事务的方法A调用一个默认事务(PROPAGATION_REQUIRED)的方法B时,如果使用this调用方法B,方法B抛出RuntimeException,此时方法B事务未生效,不会回滚。

@Service
public class EmployeeService {

    @Autowired
    private EmployeeDao employeeDao;

    public void save(){
        try {
            this.saveEmployee();  //此处this调用不会开启事务,数据会被保存
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Transactional(propagation = Propagation.PROPAGATION_REQUIRED)
    //此处无论是PROPAGATION_REQUIRED还是PROPAGATION_REQUIRES_NEW,事务均不生效
    public void saveEmployee(){
        Employee employee = new Employee();
        employee.setName("zhangsan");
        employee.setAge("26";
        employeeDao.save(employee);
        throw new RuntimeException();
    }
}

问题原因:

JDK的动态代理。只有被动态代理直接调用时才会产生事务。在SpringIoC容器中返回的调用的对象是代理对象而不是真实的对象。而这里的this是EmployeeService真实对象而不是代理对象。

解决办法:

方法1、在方法A上开启事务,方法B不用事务或默认事务,并在方法A的catch中throw new RuntimeException();(在没指定rollbackFor时,默认回滚的异常为RuntimeException),这样使用的就是方法A的事务。(一定要throw new RuntimeException();否则异常被捕捉处理,同样不会回滚。)如下:

@Transactional() //开启事务
public void save(){
    try {
        this.saveEmployee();  //这里this调用会使事务失效,数据会被保存
    }catch (Exception e){
        e.printStackTrace();
        throw new RuntimeException();
    }
}

方法2、方法A上可以不开启事务,方法B上开启事务,并在方法A中将this调用改成动态代理调用(AopContext.currentProxy()),如下:

public void save(){
    try {
        EmployeeService proxy =(EmployeeService) AopContext.currentProxy();
        proxy.saveEmployee();
    }catch (Exception e){
        e.printStackTrace();
    }
}

到此这篇关于spring事务调用失效问题的文章就介绍到这了,更多相关spring事务调用失效问题内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Spring事务失效的几种原因

    数据库引擎不支持事务 在MySQL数据库中有几种引擎(InnoDB,MyISAM,Memory等等),仅仅InnoDB支持事务,如果数据库底层都不支持事务的话,那么再怎么折腾都是白搭. @transactional加在private方法上 @Transactional只能加在public方法上,如果需要在private方法中加入事务,可以使用Aspect配transactionManager使用. 本类方法调本类另一个方法 例如: @Service public class UserServic

  • 一篇文章带你了解spring事务失效的多种场景

    目录 前言 一 事务不生效 1.访问权限问题 2. 方法用final修饰 3.方法内部调用 4.未被spring管理 5.多线程调用 6.表不支持事务 7.未开启事务 二 事务不回滚 1.错误的传播特性 2.自己吞了异常 3.手动抛了别的异常 4.自定义了回滚异常 5.嵌套事务回滚多了 三 其他 1 大事务问题 2.编程式事务 总结 前言 对于从事java开发工作的同学来说,spring的事务肯定再熟悉不过了. 在某些业务场景下,如果一个请求中,需要同时写入多张表的数据.为了保证操作的原子性(要

  • Spring事务失效问题分析及解决方案

    这篇文章主要介绍了Spring事务失效问题分析及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 隔离级别 在 TransactionDefinition.java 接口中,定义了"四种"的隔离级别枚举: /** * [Spring 独有]使用后端数据库默认的隔离级别 * * MySQL 默认采用的 REPEATABLE_READ隔离级别 * Oracle 默认采用的 READ_COMMITTED隔离级别 */ int ISOL

  • Spring事务失效场景原理及解决方案

    1.事务失效-自身调用(通过REQUIRES.REQUIRES_NEW传播属性):自身调用即调该类自己的方法. 同类OrderServiceImpl 中 doSomeThing()方法 不存在事务,该方法去调用本类中的存在事务注解的 insertAndUpdateOrderInfo() 方法.但是insertAndUpdateOrderInfo() 其实是无法保证预想的事务性. 示列验证: OrderServiceImpl.insertAndUpdateOrderInfo方法中upateData

  • 解决try-catch捕获异常信息后Spring事务失效的问题

    一.首先在Spring Boot项目中,手动添加异常方法进行测试 @Transactional(rollbackFor=Exception.class) //表示此方法有异常时触发Spring事务 @Override public CommonResult<User> saveUser(User user) { int insert = baseMapper.insert(user); try { // 添加异常,并进行捕获 int a = 10/0; }catch (Exception e)

  • Spring事务失效的一种原因关于this调用的问题

    PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务.如果没有事务则开启事务: PROPAGATION_REQUIRES_NEW:总是开启一个新的事务.如果一个事务已经存在,则将这个存在的事务挂起: 问题: Spring中一个没有事务的方法A调用一个默认事务(PROPAGATION_REQUIRED)的方法B时,如果使用this调用方法B,方法B抛出RuntimeException,此时方法B事务未生效,不会回滚. @Service public class Employ

  • Spring事务失效的各种场景(13种)

    目录 一.访问权限 二.方法用final修饰 三.方法内部调用 四.没有被spring管理 五.多线程调用 六.设计的表不支持事务 七.没有开启事务 八.错误的事务传播 九.自己捕获了异常 十.手动抛出别的异常 十一.自定义回滚异常 十二.嵌套事务回滚过头 十三.编程式事务 一.访问权限 Java的访问权限主要是:private.default.protected.public,它们的权限则是依次变大.如果我们在开发的时候定义错误的访问权限,就会导致事务出现问题 @Service public

  • Spring事务失效场景实例详解

    1.Spring事务最终依赖的数据库的事务,如果用的是mysql的话,执行引擎要是innodb;因为只有innoDB 支持事务. 2.Spring的事务是原理是aop,所以加事务所在bean是要Spring容器管理的:自己new出来的对象肯定是不行的. 3.Spring事务标签@Transactional必须注解在public方法上.private.protected.default以及finally修饰的方法或者类,以及静态方法,事务都会失效的. 4.同一个类中内部方法调用,事务会失效的.调用

  • 8个Spring事务失效场景详解

    目录 前言 Spring事务原理 Spring事务失效场景 1. 抛出检查异常 2. 业务方法本身捕获了异常 3. 同一类中的方法调用 4. 方法使用 final 或 static关键字 5. 方法不是public 6. 错误使用传播机制 7. 没有被Spring管理 8. 多线程 总结 前言 作为Java开发工程师,相信大家对Spring种事务的使用并不陌生.但是你可能只是停留在基础的使用层面上,在遇到一些比较特殊的场景,事务可能没有生效,直接在生产上暴露了,这可能就会导致比较严重的生产事故.

  • Spring事务失效场景的详细整理

    目录 前言 数据库引擎不支持事物 方法不是 public 的 自身调用问题 不支持事物 异常被吃掉 异常类型错误 总结 前言 项目中用Spring的 @Transactional 注解控制事务,使用中时常出现事物不生效的场景,本文仅限于日常项目开发中的点滴整理总结,总结以下几点,以备后续参考排查;可能不全,列举出来希望可以帮助有需要的同学,避免踩坑. 数据库引擎不支持事物 这里以 MySQL 为例,其 MyISAM 引擎是不支持事务操作的,InnoDB 才是支持事务的引擎,一般要支持事务都会使用

  • Spring事务@Transactional注解四种不生效案例场景分析

    目录 背景 示例代码 1. 类内部访问 2. 私有方法 3. 异常不匹配 4. 多线程 父线程抛出异常 子线程抛出异常 源码解读 @Transactional 执行机制 private 导致事务不生效原因 异常不匹配原因 背景 在我们工作中,经常会用到 @Transactional 声明事务,不正确的使用姿势会导致注解失效,下面就来分析四种最常见的@Transactional事务不生效的 Case: 类内部访问:A 类的 a1 方法没有标注 @Transactional,a2 方法标注 @Tra

随机推荐