Spring事务失效几个场景
  omwAZRkoq0En 2023年11月02日 39 0

1.1、未启用spring事务管理功能

@EnableTransactionManagement 注解用来启用spring事务自动管理事务的功能,这个注解千万不要忘记写了。

1.2、方法不是public类型的

@Transaction 可以用在类上、接口上、public方法上,如果将@Trasaction用在了非public方法上,事务将无效。

1.3、数据源未配置事务管理器

spring是通过事务管理器了来管理事务的,一定不要忘记配置事务管理器了,要注意为每个数据源配置一个事务管理器:

  1. @Bean
  2. public PlatformTransactionManager transactionManager(DataSource dataSource) {
  3.     return new DataSourceTransactionManager(dataSource);
  4. }

1.4、自身调用问题

spring是通过aop的方式,对需要spring管理事务的bean生成了代理对象,然后通过代理对象拦截了目标方法的执行,在方法前后添加了事务的功能,所以必须通过代理对象调用目标方法的时候,事务才会起效。

看下面代码,大家思考一个问题:当外部直接调用m1的时候,m2方法的事务会生效么?

  1. @Component
  2. public class UserService {
  3.     public void m1(){
  4.         this.m2();
  5.     }
  6.     
  7.     @Transactional
  8.     public void m2(){
  9.         //执行db操作
  10.     }
  11. }

显然不会生效,因为m1中通过this的方式调用了m2方法,而this并不是代理对象,this.m2()不会被事务拦截器,所以事务是无效的,如果外部直接调用通过UserService这个bean来调用m2方法,事务是有效的,上面代码可以做一下调整,如下,@1在UserService中注入了自己,此时m1中的m2事务是生效的

  1. @Component
  2. public class UserService {
  3.     @Autowired //@1
  4.     private UserService userService;

  5.     public void m1() {
  6.         this.userService.m2();
  7.     }

  8.     @Transactional
  9.     public void m2() {
  10.         //执行db操作
  11.     }
  12. }

重点:必须通过代理对象访问方法,事务才会生效。

1.5、异常类型错误

spring事务回滚的机制:对业务方法进行try catch,当捕获到有指定的异常时,spring自动对事务进行回滚,那么问题来了,哪些异常spring会回滚事务呢?

并不是任何异常情况下,spring都会回滚事务,默认情况下,RuntimeException和Error的情况下,spring事务才会回滚。

也可以自定义回滚的异常类型:

@Transactional(rollbackFor = {异常类型列表})

1.6、异常被吞了

当业务方法抛出异常,spring感知到异常的时候,才会做事务回滚的操作,若方法内部将异常给吞了,那么事务无法感知到异常了,事务就不会回滚了。

如下代码,事务操作2发生了异常,但是被捕获了,此时事务并不会被回滚

  1. @Transactional
  2. public void m1(){
  3.     事务操作1
  4.     try{
  5.         事务操作2,内部抛出了异常
  6.     }catch(Exception e){
  7.         
  8.     }
  9. }

1.7、业务和spring事务代码必须在一个线程中

spring事务实现中使用了ThreadLocal,ThreadLocal大家应该知道吧,可以实现同一个线程中数据共享,必须是同一个线程的时候,数据才可以共享,这就要求业务代码必须和spring事务的源码执行过程必须在一个线程中,才会受spring事务的控制,比如下面代码,方法内部的子线程内部执行的事务操作将不受m1方法上spring事务的控制,这个大家一定要注意

  1. @Transactional
  2. public void m1() {
  3.     new Thread() {
  4.         一系列事务操作
  5.     }.start();
  6. }
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  2nTRIltqfA7y   2023年12月23日   25   0   0 MVCspringMVCspring
  MaQcYKL86nCD   2023年12月22日   40   0   0 springspring
omwAZRkoq0En
作者其他文章 更多