前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【转载】Spring 中,事务的传播方式

【转载】Spring 中,事务的传播方式

作者头像
水货程序员
发布2018-11-13 17:53:25
6300
发布2018-11-13 17:53:25
举报
文章被收录于专栏:javathings

Spring 事传播行为:

spring 特有的事务传播行为,spring 支持 7 种事务传播行为,确定客户端和被调用端的事务边界(说得通俗一点就是多个具有事务控制的 service 的相互调用时所形成的复杂的事务边界控制)下图所示为 7 钟事务传播机制

o

传播行为

含义

PROPAGATION_REQUIRED(XML 文件中为 REQUIRED)

表示当前方法必须在一个具有事务的上下文中运行,如有客户端有事务在进行,那么被调用端将在该事务中运行,否则的话重新开启一个事务。(如果被调用端发生异常,那么调用端和被调用端事务都将回滚)

PROPAGATION_SUPPORTS(XML 文件中为 SUPPORTS)

表示当前方法不必需要具有一个事务上下文,但是如果有一个事务的话,它也可以在这个事务中运行

PROPAGATION_MANDATORY(XML 文件中为 MANDATORY)

表示当前方法必须在一个事务中运行,如果没有事务,将抛出异常

PROPAGATION_NESTED(XML 文件中为 NESTED)

表示如果当前方法正有一个事务在运行中,则该方法应该运行在一个嵌套事务中,被嵌套的事务可以独立于被封装的事务中进行提交或者回滚。如果封装事务存在,并且外层事务抛出异常回滚,那么内层事务必须回滚,反之,内层事务并不影响外层事务。如果封装事务不存在,则同 PROPAGATION_REQUIRED 的一样

PROPAGATION_NEVER(XML 文件中为 NEVER)

表示当方法务不应该在一个事务中运行,如果存在一个事务,则抛出异常

PROPAGATION_REQUIRES_NEW(XML 文件中为 REQUIRES_NEW)

表示当前方法必须运行在它自己的事务中。一个新的事务将启动,而且如果有一个现有的事务在运行的话,则这个方法将在运行期被挂起,直到新的事务提交或者回滚才恢复执行。

PROPAGATION_NOT_SUPPORTED(XML 文件中为 NOT_SUPPORTED)

表示该方法不应该在一个事务中运行。如果有一个事务正在运行,他将在运行期被挂起,直到这个事务提交或者回滚才恢复执行

例子讲解以上七中事务传播机制

假设有类 A 的方法 methodB(), 有类 B 的方法 methodB().

1)     PROPAGATION_REQUIRED

如果 B 的方法 methodB() 的事务传播特性是 propagation_required,那么如下图

A.methodA() 调用 B 的 methodB() 方法,那么如果 A 的方法包含事务,则 B 的方法则不从新开启事务,

1、  如果 B 的 methodB() 抛出异常,A 的 methodB() 没有捕获,则 A 和 B 的事务都会回滚;

2、    如果 B 的 methodB() 运行期间异常会导致 B 的 methodB() 的回滚,A 如果捕获了异常,并正常提交事务,则会发生 Transaction rolled back because it has been marked as rollback-only 的异常。

3、  如果 A 的 methodA() 运行期间异常,则 A 和 B 的 Method 的事务都会被回滚

2)     PROPAGATION_SUPPORTS

如果 B 的方法 methodB() 的事务传播特性是 propagation_supports, 么如下图

A.methodA() 调用 B 的 methodB() 方法,那么如果 A 的方法包含事务,则 B 运行在此事务环境中,如果 A 的方法不包含事务,则 B 运行在非事务环境;

1、如果 A 没有事务,则 A 和 B 的运行出现异常都不会回滚。

2、如果 A 有事务,A 的 method 方法执行抛出异常,B.methodB 和 A.methodA 都会回滚。

3、如果 A 有事务,B.method 抛出异常,B.methodB 和 A.methodA 都会回滚,如果 A 捕获了 B.method 抛出的异常,则会出现异常 Transactionrolled back because it has been marked as rollback-only。

3)     PROPAGATION_MANDATORY

表示当前方法必须在一个事务中运行,如果没有事务,将抛出异常,如下图调用关系:

B.methodB() 事务传播特性定义为:PROPAGATION_MANDATORY

1、如果 A 的 methoda() 方法没有事务运行环境,则 B 的 methodB() 执行的时候会报如下异常:No existingtransaction found for transaction marked with propagation ‘mandatory’

2、如果 A 的 Methoda() 方法有事务并且执行过程中抛出异常,则 A.methoda()和 B.methodb()执行的操作被回滚;

3、如果 A 的 methoda() 方法有事务,则 B.methodB() 抛出异常时,A 的 methoda() 和 B.methodB() 都会被回滚;如果 A 捕获了 B.method 抛出的异常,则会出现异常 Transaction rolled back because ithas been marked as rollback-only

4)     PROPAGATION_NESTED

如有一下方法调用关系,如图:

B 的 methodB() 定义的事务为 PROPAGATION_NESTED;

1、        如果 A 的 MethodA() 不存在事务,则 B 的 methodB() 运行在一个新的事务中,B.method() 抛出的异常,B.methodB() 回滚, 但 A.methodA() 不回滚;如果 A.methoda() 抛出异常,则 A.methodA() 和 B.methodB() 操作不回。

2、        如果 A 的 methodA() 存在事务,则 A 的 methoda() 抛出异常,则 A 的 methoda() 和 B 的 Methodb() 都会被回滚;

3、        如果 A 的 MethodA() 存在事务,则 B 的 methodB() 抛出异常,B.methodB() 回滚,如果 A 不捕获异常,则 A.methodA() 和 B.methodB() 都会回滚,如果 A 捕获异常,则 B.methodB() 回滚,A 不回滚;

5)PROPAGATION_NEVER

表示事务传播特性定义为 PROPAGATION_NEVER 的方法不应该运行在一个事务环境中

有如下调用关系:

如果 B.methodB() 的事务传播特性被定义为 PROPAGATION_NEVER,则如果 A.methodA() 方法存在事务,则会出现异常 Existingtransaction found for transaction marked with propagation ‘never’。

6)PROPAGATION_REQUIRES_NEW

表示事务传播特性定义为 PROPAGATION_REQUIRES_NEW 的方法需要运行在一个新的事务中。

如有一下调用关系:B.methodB() 事务传播特性为 PROPAGATION_REQUIRES_NEW.

1、        如果 A 存在事务,A.methodA() 抛出异常,A.methodA() 的事务被回滚,但 B.methodB() 事务不受影响;如果 B.methodB() 抛出异常,A 不捕获的话,A.methodA() 和 B.methodB() 的事务都会被回滚。如果 A 捕获的话,A.methodA() 的事务不受影响但 B.methodB() 的事务回滚。

7) PROPAGATION_NOT_SUPPORTED

表示该方法不应该在一个事务中运行。如果有一个事务正在运行,他将在运行期被挂起,直到这个事务提交或者回滚才恢复执行。

如有一下调用关系图:

如果 B.methodB() 方法传播特性被定义为:PROPAGATION_NOT_SUPPORTED。

1、        如果 A.methodA() 存在事务,如果 B.methodB() 抛出异常,A.methodA() 不捕获的话,A.methodA() 的事务被回滚,而 B.methodB() 出现异常前数据库操作不受影响。如果 A.methodA() 捕获的话,则 A.methodA() 的事务不受影响,B.methodB() 异常抛出前的数据操作不受影响。

实际场景中的七大事务传播行为的使用

1、  在一个话费充值业务处理逻辑中,有如下图所示操作:

业务需要扣款操作和创建订单操作同成功或者失败,因此,charger() 和 order() 的事务不能相互独立,需要包含在 chargeHandle() 的事务中;

通过以上需求,可以给 charge() 和 order() 的事务传播行为定义成:PROPAGATION_MANDATORY

只要 charge() 或者 order() 抛出异常整个 chargeHandle() 都一起回滚,即使 chargeHandle() 捕获异常也没用,不允许提交事务。

2、  如果业务需求没接受到一次请求到要记录日志到数据库,如下图:

因为 log() 的操作不管扣款和创建订单成功与否都要生成日志,并且日志的操作成功与否不影响充值处理,所以 log() 方法的事务传播行为可以定义为:PROPAGATION_REQUIRES_NEW.

3、  在订单的售后处理中,更新完订单金额后,需要自动统计销售报表,如下图所示:

根据业务可知,售后是已经处理完订单的充值请求后的功能,是对订单的后续管理,统计报表 report() 方法耗时较长,因此,我们需要设置 report() 的事务传播行为为:PROPAGATION_NEVER, 表示不适合在有事务的操作中调用,因为 report() 太耗时。

4、  在银行新增银行卡业务中,需要执行两个操作,一个是保存银行卡信息,一个是登记新创建的银行卡信息,其中登记银行卡信息成功与否不影响银行卡的创建。

由以上需求,我们可知对于 regster() 方法的事务传播行为,可以设置为 PROPAGATION_NESTED,action() 事务的回滚,regster() 保存的信息就没意义,也就需要跟着回滚,而 regster() 的回滚不影响 action() 事务;insert() 的事务传播行为可以设置为 PROPAGATION_REQUIRED, PROPAGATION_MANDATORY,即 insert() 回滚事务,action() 的事务必须跟着回滚。

转载自 https://blog.csdn.net/pml18710973036/article/details/58607148

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring 事传播行为:
  • 例子讲解以上七中事务传播机制
  • 实际场景中的七大事务传播行为的使用
相关产品与服务
腾讯云 BI
腾讯云 BI(Business Intelligence,BI)提供从数据源接入、数据建模到数据可视化分析全流程的BI能力,帮助经营者快速获取决策数据依据。系统采用敏捷自助式设计,使用者仅需通过简单拖拽即可完成原本复杂的报表开发过程,并支持报表的分享、推送等企业协作场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档