SpringBoot事务失效排错记录

  项目开发完后,在进行后端集成测试的时候发现用户Service层抛出异常后,事务没有回滚,于是去分析了下原因,导致事务失效的原因大致有这几点:

  1. 该方法没有被Spring管理------>类上面有@Service,排除
  2. 方法没有被public修饰------>方法是public修饰的,排除
  3. 自身调用------>方法上面有@Transactional注解,并且调用的是mapper方法,不存在自身调用,排除
  4. 不支持事务------>@Transactional注解使用的默认传播级别并未开启Propagation.NOT_SUPPORTED,排除
  5. 数据源没有配置事务管理器------>检查配置文件是开启的,排除
  6. 异常被try/catch了----->代码逻辑中并没有try/catch,排除
  7. 异常类型错误或格式配置错误----->rollbackFor回滚异常写的是Exception.class,并且抛出的异常是RuntimeException子类,排除

排查完发现该注意的都注意了,但是事务不回滚,于是写了个单元测试了一下,发现事务居然回滚了,并且如果controller层加入事务,事务也是回滚的,一下在不知道问题出在哪里了,分析了半天,决定手动回滚试一下,于是在service层try/catch异常完后手动回滚异常,请求报错:No transaction aspect-managed TransactionStatus in scope。说明这个方法就没有开启事务(但是确确实实开启了,并且都排查了一遍),完后我就去拿了一个我之前写的接口去测试下(这个接口写完的时候我特地有去调接口测过,当时事务是可以回滚的),发现这个接口的事务也不生效了,于是怀疑是不是谁提交了什么配置文件,导致事务失效了。于是看了下git提交记录发现做权限的同事新提交了一个配置文件,于是很快定位到这行代码。

  @Bean
  public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
    DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    advisorAutoProxyCreator.setProxyTargetClass(true);
    return advisorAutoProxyCreator;
  }

原因:shiroFilterFactoryBean实现了FactoryBean接口,所以它会提前被初始化。又因为SecurityManager依赖于Realm实现类、Realm实现类又依赖于用户服务,用户服务依赖一些其他服务,所以引发所有相关的bean提前初始化,导致这些service并没有被事务AOP包裹着,所以就出现了事务无效的问题.

解决方法:1.在该配置类文件注入用户服务上面加@Lazy标签,懒加载。2.使用userMapper替换userService。

ps:网上还有种说可以使用监听器的方式可以解决,我这里没有做实验

如果监听器方式可以,推荐使用监听器那种方式,这里不推荐使用第二种使用mapper替换service,因为直接与数据源交互,并且service里面可能还包含一些业务逻辑。

猜你喜欢

转载自blog.csdn.net/qq_33302985/article/details/107659497