2012-05-29 83 views
5

我正在使用同时使用JMS和Hibernate的独立应用程序。Spring同步Hibernate和JMS事务

如果我希望跨两种资源进行交易,则文档建议使用JTA。

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

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

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

+0

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

回答

12

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

你目睹的是两个本地交易的配合​​,仅支持单阶段提交。粗略地执行该序列的事件......

  1. 开始JMS交易
  2. 阅读JMS消息
  3. 开始JDBC事务
  4. 写入数据库
  5. 提交JDBC事务
  6. 提交/应答JMS

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

如果你只有这两个资源,那么你将不得不考虑的问题是,当Hibernate成功执行persistence时,你会得到一个Exception,然后你可以确认JMS服务器。由于JMS消息不会丢失,所以您不会再遇到大问题,您可以再次阅读。

然而

  1. 您必须编写了MessageListener从服务器

  2. 还必须处理不能处理因不良数据,并在结束了一个消息处理重复的邮件试图对它进行无限循环。在这种情况下,服务器可以配置为邮件移动到“停用消息队列”,或者你自己在消息监听对付这种

其他选项,并进一步阅读

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

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

This JavaWorld article更详细的问题空间。

+0

在独立环境中,我非常成功地使用了Atomikos。有据可查的产品。 –