Spring事务哪些情况会失效?

Spring事务失效

  1. 访问权限问题

    java的访问权限主要有4种:private、default、protected、public,如果事务方法的访问权限不是定义为public,这样会导致事务失效,因为spring要求被代理方法必须是public的。翻开源码,可以看到,在AbstractFallbackTransactionAttributeSource类的computeTransactionAttribute方法中有个判断,如果目标方法不是public,则返回null,即不支持

    1
    2
    3
    4
    5
    6
    7
    protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
    if (this.allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
    return null;
    } else {
    //........
    }
    }
  2. 方法用final修饰

    如果事务方法用final修饰,会导致事务失效,因为spring事务底层原理使用了aop也就是通过jdk动态代理或者cglib,帮助我们生成了代理类,在代理类中实现的事务功能。但如果某个方法用final修饰了,那么在它的代理类中,就无法重写该方法,而添加事务功能。

  3. 对象没有被spring管理

    使用spring事务的前提是:对象要被spring管理,需要创建bean实例。如果类没有加@Controller、@Service、@Component、@Repository等注解,即该类没有交给spring去管理,那么它的方法就不会生成事务。

  4. 表不支持事务

    如果MySQL使用的存储引擎是myisam,这样的话是不支持事务的,因为myisam存储引擎不支持事务。

  5. 方法内部调用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Service
    public class OrderServiceImpl implements OrderService{
    public void update(Order order){
    this.updateOrder(order);
    }

    @Transactional
    public void updateOrder(Order order){
    //更新操作
    }
    }

    如上面代码所示,update方法上没有加@Transactional注解,调用有@Transactional注解的updateOrder方法,updateOrder方法上的事务会失效。因为发生了自身调用,调用该类自己的方法,而没有经过spring的代理类,只有在外部调用事务才会生效。

    解决:

    • 再加一个serviece,将内部调用改为外部调用

    • 使用编程式事务

    • 使用AopContexct.currentProxy()获取代理对象

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      @Service
      public class OrderServiceImpl implements OrderService{
      public void update(Order order){
      ((OrderService)AopContexct.currentProxy()).updateOrder(order);
      }

      @Transactional
      public void updateOrder(Order order){
      //更新操作
      }
      }
  6. 未开启事务

    如果是spring项目,则需要再配置文件中手动配置事务相关参数,如果忘记了配置,事务肯定是失效的。如果是spingboot项目,那么不需要手动配置。因为springboot已经在DataSourceTransactionManagerAutoConfiguration类中帮我们开启了事务。

  7. 吞了异常

    有时候事务不会回滚,有可能是在代码中手动catch了异常,因为开发者自己捕获了异常,又没有手动抛出,把异常吞掉了,这种情况喜爱spring事务不会回滚。如果想要spring事务能够正常回滚必须抛出它能够处理的异常


Spring事务哪些情况会失效?
http://example.com/2022/09/04/Spring事务失效/
作者
liziyuan
发布于
2022年9月4日
许可协议