Spring Bean зависает в методе с @Transactional

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

Это приложение создает несколько потоков MessageListner для чтения объектов из очередей JMS. Как только объект получен, данные манипулируются на основе некоторой бизнес-логики, а затем сопоставляются с объектом сохранения для сохранения в базе данных оракула с использованием спящего режима EntityManager.

Еще несколько недель назад не было никаких серьезных проблем с этой конфигурацией за последний год или около того с тех пор, как я присоединился к проекту. Но для одной из очередей (проблема изолирована для этой конкретной очереди) управляемый компонент spring, который обрабатывает полученный объект, зависает в методе ниже. Моя отладка привела меня к выводу, что он выполнил все в методе, но зависает после завершения. После нескольких недель попыток решить эту проблему я в конце концов с этой проблемой. Любая помощь в этом будет принята с благодарностью.

Поскольку каждый MessageListner получает свой собственный процессор, этот метод зависания влияет только на входящие данные в одной очереди.

@Transactional(propagation = Propagation.REQUIRES_NEW , timeout = 180)
 public void update(UserRelatedData userData, User user,Company company,...)
 { 
   ...
   ....
   //business logic performed on user object
   ....
   ......
   entityMgr.persist(user);

   //business logic performed on userData object
   ...
   ....
   entityMgr.persist(userData);

   ...
   ....

   entityMgr.flush();

}

Я вставил операторы отладки только для того, чтобы пройтись по методу, и он завершает все, включая entityMgr.flush.().


person Rhouujin    schedule 17.11.2011    source источник


Ответы (4)


REQUIRES_NEW может зависнуть в тестовом контексте, потому что диспетчер транзакций, используемый в модульном тестировании, не поддерживает вложенные транзакции... Из Javadoc JpaTransactionManager:

* <p>This transaction manager supports nested transactions via JDBC 3.0 Savepoints.
 * The {@link #setNestedTransactionAllowed "nestedTransactionAllowed"} flag defaults
 * to {@code false} though, since nested transactions will just apply to the JDBC
 * Connection, not to the JPA EntityManager and its cached entity objects and related
 * context. You can manually set the flag to {@code true} if you want to use nested
 * transactions for JDBC access code which participates in JPA transactions (provided
 * that your JDBC driver supports Savepoints). <i>Note that JPA itself does not support
 * nested transactions! Hence, do not expect JPA access code to semantically
 * participate in a nested transaction.</i>

Так что ясно, если вы не вызываете (@Java config) или не устанавливаете эквивалентный флаг в своей конфигурации XML:

txManager.setNestedTransactionAllowed(true);

или, если ваш драйвер не поддерживает точки сохранения, "нормально" получить проблему с REQUIRES_NEW... (некоторые могут предпочесть исключение "вложенные транзакции не поддерживаются")

person p3consulting    schedule 05.08.2017

Проблемы такого рода могут проявляться, когда базовая база данных имеет блокировки от незафиксированных изменений.

Я подозреваю, что какой-то другой код вставляет/удаляет таблицы (таблицы) userData вне транзакции или в транзакции, выполнение которой занимает очень много времени, поскольку это пакетное задание или подобное. Вам следует проанализировать весь код, относящийся к этим таблицам, и найти отсутствующие @Transactional.

person mrembisz    schedule 17.11.2011
comment
Это старый, но я вернусь к комментарию на случай, если у кого-то возникнет аналогичная проблема. Оказалось проблема с базой данных. После нескольких встреч с администратором баз данных мы, наконец, решили эту проблему. - person Rhouujin; 22.08.2013
comment
в чем была проблема ? - person Robocide; 09.06.2015

Помимо этого ответа, вы также можете проверить уровень изоляции вашей транзакции, возможно, он слишком ограничительный.

Зависает ли метод update() навсегда или выдает исключение по истечении тайм-аута?

person MaDa    schedule 17.11.2011
comment
Метод обновления зависает навсегда, в настоящее время мы работаем со старшим разработчиком, чтобы выяснить, можем ли мы определить, является ли это проблемой блокировки таблиц. - person Rhouujin; 18.11.2011

К сожалению, у меня такая же проблема с Propagation.REQUIRES_NEW. Его удаление решает проблему. Отладчик показывает мне, что метод фиксации зависает (вызывается из реализации аспекта @Transactional).

Проблема появляется только в контексте тестового источника, когда приложение развернуто на сервере приложений, оно работает нормально.

person Vladimir Balandin    schedule 08.11.2012