Spring中的事务失效问题

本文探讨了Spring中@Transactional注解可能出现的失效情况,包括作用于非public方法、MyISAM存储引擎、内部方法调用、组件扫描重复、注解接口而非类、异常未抛出等问题。同时提到了事务传播特性和TransactionTemplate的使用,分析了可能导致事务无法回滚的传播行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


JAVA后端开发知识总结(持续更新…)


Spring中的事务失效问题



一、@Transactional 注解失效

  1. @Transactional 作用在非 public 修饰的方法上,虽然不报错,但是会导致失效。

  @Transactional注解使用的是AOP,在使用动态代理的时候只能针对public方法进行代理,源码依据在AbstractFallbackTransactionAttributeSource类中的computeTransactionAttribute方法。

protected TransactionAttribute computeTransactionAttribute(Method method,
    Class<?> targetClass) {
        // 不允许非 public 创建事务
        if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
        return null;
}
  1. 使用MySQL,存储引擎选择MyISAM,则事务会不起作用,因为MyISAM不支持事务,可以改成InnoDB引擎。

  2. 方法内部调用同类的方法,即在类A里面有方法a和方法b,然后方法b上面用 @Transactional加了方法级别的事务,在方法a里面 调用了方法b, 方法b里面的事务不会生效。

  在应用系统调用声明@Transactional 的目标方法时,Spring Framework 默认使用 AOP 代理,在代码运行时生成一个代理对象,当有注解的方法被调用的时候,实际上是代理类调用的,代理类在调用之前会开启事务,执行事务的操作。
  当在实现类中直接调用内部方法时,其本质是通过this对象来调用的方法,而不是代理对象,所以会出现事务失效的情况。

public class Test{
	  @Transactional
	  public void A(){
	    //插入一条数据
	    //调用B方法
	    B();
	  }
  
	  @Transactional
	  public void B(){
	    //插入数据
	  }
}
  1. 如果使用Spring + Spring MVC,则context:component-scan重复扫描问题可能会引起事务失效。
  • 如果Spring 和 Spring MVC的配置文件中都在扫描Service层,会先加载Spring MVC配置文件,再加载Spring配置文件。
  • 事物一般都在Spring配置文件中进行配置。
  • 如果此时在加载Spring MVC配置文件的时候,把Service也给注册了,但是此时事物还没加载,也就导致后面的事物无法成功注入到Service中。
  1. 最好在具体的类 / 类的方法上使用 @Transactional 注解,而不要使用在类实现的任何接口上使用。在接口上使用 @Transactional 注解,只能当设置了基于接口的代理时它才生效。即@Transactional 作用于接口,却使用 CGLIB 动态代理会导致事务失效。

  因为注解是不能继承的,这就意味着如果正在使用基于类的代理时,事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装。

  1. @Transactional 方法内异常被捕获,而catch语句块没有throw new RuntimeExecption异常,事务不会回滚。

  2. 默认 RuntimeException 和 Error 及子类抛出会回滚;对于rollbackFor,只有指定的异常及子类才会发生回滚。

  3. @Transactional 注解属性 propagation 设置以下三种可能导致无法回滚:

  • SUPPORTS
  • NOT_SUPPORTED
  • NEVER

二、事务传播特性和TransactionTemplate

《Spring的TransactionDefinition中定义的事务的传播特性和隔离级别》

《》

《》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值