2010-08-18 3 views
7

У меня есть четыре таблицы:HQL: Fetch Регистрация Коллекции из Eager таблицы

RootNode // Will return multiple root nodes 
SubNode // Will return one sub node per root node 
SubNodeChildren1 // Will return multiple for each sub node 
SubNodeChildren2 // Will return multiple for each sub node 

и аналогичную структуру лица:

RootNode -> SubNode -> SubNodeChildren1 
        -> SubNodeChildren2 

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

Я знаю, как написать запрос, который будет LEFT OUTER JOIN FETCH непосредственными дочерними элементами таблицы и инициализировать их соответственно. Тем не менее, я не знаю, как захватить детей таблицы, которая с нетерпением вывешена из таблицы верхнего уровня.

Я пытался что-то вроде:

SELECT rn FROM RootNode AS rn LEFT OUTER JOIN FETCH rn.SubNode.SubNodeChildren1 

но, это всегда дает мне ошибку, что владелец не является частью SELECT.

Любая помощь очень ценится.

ответ

11

Здесь идет гибернации, присвоенный

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

что предполагает ваш запрос должен быть переписана в виде

select distinct 
    rn 
from 
    RootNode rn 
left join fetch 
    rn.subNode sn 
left join fetch 
    sn.subNodeChildren 

Вы можете

отключить default subNode fetch = FetchType.EAGER и просто получить то, что вы действительно хотите, используя запрос HQL - эффективно (HQL-запрос) переопределяет внешнее объединение и ленивые объявления файла сопоставления для ассоциаций и коллекций (справочная документация Hibernate). Этот подход поддерживается POJO в книге действий.

или включить сбор SubNodeChildren как выборки = FetchType.EAGER

извлечена из гибернации FAQ (Ссылка отключена (Насколько я знаю), но я спас, прежде чем исчезнуть)

следующие

В приложении MVC, как мы можем гарантировать, что все прокси и ленивые коллекции будут инициализированы, когда представление попытается получить к ним доступ?

Один из возможных подходов заключается в том, чтобы оставить сессию открытой (и транзакцией без фиксации) при пересылке в представление. Сессия/транзакция будет закрыта/зафиксирована после визуализации представления, например, фильтра сервлетов (другим примером будет использование обратного вызова ModelLifetime.discard() в Maverick). Одна из трудностей с этим подходом заключается в том, что сеанс/транзакция закрывается/откатывается, если возникает исключение, отображающее представление.

...

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

+0

+1 Интересно, почему [вложенные попытки присоединения] (http://en.wikibooks.org/wiki/Java_Persistence/Relationships#Nested_Joins) не разрешены в JPA. –

1

Для того, чтобы получить работу запроса, я должен был сделать INNER JOIN FETCH вместо LEFT OUTER JOIN FETCH на нетерпеливое лице:

SELECT rn FROM RootNode AS rn INNER JOIN FETCH rn.SubNode AS sn LEFT OUTER JOIN FETCH sn.SubNodeChildren1 LEFT OUTER JOIN FETCH sn.SubNodeChildren2 ... 

Чтобы быть честным, я до сих пор точно не знаю, почему это работает с INNER JOIN FETCH против LEFT OUTER JOIN FETCH, но он определенно работает именно так, как мне нужно.

+0

Ok (+1) Просто для любопытства: возможно ли, что вы покажете свой фрагмент кода между ** sessionFactory.openSession() и session.close() ** ??? И ваше аннотированное сопоставление ??? –

+0

Ничего себе, это неловко ... Ваш первоначальный ответ был верным. Фрагмент кода, 'LEFT OUTER JOIN FETCH rn.SubNode AS sn', был тем, который мне нужен, чтобы мои сущности работали правильно. (Вся эта путаница была связана с проблемой с моей тестовой средой) –

Смежные вопросы