简体   繁体   English

Spring同步Hibernate和JMS事务

[英]Spring synchronising Hibernate and JMS transactions

I am working on a stand-alone application that uses both JMS and Hibernate. 我正在使用一个同时使用JMS和Hibernate的应用程序。

The documentation suggests JTA has to be used if I want to have transactions across both resources. 文档建议如果我想在两个资源之间进行交易,则必须使用JTA。

However, right now with a @Transaction annotated DAO method (and HibernateTransactionManager), this already seems to work. 但是,现在使用@Transaction带注释的DAO方法(和HibernateTransactionManager),这似乎已经起作用了。 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. 当我在JmsTemplate上调用send()时,消息不会立即发送,而是在方法返回时使用Hibernate会话提交JMS会话。

I didn't know how this is possible without the JtaTransactionManager, so I checked the source code. 如果没有JtaTransactionManager,我不知道这是怎么可能的,所以我检查了源代码。 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. 事实证明,Hibernate和JmsTemplate的包装器都会使用TransactionSynchronizationManager注册会话,并且在Hibernate会话提交时将提交JMS会话。

What's the different between this and a JTA transaction. 这和JTA交易有什么不同。 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. 简而言之,如果没有JTATransactionManager和XA感知数据源,您将无法获得对两阶段提交的支持。

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 启动JMS事务
  2. Read JMS message 读取JMS消息
  3. Start JDBC Transaction 启动JDBC事务
  4. Write to database 写入数据库
  5. Commit JDBC Transaction 提交JDBC事务
  6. Commit/Acknowledge JMS 提交/确认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. 首先将包装嵌套的JDBC事务启动JMS事务,以便在Hibernate / JDBC提交失败时回滚JMS队列。 Your JMS Listener Container should be setup not to acknowledge="auto" and instead wait for the Hibernate transaction to complete before sending the acknowledgement. 您的JMS侦听器容器应设置为 acknowledge="auto" ,而是在发送确认之前等待Hibernate事务完成。

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. 如果您只有这两个资源,那么您必须考虑的问题是,当Hibernate成功持久化时,您会在确认JMS服务器之前获得异常。 Not a big issue as the JMS message is not lost and you will read it again. 这不是一个大问题,因为JMS消息不会丢失,您将再次阅读它。

However 然而

  1. You must write your MessageListener to handle duplicate messages from the server 您必须编写MessageListener来处理来自服务器的重复消息

  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 在这种情况下,服务器可能配置为将消息移动到“死消息队列”,或者您自己在MessageListener中处理此消息

Other options and further reading 其他选项和进一步阅读

If your JMS server does not support XA (global) transactions this is pretty much your only solution. 如果您的JMS服务器不支持XA(全局)事务,那么这几乎是您唯一的解决方案。

If JMS server does support XA transactions but JDBC doesn't then you can use a JTATransactionManager and use the LastResourceCommitOptimisation . 如果JMS服务器确实支持XA事务但JDBC没有,那么您可以使用JTATransactionManager并使用LastResourceCommitOptimisation There are open source JTATransactionManagers you can use like JOTM 有像JOTM一样可以使用的开源JTATransactionManagers

This JavaWorld article goes into more detail on your problem space. 这篇JavaWorld文章详细介绍了您的问题空间。

Although this has been answered in detail by Brad, i would like to address a very specific part of your query:- 虽然Brad已经详细解答了这个问题,但我想解决一下你查询的一个非常具体的部分: -

I didn't know how this is possible without the JtaTransactionManager 如果没有JtaTransactionManager,我不知道这是怎么回事

From the spring documentation:- When a JTA environment is detected, Spring's JtaTransactionManager will be used to manage transactions 从spring文档: - 当检测到JTA环境时,Spring的JtaTransactionManager将用于管理事务

https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-jta.html https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-jta.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM