Смешивание транзакций JTA и JDBC

У меня есть сценарий Java SE (!) с JMS и JPA, где мне могут понадобиться распределенные транзакции, а также «обычные» транзакции JDBC. Мне нужно прослушивать очередь, которая отправляет запросы на обслуживание, сохранять журнал при получении, обрабатывать запрос и обновлять журнал после обработки запроса. Сообщение должно быть подтверждено только в том случае, если запрос был успешно обработан.

Первая идея заключалась в том, чтобы использовать только JTA (предоставляется Bitronix). Но тут я сталкиваюсь с двумя проблемами:

  1. журнал не будет сохраняться, если запрос не может быть обработан
  2. запрос не будет обработан, если журнал не может быть обновлен (маловероятно, но все же возможно)

Итак, другая идея состоит в том, чтобы создать и обновить журнал с помощью обычных транзакций JDBC. Только менеджеры сущностей для транзакций запроса будут присоединяться к транзакциям пользователя, а менеджеры сущностей для создания и обновления журнала будут фиксироваться напрямую.

Можно ли «смешивать» JTA и JPA в одном блоке персистентности? Или у нас уже есть шаблоны для таких транзакций JMS и JDBC?


person Andreas Dolk    schedule 27.12.2012    source источник
comment
Мне кажется, что на самом деле это не зависит от того, используется ли JTA или нет; вы хотите использовать две изолированные транзакции для выполнения работы. IE. сохранение журналов должно выполняться в их собственных (вложенных) транзакциях. Я не знаю, как именно это сделать, используя JTA напрямую, я говорю только о том опыте, который у меня есть при использовании технологии EJB. Сохранение журналов я бы сделал в аннотированном REQUIRES_NEW вызове EJB, который создает изолированную вложенную транзакцию для этого вызова.   -  person Gimby    schedule 27.12.2012
comment
На самом деле это три изолированные транзакции, в то время как внешняя транзакция является пользовательской транзакцией JTA... Вложенные транзакции звучат хорошо, некоторые реализации JTA даже поддерживают их, но они не являются частью стандарта JTA. Спасибо за подсказку!   -  person Andreas Dolk    schedule 27.12.2012
comment
Быстрое исследование: нет вложенных транзакций с bitronix, но: решение моего вопроса могло быть предоставлено с этим ответом (найденным Google): stackoverflow .com/a/7674560/105224 может помочь приостановка работы менеджера транзакций.   -  person Andreas Dolk    schedule 27.12.2012
comment
JTA используется в компонентах EJB, которые имеют распространение REQUIRES_NEW. Транзакция на самом деле не является вложенной. Внешняя транзакция приостанавливается, запускается и фиксируется или откатывается новая транзакция, затем внешняя транзакция возобновляется. Если вы работаете в среде Java SE, я предлагаю использовать Spring, который сделает это за вас.   -  person JB Nizet    schedule 27.12.2012
comment
Я бы использовал Spring, если бы мне разрешили;) У меня есть только J2SE, JPA (необходимо поддерживать как спящий режим, так и eclipselink), hornetQ и bitronix. Надеюсь, этого достаточно, чтобы изобретать велосипеды...   -  person Andreas Dolk    schedule 27.12.2012


Ответы (1)


Я на самом деле решил свою проблему с немного другим подходом. Вместо «смешивания» транзакций JTA и JDBC я использовал suspend и resume для работы с разными пользовательскими транзакциями.

Задача все та же: запускаю (JTA) пользовательскую транзакцию, которая содержит некоторые транзакции JMS и JDBC (получение сообщения, выполнение некоторых операций с базой данных). И в середине этого рабочего процесса я хочу написать журнал сообщений, но этот журнал не будет откатываться, когда «внешняя» транзакция терпит неудачу.

Итак, решение в псевдокоде:

 transactionManager.begin()
 doSomeJdbcStuff();
 Transaction main = transactionManager.suspend();

 // do the logging
 transactionManager.begin()  // <- now a new transaction is created and active!
 doSomeLogging();
 transactionManager.commit()

 // continue
 transactionManager.resume(main);
 doSomeMoreJdbcStuff();
 transactionManager.commit();
person Andreas Dolk    schedule 08.01.2013