Как Hibernate управляет транзакцией с помощью нескольких session.update (), если вы не фиксируете транзакцию явно? - PullRequest
0 голосов
/ 17 июня 2020

Я унаследовал систему, использующую Spring MVC и Hibernate, которая хранится в базе данных DB2. Недавно DB2 начала сообщать о проблеме, похожей на тупиковую, поэтому я работал над ее отладкой. Я не специалист по Spring или Hibernate, но кое-что знаю об обоих.

Код структурирован следующим образом:

controller -> service -> one or more DAO classes that performs the updates

В ситуации, когда возникает проблема, контроллер вызывает службу метод, помеченный @Transactional и @Override. Служба переходит к классу DAO, помеченному @Repository, и вызывает несколько методов, аннотированных @Transactional и @Override. Такова структура кода.

Один контроллер вызывает один сервисный метод. Метод службы вызывает несколько методов DAO. Большинство методов DAO помечены @Transactional и @Override. Некоторые имеют REQUIRES_NEW в @Transactional. Также в каждом методе DAO Session получает SessionFactory.getCurrentSession().

Первый вопрос: при таком подходе, где начинается транзакция и где находится окончательная фиксация? А откат? Ничто из этого не кодируется явно.

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

Первоначальный кодировщик пытался добавить REQUIRES_NEW к @Transactional, думая, что новая транзакция обеспечит обновление. Но взаимоблокировка по-прежнему происходит с нерегулярными интервалами.

Я попытался изменить обновление на собственный вызов SQL, но Hibernate не позволяет мне начать другую транзакцию, поскольку она уже открыта.

Кто угодно есть какие-нибудь указания здесь?

1 Ответ

1 голос
/ 17 июня 2020

Транзакция начинается, когда метод (какой класс или сам метод сначала аннотируется @Transactional в цепочке вызовов) вызывается извне (он должен вызывать извне класса, потому что аннотация «создает» прокси). Любой другой аннотированный класс / методы в цепочке с уровнем распространения по умолчанию присоединится к этой транзакции. При вызове метода с транзакцией, помеченной как REQUIRES_NEW, родительская транзакция будет приостановлена ​​(если существует), и начнется новая транзакция. Обратите внимание, что если вы вызываете аннотированный метод из другого метода в том же классе, он не будет go через прокси, поэтому он будет таким же, как и вы удалите аннотацию. Фиксация произошла сразу после возврата метода, запустившего транзакцию. То же, что и откат, это произойдет после того, как будет создано исключение. Тупик может прийти из разных мест, это сложно определить, даже если у вас есть код. Это может, например, происходить из-за обновления, и хранимая процедура пытается заблокировать некоторые строки и cycli c wait happend et c ...

У меня наивное изображение, что происходит в фоновом режиме. Есть два класса ui и service. Услуга обозначена как @Transactional. Spring создает прокси, и все звонки извне приходят через него go. Прежде чем будет вызван реальный метод, он запустит транзакцию, после чего совершит фиксацию.

enter image description here

...