【问题标题】:Real life scenarios for Transaction propagations事务传播的真实场景
【发布时间】:2015-09-21 09:17:13
【问题描述】:

有各种各样的事务传播,比如

REQUIRED - 这是 DML 操作的情况。

SUPPORTS - 这是查询数据库的情况。

MANDATORY - ?
REQUIRES_NEW - ?
NOT_SUPPORTED - ?
NEVER - ?
NESTED - ?

这些事务传播有哪些现实生活场景?为什么这些都非常适合这种情况?

【问题讨论】:

    标签: spring transactions spring-transactions


    【解决方案1】:

    有多种用法,没有简单的答案,但我会尽量解释清楚

    • MANDATORY(期望事务):通常在您期望任何“更高上下文”层启动事务并且您只想继续进行事务时使用。例如,如果您希望一个事务用于从 HTTP 请求到响应的整个操作。然后在 JAX-RS 资源级别启动事务,并且较低层(服务)需要在其中运行事务(否则会引发异常)。
    • REQUIRES_NEW(总是创建新事务):这会创建一个新事务并暂停当前事务(如果存在)。例如,从上面的示例中,这是您在 JAX-RS 资源上设置的级别。或者一般来说,如果您的流程发生了某种变化,并且您希望将逻辑拆分为多个事务(因此您的代码具有应该分开的多个逻辑操作)。
    • REQUIRED(继续事务或根据需要创建):MANDATORY 和 REQUIRES_NEW 之间的某种混合。在 MANDATORY 中,您希望事务存在,对于此级别,您希望它存在,如果不存在,则创建它。通常用于类似 DAO 的服务中(根据我的经验),但这实际上取决于您应用的逻辑。
    • 支持(调用者决定是否/在事务中运行):如果想使用与调用者相同的上下文(更高的上下文),如果你的调用者在事务中运行,那么你也运行。如果没有,您也是非事务性的。如果您需要更高的上下文来决定,也可以在类似 DAO 的服务中使用。
    • 嵌套(子事务):我必须承认我没有在实际代码中使用这个,但通常你创建一个真正的子事务作为某种检查点。因此它在“父”事务的上下文中运行,但如果失败,它会返回到该检查点(嵌套事务的开始)。当您在应用程序中需要这种逻辑时,这可能很有用,例如,如果您想将大量项目插入数据库,提交有效项目并跟踪无效项目(这样您可以在嵌套事务失败时捕获异常但仍然可以为有效交易提交整个交易)
    • NEVER(预计没有交易):当您想确保根本不存在交易时,就是这种情况。如果在事务中运行的某些代码到达此代码,则会引发异常。所以通常这适用于与 MANDATORY 完全相反的情况。例如。当您知道此代码不应影响任何事务时 - 很可能是因为该事务不应该存在。
    • NOT_SUPPORTED(以非事务方式继续):这比 NEVER 弱,您希望代码以非事务方式运行。如果您以某种方式从事务所在的上下文中输入此代码,则会暂停此事务并以非事务方式继续。

    根据我的经验,您经常希望一项业务操作是原子的。因此,每个请求只需要一个事务/...例如,通过 HTTP 进行的简单 REST 调用,它在一个类似 HTTP 的事务中执行一些数据库操作。所以我的典型用法是 REQUIRES_NEW 在顶层(JAX-RS 资源)和 MANDATORY 在注入此资源的所有较低级别的服务(甚至更低)。

    这可能对您有用。它描述了代码在给定传播下的行为(调用者->方法)

    • 必需:无->T1、T1->T1
    • REQUIRES_NEW:NONE->T1、T1->T2
    • 强制:NONE->例外,T1->T1
    • NOT_SUPPORTED:NONE->NONE,T1->NONE
    • 支持:无->无,T1->T1
    • 从不:NONE->NONE,T1->例外

    【讨论】:

    • 永远不要忘记调用链的乐趣,例如REQUIRED -> REQUIRES_NEW -> NESTED -> NOT_SUPPORTED -> REQUIRED(然后抛出异常)。事务管理总是有趣,因为它在所有 ORM 中都是一个非常容易泄漏的抽象。
    • 根据您上次的更新,您还没有为NESTED 更新它,我尝试自己做,所以我观察到 REQUIRES_NEW 与 NESTED 非常相似,那么它们之间有什么区别?
    • @Augusto REQUIRED -> REQUIRES_NEW -> NESTED -> NOT_SUPPORTED -> REQUIRED 会导致:NONE -> T1 -> Suspend T1 -> create T2-> create T3-> Suspend T3 -> T4?那为什么会抛出异常呢?
    • 实际上 NESTED 不是 JPA 规范的一部分。正如你所说,它的行为非常相似。不同之处在于,使用 NESTED 您与父事务相关,因为 REQUIRES_NEW 将创建一个未连接到父事务的新事务。我用一个例子更新了 NESTED 的答案
    猜你喜欢
    • 2015-07-17
    • 1970-01-01
    • 2011-07-11
    • 1970-01-01
    • 2011-04-16
    • 2023-03-12
    • 2022-01-18
    • 2020-08-01
    • 2017-11-22
    相关资源
    最近更新 更多