Вопрос по jms, java, spring, transactions, hibernate – Spring синхронизирует транзакции Hibernate и JMS

5

Я работаю над автономным приложением, которое использует JMS и Hibernate.

В документации предлагается использовать JTA, если я хочу, чтобы транзакции проходили через оба ресурса.

Однако сейчас, с аннотированным методом DAO @Transaction (и HibernateTransactionManager), это, похоже, уже работает. Когда я вызываю send () для JmsTemplate, сообщение отправляется не сразу, а сеанс JMS фиксируется с сеансом Hibernate, когда метод возвращается.

Я не знал, как это возможно без JtaTransactionManager, поэтому я проверил исходный код. Оказывается, что и оболочка для Hibernate, и JmsTemplate регистрируют сеансы с помощью TransactionSynchronizationManager, и сеанс JMS будет зафиксирован при фиксации сеанса Hibernate.

В чем разница между этой транзакцией и транзакцией JTA. Могу ли я использовать это, чтобы заменить последний ??

Вы проверили, что происходит, когда один из них выходит из строя? Откат обоих? Aravind R. Yarram

Ваш Ответ

2   ответа
12

Короче говоря, нет, вы не можете получить поддержку двухфазной фиксации без источников данных с поддержкой JTATransactionManager и XA.

То, что вы видите, является координацией двухLocal Transactions поддержка только однофазного коммита. Грубо выполняя эту последовательность событий ...

Start JMS Transaction Read JMS message Start JDBC Transaction Write to database Commit JDBC Transaction Commit/Acknowledge JMS

Транзакция JMS будет запущена вначале, оборачивая вложенную транзакцию JDBC, так что очередь JMS будет откатываться в случае сбоя фиксации Hibernate / JDBC. Ваш JMS Listener Container должен быть настроенnot to acknowledge="auto" и вместо этого дождитесь завершения транзакции Hibernate перед отправкой подтверждения.

Если у вас есть только эти два ресурса, то проблема, с которой вам придется столкнуться, заключается в том, когда Hibernate преуспевает в сохранении, тогда вы получите исключение, прежде чем сможете подтвердить JMS-сервер. Не большая проблема, поскольку сообщение JMS не потеряно, и вы прочитаете его снова.

However

You must write your MessageListener to handle duplicate messages from the server

You must also handle a message that cannot be processed due to bad data and ending up in an infinite loop of trying to comsume it. In this case the server may be configured to move the message to a "dead message queue", or you deal with this yourself in the MessageListener

Other options and further reading

Если ваш JMS-сервер не поддерживает XA (глобальные) транзакции, это практически единственное ваше решение.

Если JMS-сервер поддерживает транзакции XA, а JDBC - нет, то вы можете использовать JTATransactionManager и использоватьLastResourceCommitOptimisation, Есть JTATransactionManager с открытым исходным кодом, который вы можете использовать как JOTM

Эта статья о JavaWorld подробнее расскажет о вашем проблемном пространстве.

В автономной среде я очень успешно использовал Atomikos. Хорошо документированный продукт.
0

Хотя Брэд подробно ответил на этот вопрос, я бы хотел затронуть очень специфическую часть вашего запроса:

I didn't know how this is possible without the JtaTransactionManager

Из весенней документации: - When a JTA environment is detected, Spring’s JtaTransactionManager will be used to manage transactions

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

Похожие вопросы