0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Spring事务传播性的相关知识

OSC开源社区 来源:vivo互联网技术 2024-01-10 09:29 次阅读

作者:vivo 互联网服务器团队 - Zhou Shaobin

本文主要介绍了Spring事务传播性的相关知识。

Spring中定义了7种事务传播性:

PROPAGATION_REQUIRED

PROPAGATION_SUPPORTS

PROPAGATION_MANDATORY

PROPAGATION_REQUIRES_NEW

PROPAGATION_NOT_SUPPORTED

PROPAGATION_NEVER

PROPAGATION_NESTED

在Spring环境中,含有事务的方法嵌套调用,事务是如何传递的规则,以及每种规则是如何开展工作的。文章还提到每种事务传播性是如何使用的,方便读者依据实际的场景,使用不同的事务规则。

一、什么是Spring事务的传播性

Spring 事务传播性是指, 在Spring的环境中,当多个含有事务的方法嵌套调用时,每个事务方法都处于自己事务的上下文中,其提交或者回滚行为应该如何处理。

通俗讲,就是当一个事务方法调用另外一个事务方法时,事务如何跨上下文传播。

cf2af760-aee1-11ee-8b88-92fbcf53809c.jpg

1)当事务方法A调用事务方法B时,事务方法B是合并到事务方法A中,还是开启新事务?

2)当事务方法B抛出异常时 ,在合并事务或者开启新的事务的场景中,事务的回滚是如何处理的 ?

以上事务的处理规则,都取决于事务传播级别的设置。

二、事务的传播性都有哪些行为

cf2ee46a-aee1-11ee-8b88-92fbcf53809c.jpg

事务的传播行为,主要分为三种类型,分别是:支持当前事务不支持当前事务嵌套事务

2.1 支持当前事务

REQUIRED:默认的事务传播级别,表示如果当前方法已在事务内,该方法就在当前事务中执行,否则,开启一个新的事务并在其上下文中执行。

SUPPORTED:当前方法在事务内,则在其上下文中执行该方法,否则,开启一个新的事务。

MANDATORY:必须在事务中执行,否则,将抛出异常。

2.2 不支持当前事务

REQUIRES_NEW:无论当前是否有事务上下文,都会开启一个事务 。如果已经有一个事务在执行 ,则正在执行的事务将被挂起 ,新开启的事务会被执行。

事务之间相互独立,互不干扰。

NOT_SUPPORTED:不支持事务,如果当前存在事务上下文,则挂起当前事务,然后以非事务的方式执行。

NEVER:不能在事务中执行,如果当前存在事务上下文,则抛出异常。

2.3嵌套事务

NESTED:嵌套事务,如果当前已存在一个事务的上下文中,则在嵌套事务中执行,如果抛异常,则回滚嵌套事务,而不影响其他事务的操作。

三、每种事务的传播性如何工作

3.1 REQUIRED

默认的事务传播行为,保证多个嵌套的事务方法在同一个事务内执行,并且同时提交,或者出现异常时,同时回滚。

这个机制可以满足大多数业务场景。

cf396f52-aee1-11ee-8b88-92fbcf53809c.jpg

例子 :

cf421346-aee1-11ee-8b88-92fbcf53809c.jpg

cf4c16ca-aee1-11ee-8b88-92fbcf53809c.jpg

1)类TestAService的方法通过声明式事务的方式,加上了事务注解@Transactional ,并设置事务的传播性为REQUIRED。

2)调用者调用TestAService的A方法时,如果调用者没有开启事务,那么A方法会开启一个事务。

A方法的具体执行过程如下 :

a. 执行insert,但没有提交;

b.调用TestBServcie的B方法,由于B方法也声明了事务,并且传播性是REQUIRED,所以方法B的事务,合并到方法A开启的事务中。

c.方法B执行insert操作,此时也没有提交。

3)由于这两个方法的操作都在同一个事务中执行,当这两个方法所有操作执行成功之后,提交事务。

嵌套调用链路:

cf4fd530-aee1-11ee-8b88-92fbcf53809c.jpg

当方法B 执行时抛出了 Exception 异常后,事务是如何处理的 ?

1)方法B声明了事务,insert操作会回滚

2)由于方法A和方法B 同属一个事务,方法A也会执行回滚,由此说明该规则保证了事务的原子性。

嵌套调用,异常后的链路:

cf544d90-aee1-11ee-8b88-92fbcf53809c.jpg

如果 方法B 抛出异常后,方法A 使用 try-catch 处理了方法B的异常(如下代码),并没有向外抛出,此时事务又如何处理的 ?

cf661444-aee1-11ee-8b88-92fbcf53809c.jpg

方法A也会回滚。

从事务的特性我们可知,事务具有原子性。方法A和方法B同属一个事务,当方法B抛出异常,触发回滚操作后,整个事务的操作都会回滚。

因此,Spring 在处理事务过程中,当事务的传播性设置为REQUIRED,在整个事务的调用链上,任何一个环节抛出的异常都会导致全局回滚。

3.2 REQUIRES_ NEW

每次都开启一 个新的事务。

cf71346e-aee1-11ee-8b88-92fbcf53809c.jpg

例子:

cf74b526-aee1-11ee-8b88-92fbcf53809c.jpg

上面例子中,方法B的传播性设置为 REQUIRES_NEW,方法A仍然是REQUIRED,当A调用B时,具体调用链路如下:

cf78fb4a-aee1-11ee-8b88-92fbcf53809c.jpg

具体执行过程:

方法A被执行前,如果调用者没有开启事务,方法A开启一个事务1,然后执行insert ,此时没有提交;

方法B的事务传播性设置为REQUIRES_NEW,当被方法A调用时,此时方法A的事务1会被挂起,方法B开启自己的事务2,然后执行insert,此时并没有提交;

当方法B执行完毕后,提交事务2;

恢复事务1,最终提交。

当 方法B 执行时抛出了异常,会发生什么?

方法B的insert操作会被回滚掉,方法A不受影响。但这里有个前提,方法A需要try-catch方法B的异常,使其异常不会往上传递,从而导致方法A接收到异常,导致回滚。

cf8e0e4a-aee1-11ee-8b88-92fbcf53809c.jpg

3.3 SUPPORTED

当外层方法A存在事务,方法B加入到当前事务中,以事务的方式执行。

cf9203ba-aee1-11ee-8b88-92fbcf53809c.jpg

当外层方法A不存在事务,方法B不会创建新的事务,以非事务的方式执行。

cf959822-aee1-11ee-8b88-92fbcf53809c.jpg

例子1:

cf99f494-aee1-11ee-8b88-92fbcf53809c.jpg

cf9d6eee-aee1-11ee-8b88-92fbcf53809c.jpg

以上例子,方法A没有加事务注解,方法B的加了事务注解,并且传播为SUPPORTS。

具体执行过程:

方法A以非事务的方式执行insert操作。

方法B被调用,由于其外层事务A没有开启事务,方法B也是以非事务方法执行insert操作。

cfa1c642-aee1-11ee-8b88-92fbcf53809c.jpg

例子2:

cfa58354-aee1-11ee-8b88-92fbcf53809c.jpg

以上例子,方法A和B都加上了事务注解,其中方法A的传播性为REQUIRED,方法B的传播性为SUPPORTS。

具体执行过程:

如果方法A的调用方没有开启事务,则方法A开启事务,并执行insert操作,但没有提交;

方法B被调用,由于其外层方法A开启了事务,因此方法B加入到方法A开启的事务中,并执行insert,但没有提交;

当事务中的所有操作执行成功后,事务提交。

cfadd6d0-aee1-11ee-8b88-92fbcf53809c.jpg

3.4 NOT_SUPPORTED

不支持事务。

如果外层方法存在事务,则挂起外层事务,以非事务方式执行,执行完毕后,恢复外层事务。

cfb82f36-aee1-11ee-8b88-92fbcf53809c.jpg

例子:

cfbbb3f4-aee1-11ee-8b88-92fbcf53809c.jpg

以上例子:方法A和B都加上了事务注解,方法A的传播性为REQUIRED,方法B为NOT_SUPPORTED。

具体执行过程:

如A的调用方没有开启事务,方法A开启事务,并执行insert,但没有提交。

方法A调用方法B时,方法B的传播性为NOT_SUPPORTED,不支持事务,然后挂起外层方法A的事务,方法B以非事务的方式执行insert。

方法B执行完毕后,恢复方法A的事务,最终提交事务。

调用链路过程:

cfbf87cc-aee1-11ee-8b88-92fbcf53809c.jpg

3.5 NEVER

不支持事务

当外层方法A开启了事务,方法B抛出异常

cfcb8202-aee1-11ee-8b88-92fbcf53809c.jpg

例子:

cfd572ee-aee1-11ee-8b88-92fbcf53809c.jpg

以上代码,两个方法都打上了事务注解,方法A的传播性是REQUIRED,方法B的传播性是NEVER。

具体执行过程:

方法A开启事务,执行insert,没有提交。

含有事务的方法A调用方法B,方法B的传播性是NEVER,表示不支持事务,因此方法B抛出异常。

方法A的事务执行回滚。

cfdba3bc-aee1-11ee-8b88-92fbcf53809c.jpg

3.6 MANDATORY

必须在事务中执行。

如果外层方法A没有开启事务,方法B抛出异常。

cfe68804-aee1-11ee-8b88-92fbcf53809c.jpg

如果外层方法A开启了事务,方法B加入事务,方法A&B在同一事务中执行。

cfee5322-aee1-11ee-8b88-92fbcf53809c.jpg

例子:

cffb49ce-aee1-11ee-8b88-92fbcf53809c.jpg

以上例子,方法A没有加事务注解,方法B 的传播性为 MANDATORY。

具体执行过程:

方法A的调用方如果本身没有开启事务,方法A执行前不会开启事务。

当非事务方法A调用方法B时,由于方法B的传播性为MANDATORY,必须在事务中执行,条件不满足,抛出异常。

cfff335e-aee1-11ee-8b88-92fbcf53809c.jpg

3.7 NESTED

嵌套事务

如果外层方法A不存在事务,内层方法B的规则与REQUIRED 一致。

如果外层方法A存在事务,内层方法B做为外层方法A事务的子事务执行,两个方法是一起提交,但子事务是独立回滚。

内层方法B抛出异常,则会回滚方法B的所有操作,但不影响外层事务方法A。(方法A需要try-catch子事务,避免异常传递到父层事务)

外层方法A回滚,则内层方法B也会回滚。

该传播性的特点是可以保存状态点,当回滚时,只会回滚到某一个状态点,保证了子事务之间的独立性,避免嵌套事务的全局回滚。

d0034e76-aee1-11ee-8b88-92fbcf53809c.jpg

例子:

d012ff38-aee1-11ee-8b88-92fbcf53809c.jpg

以上例子,方法A的传播性为REQUIRED,方法B为NESTED。

具体执行过程:

方法A执行时,如调用方没有开启事务,则开启一个事务。

方法B被外层方法A调用时,因为方法B的传播性为NESTED,方法B在此处建立savepoint,标记insert行为。

当方法B抛出异常,其insert操作会回滚,但只会回滚到savepoint,(前提是方法A要try-catch方法B,使方法B的异常不会往外传递)。

方法B回滚后,方法A的事务提交。

调用链路:

d02ed262-aee1-11ee-8b88-92fbcf53809c.jpg

四、总结

本文解释了Spring框架中的事务传播性,即多个业务方法之间调用时事务如何处理的规则。Spring提供了七种传播级别,如

PROPAGATION_REQUIRED、

PROPAGATION_REQUIRES_NEW等。

每种级别都有适用场景和限制,本文提供了一些示例,介绍了声明式事务如何使用,每种事务的规则,产生哪种行为,当方法抛出异常时,事务的提交和回滚是如何被处理的。正确处理事务对于任何企业级应用程序都是必要的,了解Spring事务传播性是构建高效、可靠和可扩展应用程序的关键。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 互联网
    +关注

    关注

    54

    文章

    10906

    浏览量

    100743
  • 服务器
    +关注

    关注

    12

    文章

    8116

    浏览量

    82509
  • spring
    +关注

    关注

    0

    文章

    332

    浏览量

    14161

原文标题:Spring七种事务传播性介绍

文章出处:【微信号:OSC开源社区,微信公众号:OSC开源社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Spring事务失效的十种常见场景

    Spring针对Java Transaction API (JTA)、JDBC、Hibernate和Java Persistence API(JPA)等事务 API,实现了一致的编程模型
    的头像 发表于 12-11 15:03 503次阅读

    什么是java spring

    什么是java springSpring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成
    发表于 09-11 11:16

    Spring的两种方式事务管理和API接口介绍

    Spring事务管理
    发表于 03-21 06:52

    Spring事务分析的实现方式

    Spring事务原理分析
    发表于 07-02 15:19

    详解Spring事务管理

    在学习spring事务管理时,我忍不住要问,spring为什么进行事务管理,spring怎么进行的事务
    发表于 07-12 06:54

    Spring事务管理详解说明

    Spring事务管理详解
    发表于 05-20 13:46

    spring中声明式事务实现原理猜想

      @Transactional注解简介 @Transactional 是spring中声明式事务管理的注解配置方式,相信这个注解的作用大家都很清楚。 @Transactional 注解可以帮助
    的头像 发表于 10-13 09:20 1478次阅读

    Spring事务传播行为与回滚机制

    前两天在工作中忙的焦头烂额,涉及到@Transactional对于事务的控制,便仔细研究了一下,颇有所获,花费好了几天测试整理,今天才发表出来,希望看到博客的老铁们能有所获吧。话不多说直奔正题。
    的头像 发表于 07-25 15:57 1217次阅读

    浅谈Spring事务的那些坑

    对于从事java开发工作的同学来说,spring事务肯定再熟悉不过了。在某些业务场景下,如果同时有多张表的写入操作,为了保证操作的原子性(要么同时成功,要么同时失败)避免数据不一致的情况,我们一般都会使用spring
    的头像 发表于 10-11 10:31 581次阅读

    发现一个Spring事务的巨坑bug 你必须要小心了

    1.错误的访问权限 2.方法被定义成final的 3.方法内部调用 4.当前实体没有被spring管理 5.错误的spring事务传播特性 6.数据库不支持
    的头像 发表于 10-11 18:17 685次阅读

    浅谈Spring事务底层原理

    开启Spring事务本质上就是增加了一个Advisor,但我们使用@EnableTransactionManagement注解来开启Spring事务是,该注解代理的功能就是向
    的头像 发表于 12-06 09:56 513次阅读

    Spring Boot Web相关的基础知识

    Boot的第一个接口。接下来将会将会介绍使用Spring Boot开发Web应用的相关内容,其主要包括使用spring-boot-starter-web组件来实现Web应用开发、URL地址映射、参数传递、数据校验规、统一数据返
    的头像 发表于 03-17 15:03 460次阅读

    Spring事务在哪几种情况下会不生效?

    日常开发中,我们经常使用到spring事务。最近星球一位还有去美团面试,被问了这么一道面试题: Spring 事务在哪几种情况下会不生效?
    的头像 发表于 05-10 17:53 564次阅读
    <b class='flag-5'>Spring</b><b class='flag-5'>事务</b>在哪几种情况下会不生效?

    8个Spring事务失效的场景介绍

    作为Java开发工程师,相信大家对Spring事务的使用并不陌生。但是你可能只是停留在基础的使用层面上,在遇到一些比较特殊的场景,事务可能没有生效,直接在生产上暴露了,这可能就会导致比较严重的生产
    的头像 发表于 05-11 10:41 405次阅读
    8个<b class='flag-5'>Spring</b><b class='flag-5'>事务</b>失效的场景介绍

    spring事务失效的一些场景

    对于从事java开发工作的同学来说,spring事务肯定再熟悉不过了。 在某些业务场景下,如果一个请求中,需要同时写入多张表的数据。为了保证操作的原子性(要么同时成功,要么同时失败),避免数据
    的头像 发表于 10-08 14:27 270次阅读
    <b class='flag-5'>spring</b><b class='flag-5'>事务</b>失效的一些场景