Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring事务处理@Transactional方法内的JMSTemplate_Java_Spring_Transactions_Jms - Fatal编程技术网

Java Spring事务处理@Transactional方法内的JMSTemplate

Java Spring事务处理@Transactional方法内的JMSTemplate,java,spring,transactions,jms,Java,Spring,Transactions,Jms,在spring boot应用程序中,我们在数据库上有一个分页循环,它将使用JMSTemplate为每个页面发送一条JMS消息。包含循环的方法是@Transactional。创建JMSTemplate时,事务标志设置为true 我一直在浏览JMSTemplate的源代码,据我所知,如果已经有一个外部事务正在进行,它将不会提交一个事务会话,而是将其放入该事务中 现在让我们考虑下面的代码: @Transactional public void loopThroughPages(String desti

在spring boot应用程序中,我们在数据库上有一个分页循环,它将使用
JMSTemplate
为每个页面发送一条JMS消息。包含循环的方法是
@Transactional
。创建
JMSTemplate
时,事务标志设置为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());
}
@Transactional
公共void loopThroughPages(字符串目标、字符串起始、字符串终止){
Pageable pageRequest=pageRequest.of(0,maxPageSize);
页面事件页面;
做{
eventPage=eventRepo.getEventsInTimeRangeForDestination(从、到、目的地、页面请求);
if(eventPage.hasContent()){
Message eventMessage=buildEventMessage(eventPage.getContent());
JmsTemplate template=queueService.createTemplate(目的地);
模板发送(eventMessage);
pageRequest=eventPage.nextPageable();
}
}while(pageRequest!=null&&eventPage.hasNext());
}
createTemplate
使用
CachingConnectionFactory
setSessionTransactived
创建一个
DynamicJmsTemplate


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

这里的关键是交易管理

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

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


我希望它能帮助您

我已经删除了我在
JmsTemplate
中关于
commit
close
的评论,因为它不一定要关闭它获得的
会话
,只有当它无法从
ConnectionFactoryUtils.doGetTransactionalSession
中获得感兴趣的事务会话时。我们的应用程序没有使用XA事务(因此是本地事务),但是我在当前问题中注意到,循环从T+00s开始,在T+42s,MQ系统中止事务,因为它运行的时间太长,需要释放日志空间。当前分页实现的性能很差,这表明MQ
会话的事务仅在循环结束时提交(或者在这种情况下由MQ强制回滚)。这是矛盾吗?我不能完全肯定这不是矛盾,因为应用程序创建的事务管理器为每个
QueueConnectionFactory
创建了一个
ChainedTransactionManager
,其中事务始终使用
同步。因此,根据我的理解,事务将绑定在一起,提交只会在循环结束时发生。