6

私はJMSとHibernateの両方を使用するスタンドアロンアプリケーションに取り組んでいます。

ドキュメントでは、両方のリソースでトランザクションを実行する場合は、JTAを使用する必要があることが示されています。

ただし、現在、@ Transaction注釈付きDAOメソッド(およびHibernateTransactionManager)を使用すると、これはすでに機能しているようです。JmsTemplateでsend()を呼び出すと、メッセージはすぐには送信されませんが、メソッドが戻るときに、JMSセッションがHibernateセッションでコミットされます。

JtaTransactionManagerなしでこれがどのように可能かわからなかったので、ソースコードをチェックしました。HibernateのラッパーとJmsTemplateの両方がセッションをTransactionSynchronizationManagerに登録し、HibernateセッションがコミットするとJMSセッションがコミットされることがわかりました。

これとJTAトランザクションの違いは何ですか。これを使って後者を置き換えることはできますか?

4

2 に答える 2

15

つまり、JTATransactionManagerとXA対応のデータソースがないと、2フェーズコミットのサポートを利用できません。

あなたが目撃しているのは、 1フェーズコミットのみをサポートする2つのローカルトランザクションの調整です。この一連のイベントを大まかに実行しています...

  1. JMSトランザクションを開始します
  2. JMSメッセージを読む
  3. JDBCトランザクションを開始します
  4. データベースに書き込む
  5. JDBCトランザクションをコミットする
  6. JMSのコミット/確認

ネストされたJDBCトランザクションをラップする最初にJMSトランザクションが開始されるため、Hibernate/JDBCコミットが失敗した場合にJMSキューがロールバックされます。JMSリスナーコンテナは、確認応答を送信する前に、Hibernateトランザクションが完了するのを待たずに設定する必要があります。 acknowledge="auto"

これらの2つのリソースしかない場合、考慮しなければならない問題は、Hibernateが永続化に成功したときに、JMSサーバーを確認する前に例外が発生することです。JMSメッセージが失われることはなく、もう一度読むことができるため、大きな問題ではありません。

でも

  1. サーバーからの重複メッセージを処理するには、MessageListenerを作成する必要があります

  2. また、データが不良であるために処理できず、メッセージを消費しようとする無限ループに陥るメッセージを処理する必要があります。この場合、サーバーはメッセージを「デッドメッセージキュー」に移動するように構成されているか、MessageListenerで自分でこれを処理します。

その他のオプションと参考資料

JMSサーバーがXA(グローバル)トランザクションをサポートしていない場合、これがほとんど唯一の解決策です。

JMSサーバーはXAトランザクションをサポートしているが、JDBCはサポートしていない場合は、JTATransactionManagerを使用してLastResourceCommitOptimisationを使用できます。JOTMのように使用できるオープンソースのJTATransactionManagersがあります

このJavaWorldの記事では、問題領域について詳しく説明します。

于 2012-05-29T13:44:52.140 に答える
1

これはブラッドによって詳細に回答されていますが、私はあなたの質問の非常に特定の部分に対処したいと思います:-

JtaTransactionManagerなしでこれがどのように可能かわかりませんでした

Springのドキュメントから: -JTA環境が検出されると、SpringのJtaTransactionManagerがトランザクションの管理に使用されます

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

于 2017-09-25T10:38:46.527 に答える