У меня следующая установка.
- Весна 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 избавит меня от этой проблемы?