Xpoint
   [напомнить пароль]

Синхронизация сессий в Hibernate

Метки: [без меток]
2009-07-07 13:11:24 [обр] Сергей Золотухин(0/126)[досье]

Имеем два класса: House и Photo. Класс House имеет свойство List<Photo> photos. Сохранение этой конструкции в БД управляется с помощью Hibernate (с использованием SessionFactory).

Имеется веб-интерфейс для редактирования свойст House, который, естественно, загружает соотв. экземпляр из БД:

House house = houseDao.read(houseId);

В этом интерфейсе реализована загрузка фотографий с помошью ajax. В ajax-сервлете тоже выполняется houseDao.read(houseId) для того, чтобы

Photo photo = new Photo();
...
house.getPhotos().add(photo);
houseDao.update(house);

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

Проблема "лечится" принудительным закрыванием сессии в HouseDao.read, но в этом случае нет возможности реализовать Lazy-загрузку остальных данных.

Можно, наверное, создать два метода в HouseDao: read и readAndCloseSession, но я надеюсь что есть более красивое решение этой проблемы и вы мне его подскажете.

PS. Простите, если получилось слишком длинно.

спустя 2 дня 4 часа [обр] GRAy(14/259)[досье]
Сергей Золотухин[досье] А что значит "в параллельной сессии"? Откуда она вдруг берётся, ведь по идее houseDao - это для всего вашего приложения static объект (не обязательно реализованный как static поле, но фактически).
спустя 29 дней [обр] Igor Rulyov(0/19)[досье]

Очень много много используем подобные конструкции (форма и подгружаемые елементы посредством Ajax запросов). Впервые слышу о таком.
Вкратце скажу, что у нас MVC, где диспетчер (или брокер) - сервлет. Абсолютно все запросы идут через этот один единственный сервлет. Серлет (используя Reflection и MethodInvocation) перенаправялет запросы ответственному методу в нужном классе контроллера.
Так вот. Первый шаг в этом главном сервлете - старт сессии Hibernate, а последняя строка - закрытие сессии (flush, commit). Т.е.:

HbnSessionStart
businessLogic (invoked method)
HbnSessionEnd

Единственное: в одном из проектов было маленькое исключение... приходилось пару раз использовать насильный flush в теле методов. Была сложная ситуация с БД - не всегда был шанс применять HQL на уровне DAO. Пришлось мешать с SQL.

Например: таблица с данными. удаление строки.

HbnSessionStart
...
viewMethod(...)
* elemDAO.delete(id) // SQL!
* elemDAO.getAll() // HQL!
JSP rendering
...
HbnSessionEnd

В общем объект удаленный при помощи SQL (Hibernate.createQuery...) снова "всплывал" в таблице сразу после удаления. Простое обновление страницы после удаления - объект исчезал.

Т.е. HQL вероятно не "видит" что мы творим напрямую с SQL... что логично в некоторой степени. Поэтому между delete и getAll мы использовали HbnSession.flush

Powered by POEM™ Engine Copyright © 2002-2005