Hibernate, GWT и Gilead: сессии, транзакции и кэши - PullRequest
0 голосов
/ 07 января 2010

Я пишу приложение GWT, использующее Hibernate на стороне сервера. Прямо сейчас я совершенно не понимаю, как правильно передать свои объекты на клиентскую часть приложения GWT с наименьшим количеством кода. Я использую Gilead, чтобы избежать удвоения количества классов в моей доменной модели [1].

Прежде всего, мой вопрос: как мне открывать сессии и транзакции? Первоначально я делал это при каждом вызове сервера RPC:

// begin rpc call
getCurrentSession
beginTransaction
// ...do stuff
commit
// session is automatically closed
// end rpc call

Поскольку это открывает и закрывает сеанс для каждого вызова RPC, создает ли это также новое соединение с сервером базы данных каждый раз?

В любом случае, как только я начинаю использовать лениво загруженные коллекции, я получаю следующее исключение, используя этот шаблон:

org.hibernate.HibernateException: collection is not associated with any session
at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:449)`

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

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

openSession
// begin rpc call
beginTransaction
// ...do stuff
commit
// end rpc call

// next rpc call
beginTransaction
// ...etc

Однако, когда я делаю это, я вижу все виды прикольного поведения, связанного с кешем объектов Session. Во-первых, createQuery (). ExecuteUpdate (), похоже, не делает недействительным кеш сеанса, хотя я читал на разных сайтах, что должен. Когда я попытался исправить это, попытавшись аннулировать кэш сеанса, вызвав различные перестановки session.flush (), session.clear () и т. Д., Следующей ошибкой было «ClassCastException: null» при сериализации глубоко внутри Gilead или Beanlib. .

Во-вторых, когда я пытаюсь что-то вроде этого:

clients get an object from the server
client modifies object
client sends object back
server calls session.saveOrUpdate()

Я получаю сообщение об ошибке типа «другой объект с таким же идентификатором уже находится в кэше сеанса».

Как правильно настроить подобные вещи? Как я должен охватить мои сеансы и как я должен обращаться с кешем? Я не могу себе представить, что я единственный, кто пробовал это и имел проблемы с этим, но, кажется, трудно найти хороших гидов.

[1] http://code.google.com/webtoolkit/articles/using_gwt_with_hibernate.html

Ответы [ 2 ]

0 голосов
/ 07 января 2010

Я не использую Gilead, так что это может быть частью проблемы, но я использую сеансы ThreadLocal. В каждом вызове rpc я заключаю логику в метод, который всегда закрывает сеанс ThreadLocal перед окончательным возвратом. Сессия открывается для этого потока при первом запросе.

Тем не менее, вы должны полностью инициализировать любые прокси, прежде чем закрыть сеанс. Скорее всего, GWT пытается сериализовать ваш POJO после закрытия сеанса, а когда он попадает в прокси или отложенную коллекцию, он непреднамеренно пытается его инициализировать. Лично я либо копирую POJO для разделения объектов, либо проверяю, точно ли я знаю, какие поля будут сериализованы, и заранее «трогаю» их (например, вызывая size () для коллекции. трудно, если у вас есть глубоко вложенные объекты.

Было бы хорошо, если бы был хук GWT, который позволял бы вам выполнять код после сериализации, но до завершения потока rpc. Возможно, что есть, и я просто не знаю об этом.

0 голосов
/ 07 января 2010

Посмотрите этот ответ и комментарии ниже.

Вопрос здесь не совпадает с вашим - это обобщение вашего - то есть, как объединить JPA (Hibernate) с удаленным взаимодействием (то есть сериализацию объектов и отправка их для чтения по проводам). Это не простая и тривиальная проблема, хотя и распространенная. Проверьте мои предложения там и сделайте комментарий здесь, если вы чего-то не понимаете.

...