#java #database #hibernate #orm #jpa
#java #База данных #спящий режим #orm #jpa
Вопрос:
Я использую довольно старую версию Hibernate (3.2.4), так что, возможно, это связано с этим. К сожалению, требования проекта не позволяют мне выполнить обновление.
У меня есть класс Foo с ассоциацией «многие к одному» для Bar. Связь помечена:
lazy="false" fetch="join"
Теперь, когда я делаю что-то вроде:
em.find(Foo.class, id);
Я получаю ожидаемый результат: единственный оператор, соединяющий таблицу FOO с таблицей BAR. Однако, когда я пытаюсь что-то вроде:
em.createQuery("select f from Foo where f.id = :id")
.setParameter("id", id)
.getSingleResult();
Я получаю единственное соединение, за которым следует дополнительный запрос select к BAR. Второй запрос кажется совершенно излишним; все данные, необходимые для быстрого заполнения экземпляра Foo, должны были быть доступны при первоначальном соединении. Это выглядит примерно так:
select f.id, f.xyz, ..., b.id, b.xyz, ...
from foo f
join bar b on b.id = f.bar_id
where f.id = ?
select b.id, b.xyz, ...
from bar b
where b.id = ?
Есть мысли?
Ответ №1:
Режим гибернации не соблюдается fetch = "join"
при выполнении запросов HQL. Из документации:
Стратегия выборки, определенная в документе сопоставления, влияет:
- извлечение с помощью get () или load()
- извлечение, которое происходит неявно при переходе по ассоциации
- Запросы критериев
- Запросы HQL, если используется выборка по дополнительному выбору
В случае запросов HQL вам придется использовать left join fetch
:
em.createQuery("select f from Foo f left join fetch f.bar where f.id = :id")
.setParameter("id", id)
.getSingleResult();
Комментарии:
1. Да, я понял это постфактум. Есть ли способ в HQL / JPA-QL указать «join fetch all associations», чтобы мне не приходилось их перечислять? Кажется, что Hibernate поддерживает это с помощью запросов критериев (setFetchMode), но я ограничен интерфейсом JPA.
2. @user190758: Я думаю, что нет, поскольку Hibernate обладает гораздо большей свободой при построении запросов критериев, чем при переводе запросов HQL.
3. Чувак, это отстой. Знаете, возможно ли «преобразовать» запрос HQL в экземпляр criteria, для которого я мог бы программно вызвать setFetchMode()? Или, возможно, подсказка, которую я мог бы перевести в спящий режим с помощью метода JPA setHint ()?