常见的Spring事务失效常见的几种情况

事务失效的7种情况

1 未启用spring事务管理功能

在启动类上加@EnableTransactionManagement

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

2 方法不是public类型的

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

3 数据源未配置事务管理器

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

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}

4 自身调用问题

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

@Component
public class testService {
    public void a(){
        this.b();
    }
    
    @Transactional
    public void b(){
        
    }
}

以上例子事务是不会生效的,由于a方法是通过this调用b方法,而this并非是代理对象 所以不是不会被事务拦截器拦截的,因此事务是无效的,如果外部通过testService的bean调用b 事务是有效的

若是想使得a调用b事务有效,可以用以下方法

@Component
public class TestService {
    @Autowired //@1
    private TestService testService;

    public void () {
        this.testService.m2();
    }

    @Transactional
    public void b() {
       
    }
}

5 异常类型错误

默认情况下,RuntimeException和Error的情况下,spring事务才会回滚。

也可以通过rollbackFor 属性指定 自定义回滚的异常类型:

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

6 异常被吞了

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

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

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

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

你可能感兴趣的:(spring,spring,java,后端)