Spring事务注解失效的几种场景

Spring中事务注解@Transactional在一些情况下会失效,主要介绍几种可能导致事务注解失效的场景。

场景一:同类方法嵌套调用

Spring可以通过动态代理进行类增强,A类中A方法未加注解,A类中B方法加了@Transactional注解,那么如果从A入口调用B方法,会导致事务注解失效。伪代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void testA(){
System.out.println("调用本类A方法");
testB();
}
@Transactional(rollbackFor = Exception.class)
public void testB() {
//更新第一个
ShipmentDO shipmentDO=new ShipmentDO();
shipmentDO.setShipmentId(36156474);
shipmentDO.setPackboxIsOut("Y");
shipmentMapper.update(shipmentDO);
//模拟抛出异常
String string=null;
String A="A";
if (string.equals(A)){

}
//更新第二个
ShipmentDO shipmentDO1=new ShipmentDO();
shipmentDO1.setShipmentId(36156846);
shipmentDO1.setPackboxIsOut("Y");
shipmentMapper.update(shipmentDO1);
}

这段代码的结果是第一个更新操作成功写入,说明testB方法并没有达到事务控制的效果。如果我们需要达到事务控制的效果,需要从testB直接进入。

场景一总结

  • spring采用动态代理(AOP)实现对Bean的管理和切片, 它为我们的每个class生成一个代理对象, 只有在代理对象之间进行调用时, 可以触发切面逻辑
  • 在同一个类中, 方法B调用A, 调用的是当前对象的方法, 而不是通过代理对象, 所以spring无法切到这次调用, 也就是无法通过注解保证事务性
  • 通过SpringUtil.getBean(this.class)获取当前类的代理对象