如何详细探究Spring框架中的事务传播策略?

2026-05-25 20:371阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2541个文字,预计阅读时间需要11分钟。

如何详细探究Spring框架中的事务传播策略?

目录 + Spring 事务传播机制有哪些? + 事务传播机制使用与示例 + REQUIRED + 使用示例 + REQUIRED_NEW + 使用示例 + NEW + 使用示例 + NESTED + 使用示例 + 总结 + Spring 事务传播机制是指,包含多个事务的方法在相互调用时,如何管理事务的边界和传播行为。

目录
  • Spring 事务传播机制有哪些?
  • 事务传播机制使用与演示
    • REQUIRED 使用演示
    • REQUIRED_NEW 使用演示
    • NESTED 使用演示
  • 总结

    Spring 事务传播机制是指,包含多个事务的方法在相互调用时,事务是如何在这些方法间传播的。

    既然是“事务传播”,所以事务的数量应该在两个或两个以上,Spring 事务传播机制的诞生是为了规定多个事务在传播过程中的行为的。比如方法 A 开启了事务,而在执行过程中又调用了开启事务的 B 方法,那么 B 方法的事务是应该加入到 A 事务当中呢?还是两个事务相互执行互不影响,又或者是将 B 事务嵌套到 A 事务中执行呢?所以这个时候就需要一个机制来规定和约束这两个事务的行为,这就是 Spring 事务传播机制所解决的问题。

    Spring 事务传播机制有哪些?

    Spring 事务传播机制可使用 @Transactional(propagation=Propagation.REQUIRED) 来定义,Spring 事务传播机制的级别包含以下 7 种:

    • Propagation.REQUIRED:默认的事务传播级别,它表示如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
    • Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
    • Propagation.MANDATORY:(mandatory:强制性)如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
    • Propagation.REQUIRES_NEW:表示创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
    • Propagation.NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
    • Propagation.NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
    • Propagation.NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 PROPAGATION_REQUIRED。

    以上 7 种传播机制,可根据“是否支持当前事务”的维度分为以下 3 类:

    看到这里,有人可能会说:说了这么多,我也看不懂啊,即使看懂了,我也记不住啊?这要咋整?

    没关系,接下来我们用一个例子,来说明这 3 类事务传播机制的区别。

    以情侣之间是否要买房为例,我们将以上 3 类事务传播机制可以看作是恋爱中的 3 类女生类型:

    • 普通型
    • 强势型
    • 懂事型

    这三类女生如下图所示:

    支持当前事务的“女生”,这里的事务指的是“房子”,它分为 3 种(普通型女生):

    • Propagation.REQUIRED(需要有房子):有房子了咱们一起住,没房子了咱们一起赚钱买房子。
    • Propagation.SUPPORTS(可以有房子):有房子了就一起住,没房子了咱们就一起租房子。
    • Propagation.MANDATORY(强制有房子):有房子了就一起住,没房子了就分手。

    不支持当前事务的“女生”也分为 3 种(强势型或者叫事业型):

    • Propagation.REQUIRES_NEW:不要你的房子,必须一起赚钱买房子。
    • Propagation.NOT_SUPPORTED:不要你的房子,必须一起租房子。
    • Propagation.NEVER:必须一起租房子,你有房子就分手。

    最后一种是嵌套性事务 Propagation.NESTED,它属于懂事型女友,如果有房子了就以房子为基础做点小生意,卖个花生、水果啥的,如果买卖成了,那就继续发展;如果失败了,至少还有房子;如果没房子也没关系,一起赚钱买房子。

    如何详细探究Spring框架中的事务传播策略?

    事务传播机制使用与演示

    接下来我们演示一下事务传播机制的使用,以下面 3 个最典型的事务传播级别为例:

    • 支持当前事务的 REQUIRED;
    • 不支持当前事务的 REQUIRES_NEW;
    • 嵌套事务 NESTED。

    下来我们分别来看。

    事务传播机制的示例,需要用到以下两张表:

    -- 用户表 CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL, `password` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL, `createtime` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC; -- 日志表 CREATE TABLE `log` ( `id` int(11) NOT NULL AUTO_INCREMENT, `content` text NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

    创建一个 Spring Boot 项目,核心业务代码有 3 个:UserController、UserServcie 以及 LogService。在 UserController 里面调用 UserService 添加用户,并调用 LogService 添加日志。

    REQUIRED 使用演示

    REQUIRED 支持当前事务。

    UserController 实现代码如下,其中 save 方法开启了事务:

    @RestController public class UserController { @Resource private UserService userService; @Resource private LogService logService; @RequestMapping("/save") @Transactional public Object save(User user) { // 插入用户操作 userService.save(user); // 插入日志 logService.saveLog("用户插入:" + user.getName()); return true; } }

    UserService 实现代码如下:

    @Service public class UserService { @Resource private UserMapper userMapper; @Transactional(propagation = Propagation.REQUIRED) public int save(User user) { return userMapper.save(user); } }

    LogService 实现代码如下:

    @Service public class LogService { @Resource private LogMapper logMapper; @Transactional(propagation = Propagation.REQUIRED) public int saveLog(String content) { // 出现异常 int i = 10 / 0; return logMapper.saveLog(content); } }

    执行结果:程序报错,两张表中都没有插入任何数据。

    执行流程描述:

    • 首先 UserService 中的添加用户方法正常执行完成。
    • LogService 保存日志程序报错,因为使用的是 UserController 中的全局事务,所以整个事务回滚,步骤 1 中的操作也跟着回滚。
    • 所以数据库中没有添加任何数据。

    REQUIRED_NEW 使用演示

    REQUIRED_NEW 不支持当前事务。

    UserController 实现代码:

    @RequestMapping("/save") @Transactional public Object save(User user) { // 插入用户操作 userService.save(user); // 插入日志 logService.saveLog("用户插入:" + user.getName()); return true; }

    UserService 实现代码:

    @Service public class UserService { @Resource private UserMapper userMapper; @Transactional(propagation = Propagation.REQUIRES_NEW) public int save(User user) { System.out.println("执行 save 方法."); return userMapper.save(user); } }

    LogService 实现代码:

    @Service public class LogService { @Resource private LogMapper logMapper; @Transactional(propagation = Propagation.REQUIRES_NEW) public int saveLog(String content) { // 出现异常 int i = 10 / 0; return logMapper.saveLog(content); } }

    程序执行结果:

    User 表中成功添加了一条用户数据,Log 表执行失败,没有加入任何数据,但它并没有影响到 UserController 中的事务执行。

    通过以上结果可以看出:LogService 中使用的是单独的事务,虽然 LogService 中的事务执行失败了,但并没有影响 UserController 和 UserService 中的事务。

    NESTED 使用演示

    NESTED 是嵌套事务。

    UserController 实现代码如下:

    @RequestMapping("/save") @Transactional public Object save(User user) { // 插入用户操作 userService.save(user); return true; }

    UserService 实现代码如下:

    @Transactional(propagation = Propagation.NESTED) public int save(User user) { int result = userMapper.save(user); System.out.println("执行 save 方法."); // 插入日志 logService.saveLog("用户插入:" + user.getName()); return result; }

    LogService 实现代码如下:

    @Transactional(propagation = Propagation.NESTED) public int saveLog(String content) { // 出现异常 int i = 10 / 0; return logMapper.saveLog(content); }

    最终执行结果,用户表和日志表都没有添加任何数据。

    执行流程描述:

    • UserController 中调用了 UserService 的添加用户方法,UserService 使用 NESTED 循环嵌套事务,并成功执行了添加用户的方法。
    • UserService 中调用了 LogService 的添加方法,LogService 使用了 NESTED 循环嵌套事务,但在方法执行中出现的异常,因此回滚了当前事务。
    • 因为 UserService 使用的是嵌套事务,所以发生回滚的事务是全局的,也就是说 UserService 中的添加用户方法也被回滚了,最终执行结果是用户表和日志表都没有添加任何数据。

    总结

    Spring 事务传播机制是包含多个事务的方法在相互调用时,事务是如何在这些方法间传播的。事务的传播级别有 7 个,支持当前事务的:REQUIRED、SUPPORTS、MANDATORY;不支持当前事务的:REQUIRES_NEW、NOT_SUPPORTED、NEVER,以及嵌套事务 NESTED,其中 REQUIRED 是默认的事务传播级别。

    以上就是深入了解Spring的事务传播机制的详细内容,更多关于Spring事务传播机制的资料请关注自由互联其它相关文章!

    本文共计2541个文字,预计阅读时间需要11分钟。

    如何详细探究Spring框架中的事务传播策略?

    目录 + Spring 事务传播机制有哪些? + 事务传播机制使用与示例 + REQUIRED + 使用示例 + REQUIRED_NEW + 使用示例 + NEW + 使用示例 + NESTED + 使用示例 + 总结 + Spring 事务传播机制是指,包含多个事务的方法在相互调用时,如何管理事务的边界和传播行为。

    目录
    • Spring 事务传播机制有哪些?
    • 事务传播机制使用与演示
      • REQUIRED 使用演示
      • REQUIRED_NEW 使用演示
      • NESTED 使用演示
    • 总结

      Spring 事务传播机制是指,包含多个事务的方法在相互调用时,事务是如何在这些方法间传播的。

      既然是“事务传播”,所以事务的数量应该在两个或两个以上,Spring 事务传播机制的诞生是为了规定多个事务在传播过程中的行为的。比如方法 A 开启了事务,而在执行过程中又调用了开启事务的 B 方法,那么 B 方法的事务是应该加入到 A 事务当中呢?还是两个事务相互执行互不影响,又或者是将 B 事务嵌套到 A 事务中执行呢?所以这个时候就需要一个机制来规定和约束这两个事务的行为,这就是 Spring 事务传播机制所解决的问题。

      Spring 事务传播机制有哪些?

      Spring 事务传播机制可使用 @Transactional(propagation=Propagation.REQUIRED) 来定义,Spring 事务传播机制的级别包含以下 7 种:

      • Propagation.REQUIRED:默认的事务传播级别,它表示如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
      • Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
      • Propagation.MANDATORY:(mandatory:强制性)如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
      • Propagation.REQUIRES_NEW:表示创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
      • Propagation.NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
      • Propagation.NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
      • Propagation.NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 PROPAGATION_REQUIRED。

      以上 7 种传播机制,可根据“是否支持当前事务”的维度分为以下 3 类:

      看到这里,有人可能会说:说了这么多,我也看不懂啊,即使看懂了,我也记不住啊?这要咋整?

      没关系,接下来我们用一个例子,来说明这 3 类事务传播机制的区别。

      以情侣之间是否要买房为例,我们将以上 3 类事务传播机制可以看作是恋爱中的 3 类女生类型:

      • 普通型
      • 强势型
      • 懂事型

      这三类女生如下图所示:

      支持当前事务的“女生”,这里的事务指的是“房子”,它分为 3 种(普通型女生):

      • Propagation.REQUIRED(需要有房子):有房子了咱们一起住,没房子了咱们一起赚钱买房子。
      • Propagation.SUPPORTS(可以有房子):有房子了就一起住,没房子了咱们就一起租房子。
      • Propagation.MANDATORY(强制有房子):有房子了就一起住,没房子了就分手。

      不支持当前事务的“女生”也分为 3 种(强势型或者叫事业型):

      • Propagation.REQUIRES_NEW:不要你的房子,必须一起赚钱买房子。
      • Propagation.NOT_SUPPORTED:不要你的房子,必须一起租房子。
      • Propagation.NEVER:必须一起租房子,你有房子就分手。

      最后一种是嵌套性事务 Propagation.NESTED,它属于懂事型女友,如果有房子了就以房子为基础做点小生意,卖个花生、水果啥的,如果买卖成了,那就继续发展;如果失败了,至少还有房子;如果没房子也没关系,一起赚钱买房子。

      如何详细探究Spring框架中的事务传播策略?

      事务传播机制使用与演示

      接下来我们演示一下事务传播机制的使用,以下面 3 个最典型的事务传播级别为例:

      • 支持当前事务的 REQUIRED;
      • 不支持当前事务的 REQUIRES_NEW;
      • 嵌套事务 NESTED。

      下来我们分别来看。

      事务传播机制的示例,需要用到以下两张表:

      -- 用户表 CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL, `password` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL, `createtime` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC; -- 日志表 CREATE TABLE `log` ( `id` int(11) NOT NULL AUTO_INCREMENT, `content` text NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

      创建一个 Spring Boot 项目,核心业务代码有 3 个:UserController、UserServcie 以及 LogService。在 UserController 里面调用 UserService 添加用户,并调用 LogService 添加日志。

      REQUIRED 使用演示

      REQUIRED 支持当前事务。

      UserController 实现代码如下,其中 save 方法开启了事务:

      @RestController public class UserController { @Resource private UserService userService; @Resource private LogService logService; @RequestMapping("/save") @Transactional public Object save(User user) { // 插入用户操作 userService.save(user); // 插入日志 logService.saveLog("用户插入:" + user.getName()); return true; } }

      UserService 实现代码如下:

      @Service public class UserService { @Resource private UserMapper userMapper; @Transactional(propagation = Propagation.REQUIRED) public int save(User user) { return userMapper.save(user); } }

      LogService 实现代码如下:

      @Service public class LogService { @Resource private LogMapper logMapper; @Transactional(propagation = Propagation.REQUIRED) public int saveLog(String content) { // 出现异常 int i = 10 / 0; return logMapper.saveLog(content); } }

      执行结果:程序报错,两张表中都没有插入任何数据。

      执行流程描述:

      • 首先 UserService 中的添加用户方法正常执行完成。
      • LogService 保存日志程序报错,因为使用的是 UserController 中的全局事务,所以整个事务回滚,步骤 1 中的操作也跟着回滚。
      • 所以数据库中没有添加任何数据。

      REQUIRED_NEW 使用演示

      REQUIRED_NEW 不支持当前事务。

      UserController 实现代码:

      @RequestMapping("/save") @Transactional public Object save(User user) { // 插入用户操作 userService.save(user); // 插入日志 logService.saveLog("用户插入:" + user.getName()); return true; }

      UserService 实现代码:

      @Service public class UserService { @Resource private UserMapper userMapper; @Transactional(propagation = Propagation.REQUIRES_NEW) public int save(User user) { System.out.println("执行 save 方法."); return userMapper.save(user); } }

      LogService 实现代码:

      @Service public class LogService { @Resource private LogMapper logMapper; @Transactional(propagation = Propagation.REQUIRES_NEW) public int saveLog(String content) { // 出现异常 int i = 10 / 0; return logMapper.saveLog(content); } }

      程序执行结果:

      User 表中成功添加了一条用户数据,Log 表执行失败,没有加入任何数据,但它并没有影响到 UserController 中的事务执行。

      通过以上结果可以看出:LogService 中使用的是单独的事务,虽然 LogService 中的事务执行失败了,但并没有影响 UserController 和 UserService 中的事务。

      NESTED 使用演示

      NESTED 是嵌套事务。

      UserController 实现代码如下:

      @RequestMapping("/save") @Transactional public Object save(User user) { // 插入用户操作 userService.save(user); return true; }

      UserService 实现代码如下:

      @Transactional(propagation = Propagation.NESTED) public int save(User user) { int result = userMapper.save(user); System.out.println("执行 save 方法."); // 插入日志 logService.saveLog("用户插入:" + user.getName()); return result; }

      LogService 实现代码如下:

      @Transactional(propagation = Propagation.NESTED) public int saveLog(String content) { // 出现异常 int i = 10 / 0; return logMapper.saveLog(content); }

      最终执行结果,用户表和日志表都没有添加任何数据。

      执行流程描述:

      • UserController 中调用了 UserService 的添加用户方法,UserService 使用 NESTED 循环嵌套事务,并成功执行了添加用户的方法。
      • UserService 中调用了 LogService 的添加方法,LogService 使用了 NESTED 循环嵌套事务,但在方法执行中出现的异常,因此回滚了当前事务。
      • 因为 UserService 使用的是嵌套事务,所以发生回滚的事务是全局的,也就是说 UserService 中的添加用户方法也被回滚了,最终执行结果是用户表和日志表都没有添加任何数据。

      总结

      Spring 事务传播机制是包含多个事务的方法在相互调用时,事务是如何在这些方法间传播的。事务的传播级别有 7 个,支持当前事务的:REQUIRED、SUPPORTS、MANDATORY;不支持当前事务的:REQUIRES_NEW、NOT_SUPPORTED、NEVER,以及嵌套事务 NESTED,其中 REQUIRED 是默认的事务传播级别。

      以上就是深入了解Spring的事务传播机制的详细内容,更多关于Spring事务传播机制的资料请关注自由互联其它相关文章!