Java教程

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

本文主要是介绍每日一博 - 常见的Spring事务失效&事物不回滚案例集锦,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

  • 事务不生效
    • 方法内部调用
      • 修复方法一 : 【新加一个Service方法】
      • 修复方法二:【在该Service类中注入自己】
      • 修复方法三:【通过AopContent类】<---- 推荐
    • 访问权限问题
    • 方法用final修饰
    • 未被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方法不会生成事务

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

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

在这里插入图片描述

修复方法一 : 【新加一个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事务失效&事物不回滚案例集锦的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!