grails LazyInitializationException в транзакционном сервисе - PullRequest
3 голосов
/ 13 декабря 2011

У меня проблема.У меня есть сервис, который является транзакционным в Grails:

class MyService {

   static transactional = true

   Set<Furniture> getFurniture(Long idHouse) {
      return MyHouse.get(idHouse).getFurniture()
   }
}

В моем контроллере у меня есть: def myService, и я звоню myService.getFurniture(id)

Даже если мой сервис транзакционный, я получаю: LazyInitializationException Я использую Grails 2.0.0.RC3 Thx.

Ответы [ 2 ]

2 голосов
/ 13 декабря 2011

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

Так что вам просто нужно инициализировать коллекцию, и есть несколько вариантов.Одним из них является вызов метода size():

Set<Furniture> getFurniture(Long idHouse) {
   def furniture = MyHouse.get(idHouse).furniture
   furniture.size() // force eager init
   furniture
}

Это заставит Hibernate перейти в базу данных и заполнить коллекцию.Это зависит от побочного эффекта, хотя - лучший способ позвонить Hibernate.initialize():

import org.hibernate.Hibernate
...

Set<Furniture> getFurniture(Long idHouse) {
   def furniture = MyHouse.get(idHouse).furniture
   Hibernate.initialize furniture
   furniture
}
1 голос
/ 15 декабря 2011

Даже если ваш класс обслуживания транзакционный, вы можете получить исключение отложенной инициализации. Транзакция будет закрыта, когда сервисный метод завершит свое выполнение. Итак, вы отсоединили объекты на стороне контроллера. Это не проблема Грааля.

На доменном домене класса


static mapping = {
    furniture lazy:false
}

Это обеспечит, что всякий раз, когда вы запрашиваете дом, он приходит с его мебелью

Или вы можете установить режим выборки для конкретного запроса


def house = criteria.list{
    ...
    fetchMode('furniture', FetchMode.EAGER)
}

...