每日一博 - 常见的Spring事务失效&事物不回滚案例集锦

文章目录

每日一博 - 常见的Spring事务失效&事物不回滚案例集锦


事务不生效

每日一博 - 常见的Spring事务失效&事物不回滚案例集锦

方法内部调用

有时候我们需要在某个Service类的某个方法中,调用另外一个事务方法

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @Transactional
    public void add(UserModel userModel) {
        userMapper.insertUser(userModel);
        updateStatus(userModel);
    }

    @Transactional
    public void updateStatus(UserModel userModel) {
        doSameThing();
    }
}

在事务方法add中,直接调用事务方法updateStatus。 updateStatus方法拥有事务的能力是因为spring aop生成代理了对象,但是这种方法直接调用了this对象的方法,所以updateStatus方法不会生成事务

由此可见,在同一个类中的方法直接内部调用,会导致事务失效。

那么问题来了,如果有些场景,确实想在同一个类的某个方法中,调用它自己的另外一个方法,该怎么办呢?

每日一博 - 常见的Spring事务失效&事物不回滚案例集锦

修复方法一 : 【新加一个Service方法】

只需要新加一个Service方法,把@Transactional注解加到新Service方法上,把需要事务执行的代码移到新方法中。

具体代码如下:

@Servcie
public class ServiceA {
   @Autowired
   prvate ServiceB serviceB;

   @Transactional
   public void save(User user) {
         queryData1();
         queryData2();
         serviceB.doSave(user);
   }
 }

 @Servcie
 public class ServiceB {

    @Transactional(rollbackFor=Exception.class)
    public void doSave(User user) {
       addData1();
       updateData2();
    }

 }

修复方法二:【在该Service类中注入自己】

如果不想再新加一个Service类,在该Service类中注入自己也是一种选择。

具体代码如下:

@Servcie
public class ServiceA {
   @Autowired
   prvate ServiceA serviceA;

  @Transactional
   public void save(User user) {
         queryData1();
         queryData2();
         serviceA.doSave(user);
   }

   @Transactional(rollbackFor=Exception.class)
   public void doSave(User user) {
       addData1();
       updateData2();
    }
 }

注入自己 spring ioc内部的三级缓存保证了它,不会出现循环依赖问题。


修复方法三:【通过AopContent类】<---- 推荐

在该Service类中使用AopContext.currentProxy()获取代理对象

上面的方法2确实可以解决问题,但是代码看起来并不直观,还可以通过在该Service类中使用AOPProxy获取代理对象,实现相同的功能。具体代码如下:

@Servcie
public class ServiceA {

	@Transactional
   public void save(User user) {
         queryData1();
         queryData2();
         ((ServiceA)AopContext.currentProxy()).doSave(user);
   }

   @Transactional(rollbackFor=Exception.class)
   public void doSave(User user) {
       addData1();
       updateData2();
    }
 }

访问权限问题

方法用final修饰

未被spring管理

多线程调用

表不支持事务

未开启事务


事务不回滚

每日一博 - 常见的Spring事务失效&事物不回滚案例集锦

错误的传播特性

自己吞了异常

手动抛了别的异常

自定义了回滚异常

嵌套事务回滚多了


其他常见问题

每日一博 - 常见的Spring事务失效&事物不回滚案例集锦

编程式事务

大事务问题

每日一博 - 常见的Spring事务失效&事物不回滚案例集锦

上一篇:2021-10-20


下一篇:[深入React] 7.组件生命周期