HQL: получение объединяемых коллекций из Eager Table - PullRequest
7 голосов
/ 19 августа 2010

У меня есть четыре таблицы:

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.

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

Ответы [ 2 ]

11 голосов
/ 19 августа 2010

Здесь идет ссылка на Hibernate

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

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

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

Вы можете либо

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

или включить коллекцию SubNodeChildren как fetch = FetchType.EAGER

Следующее было извлечено из Hibernate FAQ (ссылка была отключена (насколько я знаю), но я сохранилперед исчезновением)

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

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

...

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

1 голос
/ 19 августа 2010

Чтобы запрос работал, мне нужно было сделать 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, но он определенно работает именно так, как мне нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...