Spring @Transactional 方法中的事务处理 JMSTemplate

Spring transaction handling JMSTemplate inside @Transactional method

在我们的 spring 引导应用程序中,我们在数据库上有一个分页循环,它将使用 JMSTemplate 为每个页面发送一条 JMS 消息。包含循环的方法是 @TransactionalJMSTemplate 是在交易标志设置为 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 端的事务将保持打开状态,直到处理完最后一页。这个理解对吗?

这里的重点是交易管理。

如果您使用 XA 数据源并在您的 spring 启动应用程序上配置它,您将拥有一个分布式事务,并且您的事务的 commit/rollback 将由 spring 管理,因为那你有一个用@Transactional 注释的方法,否则你将有一个本地事务管理,并且你的数据库和消息系统的事务将不会同步。

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

希望对您有所帮助