Смесване на 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 (трябва да поддържам hibernate и eclipselink), hornetQ и bitronix. Надяваме се, че това е достатъчно, за да преоткрием колелата...   -  person Andreas Dolk    schedule 27.12.2012


Отговори (1)


Всъщност реших проблема си с малко по-различен подход. Вместо да „смесвам“ JTA и JDBC транзакции, използвах спиране и възобновяване за работа с различни потребителски транзакции.

Задачата е все същата: стартирам (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