JtaTransaction localStatus откатывается после создания

#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 вызове метода or CustomSessionWrapper класса.

Ответ №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. Я думаю, что я выяснил, что откатывает транзакцию, и обновил вопрос. Может быть, вы что-то знаете 🙂