【问题标题】:Spring transaction handling JMSTemplate inside @Transactional method@Transactional 方法中的 Spring 事务处理 JMSTemplate
【发布时间】:2018-12-20 07:56:30
【问题描述】:

在我们的 Spring Boot 应用程序中,我们在数据库上有一个分页循环,它将使用 JMSTemplate 为每个页面发送一条 JMS 消息。包含循环的方法是@TransactionalJMSTemplate 是在将 transacted 标志设置为 true 的情况下创建的。

我一直在浏览JMSTemplate 的源代码,据我所知,如果已经有外部事务在进行,它将不会提交事务会话,但会将其放入该事务中。

现在让我们考虑以下代码:

@Transactional
public void loopThroughPages(String destination, String from, String to) {
    Pageable pageRequest = PageRequest.of(0, maxPageSize);
    Page<Event> eventPage;
    do {
       eventPage = eventRepo.getEventsInTimeRangeForDestination(from, to, destination, pageRequest);
       if(eventPage.hasContent()) {
          Message<String> eventMessage = buildEventMessage(eventPage.getContent());
          JmsTemplate template = queueService.createTemplate(destination);
          template.send(eventMessage);
          pageRequest = eventPage.nextPageable();
       }
    } while(pageRequest != null && eventPage.hasNext());
}

createTemplate 使用CachingConnectionFactorysetSessionTransacted 创建DynamicJmsTemplatetrue

我现在不完全确定这如何转化为交易。我的理解是,所有N 页面消息都是在从loopThroughPages 创建的事务中发送的,一旦loopThroughPages 方法完成,它将提交所有N 消息,而不是在发送每条消息之后。这也意味着 MQ 端的事务将保持打开状态,直到处理完最后一页。这种理解正确吗?

【问题讨论】:

  • 我在JmsTemplate 中删除了我对commitclose 的评论,因为它不一定会关闭它获得的Session,除非它无法从@987654339 获得事务会话@

标签: java spring transactions jms


【解决方案1】:

这里的关键点是事务管理。

如果您使用 XA 数据源并在 Spring Boot 应用程序上对其进行配置,您将拥有一个分布式事务,并且您的事务的提交/回滚将由 Spring 管理,因为您有一个使用 @Transactional 注释的方法,否则您将拥有本地事务管理,您的数据库和消息系统的事务将不会同步。

对于发送消息,您可以通过属性配置消息是否持久化,这意味着您的消息是否将由您的消息传递系统持久化,而对于侦听器,您可以配置确认模式。 顺便说一句,我的建议是让弹簧管理事务,一切都会好起来的,但真正要注意的是,如果你想要数据库和 jms 系统之间的分布式事务,你只需要配置它 atomikos 可以是一个可用的选项,否则它不用手动管理事务就足够了,让 Spring 为您管理它。

希望对你有帮助

【讨论】:

  • 这很有趣。我们的应用程序没有使用 XA 事务(因此在本地进行事务处理),但是我在当前问题中注意到循环从 T+00s 开始,在 T+42s MQ 系统中止事务,因为它运行了太长时间并且它需要释放日志空间。当前分页实现的性能很差,这表明 MQ Session 的事务仅在循环结束时提交(或者在这种情况下被 MQ 强制回滚)。这是矛盾吗?我不完全确定
  • 这并不矛盾,因为应用程序创建的事务管理器会创建一个ChainedTransactionManager,默认为JpaTransactionManager,并为每个QueueConnectionFactory创建一个JmsTransactionManager,其中事务使用SYNCHRONIZATION_ALWAYS .因此,根据我的理解,事务将被捆绑在一起,提交只会在循环结束时发生。
猜你喜欢
  • 2019-03-30
  • 2011-02-21
  • 2019-02-26
  • 2014-07-08
  • 2014-11-30
  • 1970-01-01
  • 2019-01-09
  • 2018-10-13
  • 2023-03-07
相关资源
最近更新 更多