您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

大白话解读Spring事务传播原理

时间:2023-05-06 11:30:09  来源:  作者:知其然亦知其所以然

大家好,我是小米,一个热爱技术分享的程序员。今天我们来谈一下Spring事务传播。在使用Spring进行数据库操作时,我们经常会遇到需要使用事务的情况,而Spring对事务的管理非常方便,其中就包括事务传播机制。

 

什么是事务传播

事务传播指的是在一个方法调用另一个方法时,事务应该如何进行传播。在Spring框架中,事务传播有多种策略,它们用于控制不同方法之间事务的关系。在使用Spring事务的时候,我们需要了解这些事务传播机制的特点和使用场景,以便更好地控制事务的传播和管理。

事务的不同分类

Spring事务传播机制根据传播的不同情况,可以分为三类:支持当前事务、不支持当前事务、嵌套事务。

支持当前事务:是指当前方法需要在一个事务内执行,如果当前没有事务,则创建一个新的事务。如果当前存在事务,则沿用当前事务。

不支持当前事务:是指当前方法需要在没有事务的情况下执行,如果当前存在事务,则挂起当前事务,执行当前方法,执行完毕后再恢复原先的事务。

嵌套事务:是指在当前事务中开启一个新的事务,这个新的事务可以看做是当前事务的子事务。如果当前没有事务,则创建一个新的事务。

 

事务的传播方式

Spring事务的传播方式用的比较多的是以下三种:

  • Required(默认):表示当前方法必须在一个事务内执行,如果当前没有事务,则新开启一个事务,如果当前存在事务,则沿用当前事务。它是Spring事务传播机制的默认选项。这种事务传播机制的使用场景是:多个操作需要在同一事务中进行,例如对订单进行下单和扣款操作。
  • Requires_new:表示当前方法必须在一个新的事务中执行,如果当前存在事务,则挂起当前事务,开启新的事务,执行完毕后再恢复原先的事务。这种事务传播机制的使用场景是:需要将当前事务挂起,执行独立的操作,例如对商品进行库存调整和日志记录。
  • Nested:表示当前方法必须在一个嵌套事务中执行,如果当前没有事务,则新开启一个事务,如果当前存在事务,则在当前事务的基础上创建一个嵌套事务。这种事务传播机制的使用场景是:需要对当前事务进行子事务的操作,例如对订单进行部分退款操作。

 

需要注意的是,Nested只在当前事务是一个真正的事务时才有效,如果当前事务并不是一个真正的事务(例如使用TransactionDefinition.PROPAGATION_NOT_SUPPORTED或TransactionDefinition.PROPAGATION_NEVER时),Nested和Required的效果是一样的。

 

除了上述传播方式外,Spring还支持其他的传播方式,例如supports、not_supported、mandatory、never等,它们的作用和含义可以根据具体的业务场景进行选择和使用。

 

判断内外方法是否在同一事务

在使用Spring事务时,我们需要注意内部方法和外部方法是否在同一个事务中。

  • 如果内部方法和外部方法在同一个事务中,那么当内部方法发生异常时,外部方法也会受到影响,此时需要将异常统一在外层处理。
  • 如果内部方法和外部方法不在同一个事务中,那么内部方法的异常不会影响到外部方法,但是外部方法的异常可能会影响到内部方法。
  • 然而,Nested有一个特殊情况,即当内部方法使用Nested传播机制时,内部方法和外部方法不在同一个事务中,但是内部方法的异常仍然会影响到外部方法。

 

案例:内外方法在同一个事务

 

为了更好地理解Spring事务的传播机制,我们可以通过一个简单的电商项目来演示上述三种情况。

 

在该电商项目中,我们有两个Service,一个是OrderService,一个是GoodsService。OrderService负责生成订单,而GoodsService负责扣减库存。两个Service中都有一个reduceStock方法,用来扣减库存。在扣减库存的同时,我们还需要判断库存是否充足。如果库存不足,我们需要抛出一个RuntimeException。

 

首先,我们来看一下内部方法和外部方法在同一个事务中的情况。在这种情况下,我们可以使用required传播机制。具体实现如下:

 

 

 

 

 

图片

 

 

 

 

 

 

 

图片

 

 

在这个例子中,如果库存不足,会抛出一个RuntimeException,整个事务会回滚。如果扣减库存失败,同样会抛出一个RuntimeException,整个事务也会回滚。如果订单生成成功,整个事务会被提交。

 

 

 

 

案例:内外方法不在同一个事务

接下来,我们来看一下内部方法和外部方法不在同一个事务中的情况。在这种情况下,我们可以使用requires_new传播机制。具体实现如下:

 

 

 

 

 

图片

 

 

在这个例子中,我们将reduceStock方法的事务传播机制设置为REQUIRES_NEW。在执行该方法时,Spring会将当前事务挂起,创建一个新的事务来执行reduceStock方法。如果reduceStock方法执行成功,则会提交新的事务。如果reduceStock方法执行失败,则会回滚新的事务,但不会影响当前事务。 

 

在这个例子中,我们将需要扣减的库存数量加了1。这样在扣减库存时,就会发现库存不足。此时,reduceStock方法会抛出一个RuntimeException,新的事务会回滚,但当前事务不会受到影响。因此,订单生成成功,但库存并没有被扣减。 

 

 

 

 

嵌套事务

最后,我们来看一下嵌套事务的情况。在这种情况下,我们可以使用nested传播机制。具体实现如下:

 

 

 

 

 

 

在这个例子中,我们将reduceStock方法的事务传播机制设置为NESTED。在执行该方法时,Spring会创建一个嵌套事务来执行reduceStock方法。如果reduceStock方法执行成功,则嵌套事务会提交。如果reduceStock方法执行失败,则嵌套事务会回滚,但不会影响外层事务。

 

在这个例子中,我们在createOrder方法中调用了reduceStock方法,并将需要扣减的库存数量加了2。这样在扣减库存时,就会发现库存不足。此时,reduceStock方法会抛出一个RuntimeException,嵌套事务会回滚,但当前事务不会受到影响。因此,订单生成失败,库存也没有被扣减。

 

 

 

 

结论

综上所述,Spring事务传播机制提供了灵活的事务管理方式,可以根据不同的业务场景选择不同的传播机制来控制事务的行为。其中,REQUIRES_NEW和NESTED是比较特殊的传播机制,可以在需要的时候使用。

 

在使用Spring事务时,需要注意以下几点:

  • 事务传播机制的选择要根据业务场景来确定。
  • 如果内层方法和外层方法在同一个事务中,那么内层方法抛出异常时,异常应该由外层方法来处理。
  • 如果内层方法和外层方法在不同的事务中,那么内层方法抛出异常时,不会影响到外层方法。
  • NESTED传播机制是一种比较特殊的传播机制,需要慎重使用。

 

在实际开发中,我们需要根据不同的业务场景选择合适的事务传播机制,并且要根据实际情况来处理事务异常,以保证事务的正确执行。



Tags:Spring   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Spring Security:保障应用安全的利器
SpringSecurity作为一个功能强大的安全框架,为Java应用程序提供了全面的安全保障,包括认证、授权、防护和集成等方面。本文将介绍SpringSecurity在这些方面的特性和优势,以及它...【详细内容】
2024-02-27  Search: Spring  点击:(54)  评论:(0)  加入收藏
Spring Security权限控制框架使用指南
在常用的后台管理系统中,通常都会有访问权限控制的需求,用于限制不同人员对于接口的访问能力,如果用户不具备指定的权限,则不能访问某些接口。本文将用 waynboot-mall 项目举例...【详细内容】
2024-02-19  Search: Spring  点击:(39)  评论:(0)  加入收藏
详解基于SpringBoot的WebSocket应用开发
在现代Web应用中,实时交互和数据推送的需求日益增长。WebSocket协议作为一种全双工通信协议,允许服务端与客户端之间建立持久性的连接,实现实时、双向的数据传输,极大地提升了用...【详细内容】
2024-01-30  Search: Spring  点击:(16)  评论:(0)  加入收藏
Spring实现Kafka重试Topic,真的太香了
概述Kafka的强大功能之一是每个分区都有一个Consumer的偏移值。该偏移值是消费者将读取的下一条消息的值。可以自动或手动增加该值。如果我们由于错误而无法处理消息并想重...【详细内容】
2024-01-26  Search: Spring  点击:(86)  评论:(0)  加入收藏
SpringBoot如何实现缓存预热?
缓存预热是指在 Spring Boot 项目启动时,预先将数据加载到缓存系统(如 Redis)中的一种机制。那么问题来了,在 Spring Boot 项目启动之后,在什么时候?在哪里可以将数据加载到缓存系...【详细内容】
2024-01-19  Search: Spring  点击:(86)  评论:(0)  加入收藏
Spring Boot2.0深度实践 核心原理拆解+源码分析
Spring Boot2.0深度实践:核心原理拆解与源码分析一、引言Spring Boot是一个基于Java的轻量级框架,它简化了Spring应用程序的创建过程,使得开发者能够快速搭建一个可运行的应用...【详细内容】
2024-01-15  Search: Spring  点击:(95)  评论:(0)  加入收藏
SpringBoot3+Vue3 开发高并发秒杀抢购系统
开发高并发秒杀抢购系统:使用SpringBoot3+Vue3的实践之旅随着互联网技术的发展,电商行业对秒杀抢购系统的需求越来越高。为了满足这种高并发、高流量的场景,我们决定使用Spring...【详细内容】
2024-01-14  Search: Spring  点击:(91)  评论:(0)  加入收藏
Spring Boot 3.0是什么?
Spring Boot 3.0是一款基于Java的开源框架,用于简化Spring应用程序的构建和开发过程。与之前的版本相比,Spring Boot 3.0在多个方面进行了改进和增强,使其更加易用、高效和灵活...【详细内容】
2024-01-11  Search: Spring  点击:(133)  评论:(0)  加入收藏
GraalVM与Spring Boot 3.0:加速应用性能的完美融合
在2023年,SpringBoot3.0的发布标志着Spring框架对GraalVM的全面支持,这一支持是对Spring技术栈的重要补充。GraalVM是一个高性能的多语言虚拟机,它提供了Ahead-of-Time(AOT)编...【详细内容】
2024-01-11  Search: Spring  点击:(124)  评论:(0)  加入收藏
Spring Boot虚拟线程的性能还不如Webflux?
早上看到一篇关于Spring Boot虚拟线程和Webflux性能对比的文章,觉得还不错。内容较长,抓重点给大家介绍一下这篇文章的核心内容,方便大家快速阅读。测试场景作者采用了一个尽可...【详细内容】
2024-01-10  Search: Spring  点击:(115)  评论:(0)  加入收藏
▌简易百科推荐
Web Components实践:如何搭建一个框架无关的AI组件库
一、让人又爱又恨的Web ComponentsWeb Components是一种用于构建可重用的Web元素的技术。它允许开发者创建自定义的HTML元素,这些元素可以在不同的Web应用程序中重复使用,并且...【详细内容】
2024-04-03  京东云开发者    Tags:Web Components   点击:(8)  评论:(0)  加入收藏
Kubernetes 集群 CPU 使用率只有 13% :这下大家该知道如何省钱了
作者 | THE STACK译者 | 刘雅梦策划 | Tina根据 CAST AI 对 4000 个 Kubernetes 集群的分析,Kubernetes 集群通常只使用 13% 的 CPU 和平均 20% 的内存,这表明存在严重的过度...【详细内容】
2024-03-08  InfoQ    Tags:Kubernetes   点击:(12)  评论:(0)  加入收藏
Spring Security:保障应用安全的利器
SpringSecurity作为一个功能强大的安全框架,为Java应用程序提供了全面的安全保障,包括认证、授权、防护和集成等方面。本文将介绍SpringSecurity在这些方面的特性和优势,以及它...【详细内容】
2024-02-27  风舞凋零叶    Tags:Spring Security   点击:(54)  评论:(0)  加入收藏
五大跨平台桌面应用开发框架:Electron、Tauri、Flutter等
一、什么是跨平台桌面应用开发框架跨平台桌面应用开发框架是一种工具或框架,它允许开发者使用一种统一的代码库或语言来创建能够在多个操作系统上运行的桌面应用程序。传统上...【详细内容】
2024-02-26  贝格前端工场    Tags:框架   点击:(47)  评论:(0)  加入收藏
Spring Security权限控制框架使用指南
在常用的后台管理系统中,通常都会有访问权限控制的需求,用于限制不同人员对于接口的访问能力,如果用户不具备指定的权限,则不能访问某些接口。本文将用 waynboot-mall 项目举例...【详细内容】
2024-02-19  程序员wayn  微信公众号  Tags:Spring   点击:(39)  评论:(0)  加入收藏
开发者的Kubernetes懒人指南
你可以将本文作为开发者快速了解 Kubernetes 的指南。从基础知识到更高级的主题,如 Helm Chart,以及所有这些如何影响你作为开发者。译自Kubernetes for Lazy Developers。作...【详细内容】
2024-02-01  云云众生s  微信公众号  Tags:Kubernetes   点击:(50)  评论:(0)  加入收藏
链世界:一种简单而有效的人类行为Agent模型强化学习框架
强化学习是一种机器学习的方法,它通过让智能体(Agent)与环境交互,从而学习如何选择最优的行动来最大化累积的奖励。强化学习在许多领域都有广泛的应用,例如游戏、机器人、自动驾...【详细内容】
2024-01-30  大噬元兽  微信公众号  Tags:框架   点击:(68)  评论:(0)  加入收藏
Spring实现Kafka重试Topic,真的太香了
概述Kafka的强大功能之一是每个分区都有一个Consumer的偏移值。该偏移值是消费者将读取的下一条消息的值。可以自动或手动增加该值。如果我们由于错误而无法处理消息并想重...【详细内容】
2024-01-26  HELLO程序员  微信公众号  Tags:Spring   点击:(86)  评论:(0)  加入收藏
SpringBoot如何实现缓存预热?
缓存预热是指在 Spring Boot 项目启动时,预先将数据加载到缓存系统(如 Redis)中的一种机制。那么问题来了,在 Spring Boot 项目启动之后,在什么时候?在哪里可以将数据加载到缓存系...【详细内容】
2024-01-19   Java中文社群  微信公众号  Tags:SpringBoot   点击:(86)  评论:(0)  加入收藏
花 15 分钟把 Express.js 搞明白,全栈没有那么难
Express 是老牌的 Node.js 框架,以简单和轻量著称,几行代码就可以启动一个 HTTP 服务器。市面上主流的 Node.js 框架,如 Egg.js、Nest.js 等都与 Express 息息相关。Express 框...【详细内容】
2024-01-16  程序员成功  微信公众号  Tags:Express.js   点击:(88)  评论:(0)  加入收藏
站内最新
站内热门
站内头条