何时使用 Spring @Transactional (propagation = Propagation.SUPPORTS)?

Posted

技术标签:

【中文标题】何时使用 Spring @Transactional (propagation = Propagation.SUPPORTS)?【英文标题】:When to use Spring @Transactional (propagation = Propagation.SUPPORTS)? 【发布时间】:2013-02-13 17:38:47 【问题描述】:

根据 Spring javadoc @Transactional(propagation = Propagation.SUPPORTS)

支持当前事务,如果没有则以非事务方式执行 存在。类似于 EJB 事务的同名属性。

看来我可以只声明非事务性方法并完成它,所以我的问题是。

在哪些情况下需要支持传播? 支持传播的意义何在?

谁能给出一个支持实际有用的真实示例/场景?

【问题讨论】:

Heva 看看这个答案:***.com/questions/6437828/… 【参考方案1】:

根据这个问题Improve performance with Propagation.SUPPORTS for readOnly operation,您不应该使用 Propagation.SUPPORTS 设置只读事务:

目前尚不清楚该更改是否会真正提高性能。这有多个方面。首先是链接的文章已经过时并且存在令人难以置信的缺陷,因为它积极地简化了事情。如果您愿意,我可以详细说明,但我暂时先不谈。这里有很多影响执行性能的因素。如果没有正在进行的事务,则 readOnly 标志不会传播到 JDBC 驱动程序(这会导致许多数据库的优化未应用),也不会在 Spring 的 JPA 资源管理代码中应用优化,例如显式关闭刷新,如果应用 - 如果您读取大量数据,可以显着提高性能。

【讨论】:

【参考方案2】:

它与选择操作上的readOnly=true Transactional 标志形成了很好的配对,尤其是在使用 ORM 时:

@Transactional(readOnly = true, propagation=Propagation.SUPPORTS)
public Pojo findPojo(long pojoId) throws Exception 
   return em.find(Pojo.class, pojoId);

在这种情况下,如果还没有仅用于执行选择操作的新交易,请确保不要支付创建新交易的费用。

虽然如果你已经在这个思考过程中,你甚至可以考虑一起放弃事务方面:

public Pojo findPojo(long pojoId) throws Exception 
   return em.find(Pojo.class, pojoId);

【讨论】:

so...是否真的应该将@Transactional注解用于通过ORM框架(例如MyBatis)在本地数据库中进行选择? 通过“抛弃事务方面”,这和使用@NotTransactional 一样吗? 如果某些东西没有事务方面,或者是@NotTransactional,并且它是从事务中调用的,会发生什么?例如如果事务方法 A 向 DB 写入内容,然后调用 NotTransactional 方法 be,该方法也写入内容,那么 A 或 B 会抛出未经检查的异常,该异常会被回滚? 我仍然认为拥有支持与没有支持之间没有区别。我认为 API 设计者只是把它过于痴迷于注释。也许在未来的某一天,我们会扭转这种邪恶,重新按照上帝的意图进行真正的面向对象编程。【参考方案3】:

我能想到的最简单的例子是将一些内容发送到 JMS 服务器的方法。如果您在事务的上下文中,您希望消息与事务范围耦合。但是,如果还没有一个事务正在运行,为什么还要调用事务服务器并启动一个只是为了做一次性消息呢?

请记住,这些可以在 API 和实现上声明。因此,即使您的用例在将其放在那里和什么都不放在那里之间没有太大区别,它仍然为 API 作者增加了价值,以指定哪些操作能够包含在事务中,而不是可能调用的操作不参与交易的外部系统。

这当然是在 JTA 上下文中。在事务仅限于资源本地物理数据库事务的系统中,该功能实际上并没有太多实际用途。

【讨论】:

在您给出的 JMS 示例中,如果没有 tx 但 jms 会话/生产者是共享的,那么作为 TX 的一部分发送的消息。我猜分布式 tx 是唯一可以使用 SUPPORTS 的地方。 我认为,如果您有 NOT_SUPPORTED 的实例并且想要区分,它在非分布式设置中作为 API 标记仍然有用。但是你是对的,在实现方面,如果 tx 没有被分发,它与什么都不放在那里并没有太大的不同。 我不明白为什么分发或不分发会有什么不同。没有添加 NOT_SUPPORTED 的没有 SUPPORTS 的方法确实有效地支持事务。这就是所有这一切的重点。这就像为每个非最终方法添加一个“@PossiblyOverridden”注释。无意义! Affe,你的第一段..是错的? “如果没有正在运行的事务”则没有正在运行的事务。你的第二段,也错了?同样,如果我不支持事务,我使用 NOT_SUPPORTED。任何没有事务注释的地方都有效地“支持”。 我不确定您正在寻找什么样的回应来评论一个关于 18 岁 API 的 7 岁答案,这似乎是一个基于现代感性的愚蠢设计......是的..它实际上“什么都不做”......是的,20 年前的 Sun 工程师与今天的谷歌和 Facebook 工程师有不同的设计理念?如果我今天回答这个问题,我可能会写类似“这就是我们在 2002 年推出的方式,那种对 UML 感到兴奋的人会像那样重视‘完整性’,即使设置实际上是一个空操作。”

以上是关于何时使用 Spring @Transactional (propagation = Propagation.SUPPORTS)?的主要内容,如果未能解决你的问题,请参考以下文章

注意Spring事务这一点,避免出现大事务

注意Spring事务这一点,避免出现大事务

为啥以及何时在 Spring 中使用 @Inject 而不是 @Autowired? [复制]

何时使用 Spring 原型作用域?

Spring AOP何时使用JDK动态代理?何时使用Cglib ?默认是哪种?

何时使用 Spring @Transactional (propagation = Propagation.SUPPORTS)?