У меня следующая установка.
- Весна 3.0.5
- Спящий режим 3.5.6
- MySQL 5.1
Чтобы сохранить запись в БД через Hibernate, у меня есть следующий рабочий процесс.
отправьте JSON
{id:1,name:"test",children:[...]}
в приложение Spring MVC и используйте Джексона для преобразования его в граф объектов (если это существующий экземпляр, JSON имеет правильный идентификатор записи в наборе БДсохранить объект в БД через вызов сервисного уровня (подробности ниже)
функция сохранения интерфейса сервисного уровня
SomeObjectService
имеет аннотацию @Transactional сreadOnly=false
и распространениемREQUIRED
реализация этого сервисного уровня
SomeObjectServieImpl
вызывает метод сохранения DAODAO сохраняет новые данные с помощью вызова слияния спящего режима, например.
hibernateTempate().merge(someObj)
hibernate
merge
сначала загружает объект из БД черезSELECT
У меня есть EntityListener, который подключен к Spring (я использовал эту технику Spring + EntityManagerFactory + Hibernate Listeners + Injection) и слушает
@PostLoad
Слушатель использует
LockingServie
для обновления одного поляsomeObject
, чтобы установить его как заблокированное (это на самом деле должно происходить только тогда, когдаsomeObject
загружается через вызовы Hibernate HQL, SQL или Criteria, но также вызывается при слиянии)LockingServie
имеет функциюlock(someObj,userId)
, которая также аннотирована @Transactional сreadOnly=false
иREQUIRED
обновление происходит через вызов
Query query = sess.createQuery("update someObj set lockedBy=:userId");
, а затемquery.executeUpdate();
после того, как слияние загрузило данные, оно начинается с обновления
someObject
и вставки соответствующих дочерних элементов (‹= именно здесь происходит тупиковая ситуация)
вернуть результат JSON (включая вновь созданный идентификатор объекта) обратно клиенту.
Проблема мне видится в том, что сначала
- запись загружается в транзакцию
- затем изменяется в другой (внутренней) транзакции
- а затем должен снова обновиться с данными внешней транзакции, но не может быть обновлен, потому что он заблокирован.
Я вижу через MySQL
SHOW OPEN TABLES
что дочерняя таблица (которая является частью графа объектов) заблокирована.
Интересным фактом является то, что взаимная блокировка возникает не в таблице someObj, а в таблице, представляющей дочерний элемент.
Я немного потерялся здесь. Любая помощь более чем приветствуется.
Кстати, возможно, isolation избавит меня от этой проблемы?