【问题标题】:What precisely means setSessionTransacted in JMSTemplate?JMSTemplate 中的 setSessionTransacted 究竟是什么意思?
【发布时间】:2020-02-17 20:21:40
【问题描述】:

如果我对 Spring 文档的理解正确,请解释一下。

Spring 文档状态:https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#jms-tx

(...)当您在非托管环境中使用 JmsTemplate 时,您可以通过使用属性 sessionTransacted 和 sessionAcknowledgeMode 来指定这些值(事务和确认模式)。

当您将 PlatformTransactionManager 与 JmsTemplate 一起使用时,模板总是被赋予一个事务性 JMS 会话。(..)

(顺便说一句,这是真的 - 会话是事务性的)

Javadoc 状态:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jms/core/JmsTemplate.html

JMS 会话的默认设置是“未处理”和“自动确认”。正如 Java EE 规范所定义的,当在活动事务中创建 JMS 会话时,事务和确认参数将被忽略,无论是 JTA 事务还是 Spring 管理的事务

我知道如果事务处于活动状态,JMS 模板会话事务设置将被忽略 - 这是真的 - 并且会话应该参与活动事务 - 这是不正确的强>.

我调试了为什么它不是真的,我发现:https://github.com/spring-projects/spring-framework/blame/master/spring-jms/src/main/java/org/springframework/jms/connection/ConnectionFactoryUtils.java#L353

if (resourceHolderToUse != resourceHolder) {
  TransactionSynchronizationManager.registerSynchronization(
    new JmsResourceSynchronization(resourceHolderToUse, connectionFactory,
                             
 resourceFactory.isSynchedLocalTransactionAllowed()));
 resourceHolderToUse.setSynchronizedWithTransaction(true);
 TransactionSynchronizationManager.bindResource(connectionFactory, resourceHolderToUse);
}

resourceHolderToUse.setSynchronizedWithTransaction(true) 行是对齐文档。

这里的问题:resourceFactory.isSynchedLocalTransactionAllowed()

因为resourceFactory 是指向JmsTemplate#sessionTransacted 的org.springframework.jms.core.JmsTemplate.JmsTemplateResourceFactory#isSynchedLocalTransactionAllowed。

结论: 根据文档,如果事务处于活动状态,则应忽略 JmsTemplate#sessionTransacted。但事实并非如此——虽然会话是事务性的,但不能不参与提交。

JmsTemplate#sessionTransacted 最终映射到 ConnectionFactoryUtils.JmsResourceSynchronization#transacted 并且 default=false 防止在事务结束时调用提交(JmsResourceSynchronization “认为”它不参与事务)

我对文档的理解正确吗,这里真的有错误吗?

【问题讨论】:

  • 该方法的名称isSynchedLocalTransactionAllowed 用于本地事务(即JmsTransactionManager),但这不适用于托管 (J(2)EE) 环境,其中事务由 JTA 而不是 Spring 驱动(即不是本地事务)。
  • @M.Deinum 在我的代码中我调用platformTransactionManager.getTransaction() 并根据“无论是 JTA 事务还是 Spring 管理的事务”。我希望sessionTransacted 应该被忽略。我说的对吗?
  • 只有原生JMS事务或托管事务才能参与事务。当它是 JPA 之类的其他东西时,它不能参与,因为它不能提交并且它需要自己管理它(这也记录在 ConnectionFactoryUtils 中)。

标签: spring transactions spring-transactions spring-jms jmstemplate


【解决方案1】:

在 M. Deinum 的指导下,我做了更多的实验,似乎我错误地理解了术语Spring-managed transaction

我只是认为 Spring 托管事务是由 platformTransactionManager 启动的。但是:

  1. 如果platformTransactionManagerJtaTransactionManager 并且事务已启动,则它 Spring 托管事务; JMS 模板属性 sessionTransacted 被忽略,JMS 模板是事务的一部分
  2. 如果platformTransactionManagerDataSourceTransactionManagerJpaTransactionManager 那么
    • 如果sessionTransacted 为false,则JMS 模板不在事务中
    • 如果sessionTransacted 为真,JMS 模板与事务同步:在 JDBC/JPA 事务上回调/回滚后,JMS 事务上调用对应的提交/回滚

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-12
    • 2014-10-29
    • 2016-01-27
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多