Ответ
JOIN FETCH в JPQL/HQL заставляет Hibernate загружать связанную коллекцию или сущность немедленно (eagerly) в рамках одного SQL-запроса, игнорируя объявленную стратегию FetchType.LAZY.
Цель: Решение проблемы N+1 запроса.
Пример:
@Entity
public class Order {
@Id
private Long id;
@OneToMany(mappedBy = "order", fetch = FetchType.LAZY) // Объявлена LAZY
private List<OrderItem> items;
}
// Запрос с JOIN FETCH
String jpql = "SELECT o FROM Order o JOIN FETCH o.items WHERE o.id = :id";
Order order = entityManager.createQuery(jpql, Order.class)
.setParameter("id", orderId)
.getSingleResult();
// Коллекция `items` уже загружена и доступна вне сессии
Важные ограничения:
- Пагинация: Использование
JOIN FETCHсsetFirstResult()/setMaxResults()приведет кQueryException, так как JOIN изменяет результирующий набор строк. Для пагинации связанных коллекций используйте отдельный запрос или@BatchSize. - Несколько коллекций:
JOIN FETCHболее чем одной коллекции в одном запросе может привести к декартову произведению (Cartesian Product). В таких случаях предпочтительнее использовать несколько запросов. - Повторяющиеся сущности: Hibernate устраняет дубликаты корневых сущностей в результате, но это может повлиять на производительность.