本文介绍了Spring同步Hibernate和JMS事务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



文档建议如果我想通过两种方式进行事务处理,就必须使用JTA资源。

然而,现在使用@Transaction注释的DAO方法(和HibernateTransactionManager),这似乎已经工作了。当我在JmsTemplate上调用send()时,不会立即发送消息,而是在方法返回时使用Hibernate会话提交JMS会话。



我没有如果没有JtaTransactionManager,我不知道这是如何实现的,所以我检查了源代码。事实证明,Hibernate和JmsTemplate的包装程序都使用TransactionSynchronizationManager注册会话,并且在Hibernate会话提交时JMS会话将被提交。



这和a JTA交易。我可以用这个来代替后者吗?

解决方案

总之,不能获得对两阶段提交的支持没有JTATransactionManager和XA感知数据源。



您目睹的是两个仅支持单阶段提交的本地事务的协调。大致执行这一系列事件......


  1. 启动JMS Transaction

  2. 阅读JMS消息
  3. li>
  4. 开始JDBC事务

  5. 写入数据库
  6. 提交JDBC事务
  7. >提交/确认JMS

JMS事务将首先包装嵌套的JDBC事务,以便JMS队列将回滚Hibernate / JDBC提交失败。您的JMS Listener容器应该设置为不是 acknowledge =auto,而是在发送确认之前等待Hibernate事务完成。

然而


  1. 您必须编写MessageListener来处理来自服务器的重复邮件

  2. 您还必须处理由于错误的数据而无法处理的消息,并最终以无限循环尝试消除它。在这种情况下,可以将服务器配置为将消息移动到死信消息队列,或者在MessageListener中自行处理此消息。

其他选项和进一步阅读

如果您的JMS服务器不支持XA(全局)如果JMS服务器不支持XA事务,但是JDBC不支持,那么您可以使用JTATransactionManager并使用。您可以使用像JOTM这样的开源的JTATransactionManagers



详细介绍了您的问题空间。


I am working on a stand-alone application that uses both JMS and Hibernate.

The documentation suggests JTA has to be used if I want to have transactions across both resources.

However, right now with a @Transaction annotated DAO method (and HibernateTransactionManager), this already seems to work. When I call send() on the JmsTemplate, the message is not immediately sent, but rather the JMS session is committed with the Hibernate session as the method returns.

I didn't know how this is possible without the JtaTransactionManager, so I checked the source code. It turns out both the wrapper for Hibernate and JmsTemplate registers the sessions with TransactionSynchronizationManager and the JMS session will be committed when the Hibernate session commits.

What's the different between this and a JTA transaction. Can I use this to replace the latter??

解决方案

In short no, you can't get support for 2-phase commit without a JTATransactionManager and XA aware datasources.

What you are witnessing is a co-ordination of two Local Transactions supporting 1-phase commit only. Roughly performing this sequence of events...

  1. Start JMS Transaction
  2. Read JMS message
  3. Start JDBC Transaction
  4. Write to database
  5. Commit JDBC Transaction
  6. Commit/Acknowledge JMS

The JMS transaction will be started first wrapping the nested JDBC transaction, so that the JMS queue will rollback if the Hibernate/JDBC commit fails. Your JMS Listener Container should be setup not to acknowledge="auto" and instead wait for the Hibernate transaction to complete before sending the acknowledgement.

If you only have these two resources then the issue you will have to consider is when Hibernate succeeds in persiting then you get an Exception before you can acknowledge the JMS server. Not a big issue as the JMS message is not lost and you will read it again.

However

  1. You must write your MessageListener to handle duplicate messages from the server

  2. You must also handle a message that cannot be processed due to bad data and ending up in an infinite loop of trying to comsume it. In this case the server may be configured to move the message to a "dead message queue", or you deal with this yourself in the MessageListener

Other options and further reading

If your JMS server does not support XA (global) transactions this is pretty much your only solution.

If JMS server does support XA transactions but JDBC doesn't then you can use a JTATransactionManager and use the LastResourceCommitOptimisation. There are open source JTATransactionManagers you can use like JOTM

This JavaWorld article goes into more detail on your problem space.

这篇关于Spring同步Hibernate和JMS事务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 06:59