У меня есть приложение Grails (2.5.4), развернутое в рабочей среде, которое получает большой объем трафика.
Мы получаем периодические исключения LazyInitializationException
при попытке доступа к полям из объектов домена, которые хранятся в сеансе.
Чтобы уточнить, как работает поток:
У нас есть фильтр (http://docs.grails.org/2.5.4/ref/Plug-ins/filters.html), который вызывается перед каждым действием контроллера. В этом фильтре мы сохраняем объект домена в сеансе (http://docs.grails.org/2.5.4/ref/Servlet%20API/session.html) следующим образом:
session.account = Account.get(1)
В контроллере мы получаем домен следующим образом:
def account = session.account
Затем мы передаем объект домена другой службе, которая вызывает другую службу, которая в конечном итоге пытается вызвать поле hasMany в объекте домена следующим образом:
account.transactions.name
Приведенное выше выдает LazyInitializationException
с сообщением, подобным этому:
failed to lazily initialize a collection of role: com.example.app.Account.transactions, no session or session was closed
Таким образом, по какой-то причине сеанс Hibernate закрывается до завершения запроса, отсюда и исключение отложенной загрузки.
Мы обнаружили, что следующие действия в контроллере полностью устраняют возникновение ошибки:
Account account = Account.findById(session.account.id)
Проблема в том, что я понятия не имею, почему, и хотел бы понять, почему это устраняет проблему, прежде чем слепо внедрять это исправление в другие части приложения. Я не вижу причин, по которым объект должен отсоединяться от сеанса Hibernate, поскольку весь этот поток происходит в рамках одного и того же запроса. Вдобавок ко всему, это очень случайная проблема - она возникает, может быть, в 1% случаев, когда выполняется запрос, если не меньше.
Чтобы уточнить, вопрос; Почему сеанс закрывается и почему объект отсоединяется от сеанса Hibernate, когда все это происходит в одной области запроса? Кроме того, почему это происходит очень редко и случайным образом?
account.attach()
перед попыткой доступа кaccount.transactions
? См. docs.grails.org/latest/ref/Domain%20Classes/attach. .html - person Emmanuel Rosa   schedule 08.12.2016Account account = Account.findById(session.account.id)
. Мой вопрос не в том, как повторно подключить домен к сеансу, поскольку это легко, а в том, почему он вообще отключается. Документация в указанной вами ссылке гласит: если объект извлекается из сеанса и помещается в веб-область, такую как HttpSession, он будет отсоединен от сеанса Hibernate после закрытия сеанса и его удаления. Так почему же сеанс закрывается и отбрасывается, если запрос не завершен? - person DeaIss   schedule 08.12.2016