#java #hibernate #jta
#java #спящий режим #jta
Вопрос:
Я создаю спящий Session
режим и пытаюсь запустить новую транзакцию [Jta]. Тем не менее, транзакция не может быть запущена, потому что JtaTransaction, который используется в фоновом режиме, похоже, откатывается.
Вот что я делаю.
Session session = sessionFactory.openSession();
CustomSessionWrapper dpSession = new CustomSessionWrapper(session, this);
if (!session.isClosed() amp;amp; !session.getTransaction().isActive()) {
session.beginTransaction();
}
Тем не менее, транзакция по-прежнему не активна после beginTransaction
вызова. Когда я отлаживаю beginTransaction
метод, я прихожу к doBegin
методу JtaTransaction
(я не переопределяю этот метод, я просто публикую исходный код этого метода).
@Override
protected void doBegin() {
LOG.debug( "begin" );
userTransaction = locateUserTransaction();
try {
if ( userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION ) {
userTransaction.begin();
isInitiator = true;
LOG.debug( "Began a new JTA transaction" );
}
}
catch ( Exception e ) {
throw new TransactionException( "JTA transaction begin failed", e );
}
}
userTransaction.getStatus()
Возвращается, Status.STATUS_ROLLEDBACK
и транзакция не запускается. Кто-нибудь знает, как я могу это исправить?
ОБНОВЛЕНИЕ 1 (вы можете пропустить это, поскольку это была ошибка, см. ОБНОВЛЕНИЕ 2)
Я обнаружил, что есть два потока, один из которых использует основной сеанс, а другой использует меньшие сеансы для ведения журнала. Основной сеанс (и транзакция) открыты в течение более длительного периода времени, то есть в основном до завершения операции. Кажется, что locateUserTransaction
всегда возвращается одно и то же userTransaction
. Это означает, что основной сеанс открывает эту пользовательскую транзакцию, а одна из побочных транзакций фиксирует / откатывает эту транзакцию. Кто-нибудь знает, что делать, чтобы извлекались разные транзакции?
ОБНОВЛЕНИЕ 2
Я обнаружил, что у меня нет двух потоков, только один поток открывает два сеанса параллельно. Затем каждый сеанс должен открывать свою собственную транзакцию, хотя оба получают одну и ту же пользовательскую транзакцию. Как я могу сообщить hibernate, что каждый сеанс должен получать свою собственную транзакцию [User]?
Комментарии:
1. Вы закрыли сеанс везде в своем приложении?
2. Да, сеанс всегда закрывается при
commit
rollback
вызове метода orCustomSessionWrapper
класса.
Ответ №1:
Hibernate абстрагирует как локальные, так и JTA-транзакции за своим собственным уровнем абстракции, поэтому я не понимаю, почему вам нужно писать такой низкоуровневый код обработки транзакций.
В Java EE у вас есть сервер приложений для управления транзакциями, в автономных приложениях Bitronix Spring тоже выполняют свою работу.
Хотя вы можете написать свою собственную логику управления транзакциями, я всегда советую людям повторно использовать то, что у них уже есть. Для бесперебойной работы Xa / JTA и Hibernate требуются обширные знания.
Обновление 1
Два разных потока не должны использовать одну и ту же пользовательскую транзакцию, вы должны использовать разные транзакции для каждого потока.
Комментарии:
1. Привет, спасибо за ваше предложение. К сожалению, есть две причины, по которым я не могу использовать этот подход (хотя я бы сделал это, если бы мог …). Сначала код должен работать для веб-сервисов и fatclients. Веб-сервисы используют jta, тогда как fatclients используют jdbc. Во-вторых, этот код находится в огромной кодовой базе, поэтому переписать все невозможно. Недавно мы обновились с hibernate 3.2 до 4.3, и с тех пор возникает эта проблема…
2. Я также не переопределяю метод doBegin, я просто опубликовал исходный код, чтобы рассказать вам, что я узнал.
3. Я понимаю. Ну, если транзакция была помечена как откатная, вы больше не можете ее использовать, единственное решение — запустить новую. Поскольку транзакции привязаны к потокам, вы должны позволить ему выполнить откат, выйти из границы транзакции и повторить попытку с ближайшей внешней точки, где начинается граница транзакции (обычно @Transactional service). Обычно я делаю это с помощью AOP, где я просто повторяю попытку, если транзакция завершилась неудачно, но ее можно восстановить (например, оптимистичная блокировка, взаимоблокировки). Обязательно выяснить, что заставляет вашу транзакцию откатываться.
4. Спасибо, в настоящее время я занимаюсь тем, что откатывает транзакцию.
5. Я думаю, что я выяснил, что откатывает транзакцию, и обновил вопрос. Может быть, вы что-то знаете 🙂