2012-05-29 123 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。有據可查的產品。 –