Spring事务失效的几种场景

发布于:2025-02-20 ⋅ 阅读:(140) ⋅ 点赞:(0)

往期推荐

符号引用和直接引用、强引用、软引用、弱引用、虚引用-CSDN博客

已老实!再学消息队列、死信队列-CSDN博客

synchronized如何实现可重入,和Lock区别-CSDN博客

Mysql索引失效的几种场景、回表、索引覆盖、索引下推-CSDN博客

1. 未启用Spring事务管理功能或bean没有被spring管理

2. @Transactional修饰的方法非public或被final、static修饰

3. 同类的方法A直接调用同类的事务方法B

spring事务是通过Spring AOP实现的,对需要spring管理事务的bean生成了代理对象,然后通过代理对象拦截了目标方法的执行,在方法前后添加了事务的功能,所以必须通过代理对象调用目标方法的时候,事务才会起效。如果方法A直接调用方法B则是this调用,即该类的类对象,就不是代理对象。可以通过Service 类中注入自己,或者通过AopContext.currentProxy()获取代理对象来解决。

4. 抛出的异常类型错误

在业务方法进行异常抛出,spring会自动对事务进行回滚,那么问题来了,抛出哪些异常spring会回滚事务呢?默认情况下,spring遇到RuntimeException和Error的事务才会回滚。因为spring认为RuntimeException和Error是不可预期的错误,而而受检异常是可预期的错误,可以通过业务逻辑即可解决。

当然也可以自定义回滚异常类型@Transactional(rollbackFor = {异常类型列表})

5. 异常被捕获处理

spring感知到指定异常被抛出才会进行回滚,如果在方法内部捕获处理掉异常,事务就不会回滚

@Transactional
public void m1(){
    事务操作1
    try{
        事务操作2,内部抛出了异常
    }catch(Exception e){
     log.error(....)   
    }
}

正确做法是捕获处理掉异常后抛出来,如下:

@Transactional
public void m1(){
    事务操作1
    try{
        事务操作2,内部抛出了异常
    }catch(Exception e){
     log.error(....)   
     throw e
    }
}

6. 事务操作和@Transactional方法不在同一线程

@Transactional
public void m1() {
    new Thread() {
        一系列事务操作
    }.start();
}

7. 事务传播行为设置不对

spring默认事务传播行为默认是required,事务方法A内部调用事务方法B,如果方法A存在事务则方法B加入方法A的事务,否则创建新事务。如果非事务方法A调用事务方法B,事务传播级别为NOT_SUPPORT,因为方法A当前不存在事务,则方法B虽然有@Transactional注解,但仍然以非事务去执行。


网站公告

今日签到

点亮在社区的每一天
去签到