2009-07-01 3 views
7

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

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

Каковы способы/лучший способ погрузки этой коллекции?

  • Предположим, что сеанс в представлении не является вариантом, так как выборка коллекции «Дети» произойдет только после того, как пользователь просмотрит родителя и решил посмотреть на «Дети».
  • Это сервис, к которому будет удален доступ через веб-клиент и настольный клиент.

Спасибо.

ответ

3

Я делаю некоторые предположения о том, что пользователь смотрит, но кажется, что вы хотите только получить детей, если пользователь уже просмотрел родителя и действительно хочет видеть детей.

Почему бы не попробовать открыть новую сессию и получить детей от их родителей? Что-то вдоль линий ...

criteria = session.createCriteria(Child.class); 
criteria.add(Restrictions.eq("parent", parent)); 
List<Child> children = criteria.list(); 
+0

приятный. Я пропустил, что вы можете указать объекты в Ограничении. –

+1

Что делать, если поле «parent» является коллекцией? – Damian

7

Ленивый коллекция может быть загружен с помощью Hibernate.initialize (parent.getCollection()), за исключением, что родительский объект должен быть присоединен к активной сессии.

Это решение принимает родительское Entity и имя ленивого поля и возвращает Entity с полной загрузкой коллекции.

К сожалению, поскольку родитель должен быть привязан к вновь открытому сеансу, я не могу использовать ссылку на ленивую коллекцию, так как это будет ссылаться на отдельную версию Entity; следовательно, поле Name и отражение. По той же причине это должно вернуть прикрепленное родительское Entity.

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

Parent parentWithChildren = dao.initialize(parent,"lazyCollectionName"); 

Метод:

public Entity initialize(Entity detachedParent,String fieldName) { 
    // ...open a hibernate session... 
    // reattaches parent to session 
    Entity reattachedParent = (Entity) session.merge(detachedParent); 

    // get the field from the entity and initialize it 
    Field fieldToInitialize = detachedParent.getClass().getDeclaredField(fieldName); 
    fieldToInitialize.setAccessible(true); 
    Object objectToInitialize = fieldToInitialize.get(reattachedParent); 

    Hibernate.initialize(objectToInitialize); 
    return reattachedParent; 
} 
0

Hibernate обрабатывает коллекции в других таким образом, что нормальные поля.

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

public Parent loadParentWithIntent1(Long parentId) 
{ 
    Parent parent = loadParentFromDAO(); 

    for (Child c : parent.getChildren()) 
    { 
    c.getField1(); 
    } 
} 

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

+1

Я использую эту сторону n + 1 запросов. –