Grails / Hibernate Как распутать исключение без открытия сеанса, вызванное сохранением объекта в сеансе http

#hibernate #session #grails

#спящий режим #сеанс #grails

Вопрос:

Я знаю, что сохранение объекта в сеансе http — плохая идея, поскольку OSIV не может разрешить исключение LazyInitializationException, вызванное, когда я пытаюсь получить доступ к свойству типа коллекции этого объекта.

К сожалению, я сохранял некоторые объекты в сеансе http, например, CurrentUser :

Я сохраняю текущего пользователя в сеансе http следующим образом :

 session.currentUser = loggedUser
 

У пользователя есть коллекция правил, например

 session.currentUser.rules
 

Как и ожидалось, когда я пытаюсь получить доступ к коллекции правил в последующих запросах, я получаю исключение LazyInitializationException, поскольку session.CurrentUser теряет контекст сохранения.

Несмотря на то, что я перехожу к правильному подходу, который сохраняет идентификатор объекта в сеансе http, я должен найти решение для обеспечения того, чтобы доступ к свойству коллекции объектов, хранящихся в сеансе http, не вызывал исключения LazyInitializationException.

Я думаю о решении путем переопределения метода HttpSession:

 HttpSession.metaClass.getProperty { name ->
        if(name.equals("currentUser")){
            def userId = delegate.getProperty(name).id
            def userInstance = Utilisateur.get(userId)
            println 'in metaclass currentUser '   userInstance.isAttached()
            return userInstance
        }else{
            return  delegate.getProperty(name)
        }
    }
 

вместо прямого возврата текущего пользователя я извлекаю вложенный объект из сеанса гибернации с помощью метода Get().

это решение кажется работающим, как вы думаете, это хорошая идея?

Ответ №1:

Самым простым решением было бы сделать rules ассоциацию не ленивой

 static mapping = {
  rules lazy:false
}
 

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

Комментарии:

1. привет, Робертс, но я все еще хочу иметь режим отложенной выборки.

Ответ №2:

Вы должны убедиться, что ваш объект полностью инициализирован, прежде чем помещать его в сеанс. Лучший способ сделать это — обеспечить быстрый запрос. Так, например, если у вас User есть rules , вы бы сделали:

 session.currentUser = User.findByLogin("blah", [fetch:[rules:"eager"])
 

Комментарии:

1. привет, Рошер, спасибо за ответ. но как вы думаете, мое решение будет работать нормально (переопределить getProperty() класса HttpSession)?

2. другой вопрос: является ли это нетерпеливым finder (User.findByLogin(«blah», [fetch:[rules:»нетерпеливый»])) эквивалентным Hibernate.initialize(usr.rules) ? Спасибо