HQL: Получение коллекций соединения из нетерпеливой таблицы

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

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

Мне нужен один запрос, который вернет все корневые узлы в таблице с инициализированными дочерними подузлами и подузлами . Подузел извлекается быстро, но дочерние узлы Подузел выбираются лениво.

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

Я пробовал что-то вроде:

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

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

Любая помощь приветствуется.

7
задан Stephen Watkins 18 August 2010 в 21:37
поделиться

2 ответа

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

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

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

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

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

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

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

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

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

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

...

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

12
ответ дан 6 December 2019 в 19:30
поделиться

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

1
ответ дан 6 December 2019 в 19:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: