Java Spring同步Hibernate和JMS事务

Java Spring同步Hibernate和JMS事务,java,spring,hibernate,transactions,jms,Java,Spring,Hibernate,Transactions,Jms,我正在开发一个同时使用JMS和Hibernate的独立应用程序 文档表明,如果我想在两种资源之间进行事务处理,就必须使用JTA 然而,现在使用@Transaction注释的DAO方法(和HibernateTransactionManager),这似乎已经起作用了。在JmsTemplate上调用send()时,消息不会立即发送,而是在方法返回时,通过Hibernate会话提交JMS会话 我不知道没有JtaTransactionManager怎么可能做到这一点,所以我检查了源代码。事实证明,Hibe

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

文档表明,如果我想在两种资源之间进行事务处理,就必须使用JTA

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

我不知道没有JtaTransactionManager怎么可能做到这一点,所以我检查了源代码。事实证明,Hibernate包装器和JmsTemplate都向TransactionSynchronizationManager注册了会话,并且当Hibernate会话提交时,JMS会话将被提交


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

简言之,不,如果没有JTATransactionManager和XA感知数据源,就无法获得对2阶段提交的支持

您看到的是两个本地事务的协调,它们只支持1阶段提交。大致执行这一系列事件

  • 启动JMS事务
  • 读取JMS消息
  • 启动JDBC事务
  • 写入数据库
  • 提交JDBC事务
  • 提交/确认JMS
  • JMS事务将首先包装嵌套的JDBC事务启动,这样,如果Hibernate/JDBC提交失败,JMS队列将回滚。您的JMS侦听器容器应该设置为而不是
    acknowledge=“auto”
    ,而是在发送确认之前等待Hibernate事务完成

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

    但是

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

  • 您还必须处理由于坏数据而无法处理的消息,并最终导致尝试使用它的无限循环。在这种情况下,可以将服务器配置为将消息移动到“死消息队列”,或者您自己在MessageListener中处理此问题

  • 其他选项和进一步阅读

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

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


    详细介绍您的问题空间。

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

    没有JtaTransactionManager,我不知道这是怎么可能的

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


    您是否检查了其中一个失败时会发生什么情况?它们都回滚吗?在一个独立的环境中,我非常成功地使用了Atomikos。有良好记录的产品。