最近有同学给我说他的spring配置是正确的,但是发现有的事务生效,有的事务不生效,我第一直觉就是他的写法可能有问题。后来我总结一些事务不生效的场景。
spring事务分两种,一种注解事务,另一种编程式事务。我们一般使用注解事务@Transactional。注解实现原理是基于AOP,而AOP基于代理拦截做的,另外事务的传递是利用ThreadLocal,所以必须满足三个条件事务才能生效:
1,被调用的方法不能在同一个类中;
2,被调用的方法必须是public类型的;
3,被调用的方法不能跨线程;
4,回滚的时候,异常不能被捕获;
我用代码说明下:
1,被调用的方法不能在同一个类中:因为事务注解基于代理实现,如果调用方法和被调用的方法在同一个类中,是平级调用不能生效
public void save1(){
save2();
}
@Transactional
public void save2(){
//写库,事务是不生效的
}
2,被调用的方法不能跨线程,因为内部事务传递是利用ThreadLocal实现的,所以不能第二个事务是失效的
public void update(){
//生效
order.withdrawOrderSubmit(null);
//失效
ExecutorService pool = Executors.newFixedThreadPool(5);
pool.execute(()->order.withdrawOrderSubmit(null));
}
3,数据回滚的时候异常不能被捕获,必须把异常抛出来
@Transactional
public void save2() {
try {
//这种情况,事务是无法回滚的
order.withdrawOrderSubmit(null);
} catch (Exception e) {
log.error("异常",e);
}
}