Spring事务失效-十宗罪

文章讲述了Spring中@Transactional注解的事务管理可能失效的多种情况,包括访问修饰符限制、静态与final方法、异常类型不匹配、数据表存储引擎不支持事务、类未被Spring管理、异常处理不当、this调用问题、缺少事务管理器配置、事务传播类型和多线程调用等,并提供了相应的解决方案。
摘要由CSDN通过智能技术生成

1.事务方法访问修饰符非public

@Transactional
private void method{

   // 业务逻辑处理......
   // 事务不生效......
}

@Transactional
protected void method{

   // 业务逻辑处理......
   // 事务不生效......
}

2.修饰符static、final修饰的,同样无法通过动态代理,事务也是不会生效

Spring的声明式事务是基于动态代理实现的,我们无法重写final修饰的方法;

不管是JDK动态代理还是Cglib的动态代理,就是要通过代理的方式获取到代理的具体对象,而static方法修饰的方法是属于类的,不属于任何对象,所以static方法不能被重写,即便写法上是重写,但是并不具备重写的含义,也就是说static方法也不被进行动态代理。

3.@Transactional注解的方法抛出的异常不是spring的事务支持的异常,导致事务失效

  方式一:使用@Transactional(rollbackFor=Exception.class)指定拦截异常。

  方式二:throw new RuntimeException("抛出运行时异常") 抛出spring事务支持的异常

                spring的事务只支持未检查异常(unchecked),不支持已检查异常(checked)

4.数据表本身是不支持事务,导致事务失效

  如果使用MySQL且存储引擎是MyISAM,则事务是不起作用的,原因是MyIASM不支持事务,

可以改为InnoDB存储引擎,支持事务。

5.@Transactional注解所在的类没有被spring管理,导致事务失效

未将类加入spring容器管理,例如未使用@Service @Component等,未使用其他能注册

成 Spring Bean的方式或注解。

6.捕获了异常之后,没有再次抛出异常,导致事务未拦截到异常,事务失效

如果在加有事务的方法内,使用了try…catch…语句块对异常进行了捕获,而catch语句块没有throw new RuntimeException异常或者Spring支持的异常类型,则事务不会回滚。

7.this调用问题,导致事务失效

情况一:同一类中,非事务方法使用this.调用事务方法

情况二:被调用方法重新开启了新的事务

原因:因为spring事务是基于AOP实现的,而AOP的实现是基于动态代理,this是自己调自己,并不存在代理对象的调用,这样AOP不起作用导致事务注解失效。

解决方法:

a.将被调用类放入其他类进行调用

b.自己注入自己,用注入的实例来调用

c.使用AopContext.currentProxy()将this调用改成动态代理调用

d.被调用的方法去掉事务注解,直接加入调用它的方法的事务里面

@Service
public class UserServiceImpl implements UserService{

    // 自己注入自己
    @Autowired
    private UserService userService;

    // 方式一
    public void insert(User user){
     // 调用方法
     
     // 注意:这里不使用this调用,而是@Autowired自己(UserService)注入,然后调用事务方法
     userService.insertUser(user);

   }


   // 方式二
    public void insert(User user){
     // 调用方法
     
     // 获取代理类,利用代理类调用自己类的方法
     UserServiceImpl proxy = (UserServiceImpl) AopContext.currentProxy();
     proxy.insertUser(user);

   }


   @Transactional
   @Override
   public void insertUser(User user){
     // 被调用方法
    
   }

}

8.数据源没有配置事务管理器,导致事务失效

9.事务传播类型不支持事务,导致事务失效

例如:使用了@Transactional(propagation=Propagation.NOT_SUPPORTED)非事务方式等。

10.多线程调用,导致事务失效

两个方法不在同一个线程中,获取到的数据连接不一样,从而是两个不同的事务。我们说的

同一事务,实际是指同一数据库连接,拥有同一数据库连接才能同时提交和回滚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值