【问题标题】:Spring synchronising Hibernate and JMS transactionsSpring同步Hibernate和JMS事务
【发布时间】:2012-06-03 17:02:14
【问题描述】:

我正在开发一个同时使用 JMS 和 Hibernate 的独立应用程序。

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

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

我不知道没有 JtaTransactionManager 怎么可能,所以我检查了源代码。事实证明,Hibernate 的包装器和 JmsTemplate 都使用 TransactionSynchronizationManager 注册会话,并且 JMS 会话将在 Hibernate 会话提交时提交。

这与 JTA 事务有什么不同。我可以用它来代替后者吗??

【问题讨论】:

  • 您是否检查过其中一个失败时会发生什么?它们都回滚了吗?

标签: java spring hibernate transactions jms


【解决方案1】:

简而言之,如果没有 JTATransactionManager 和 XA 感知数据源,您将无法获得对两阶段提交的支持。

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

  1. 启动 JMS 事务
  2. 读取 JMS 消息
  3. 启动 JDBC 事务
  4. 写入数据库
  5. 提交 JDBC 事务
  6. 提交/确认 JMS

JMS 事务将首先包装嵌套的 JDBC 事务,这样如果 Hibernate/JDBC 提交失败,JMS 队列将回滚。您的 JMS 侦听器容器应设置为不要 acknowledge="auto",而是等待 Hibernate 事务完成后再发送确认。

如果您只有这两个资源,那么您必须考虑的问题是当 Hibernate 成功持久化时,您会在确认 JMS 服务器之前收到一个异常。不是什么大问题,因为 JMS 消息没有丢失,您将再次阅读它。

但是

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

  2. 您还必须处理由于数据错误而无法处理的消息,并最终陷入无限循环尝试接收它。在这种情况下,服务器可能被配置为将消息移动到“死消息队列”,或者您自己在 MessageListener 中处理这个

其他选项和进一步阅读

如果您的 JMS 服务器不支持 XA(全局)事务,这几乎是您唯一的解决方案。

如果 JMS 服务器确实支持 XA 事务但 JDBC 不支持,那么您可以使用 JTATransactionManager 并使用 LastResourceCommitOptimisation。有一些开源的 JTATransactionManager 可以像 JOTM 一样使用

This JavaWorld article 更详细地介绍了您的问题空间。

【讨论】:

  • 在独立环境中,我非常成功地使用了 Atomikos。一个有据可查的产品。
【解决方案2】:

虽然 Brad 已经详细回答了这个问题,但我想解决您查询的一个非常具体的部分:-

如果没有 JtaTransactionManager,我不知道这怎么可能

来自 spring 文档:- 当检测到 JTA 环境时,Spring 的 JtaTransactionManager 将用于管理事务

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

【讨论】:

    猜你喜欢
    • 2012-03-03
    • 2011-06-13
    • 1970-01-01
    • 1970-01-01
    • 2015-01-22
    • 1970-01-01
    • 1970-01-01
    • 2017-07-17
    • 2015-03-26
    相关资源
    最近更新 更多