Сколько запросов к БД генерирует Hibernate при выборке сущностей со связью @ManyToOne или @OneToMany?

«Сколько запросов к БД генерирует Hibernate при выборке сущностей со связью @ManyToOne или @OneToMany?» — вопрос из категории Базы данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

При ленивой загрузке (FetchType.LAZY) по умолчанию возникает проблема N+1 запроса:

  1. 1 запрос для получения основной коллекции сущностей (например, Order).
  2. N запросов для загрузки связанных сущностей (например, Customer для каждого заказа), если к ним обратиться.

Пример проблемы:

@Entity
class Order {
    @ManyToOne(fetch = FetchType.LAZY)
    private Customer customer;
}
// HQL-запрос, вызывающий N+1
List<Order> orders = session.createQuery("FROM Order", Order.class).list();
for (Order o : orders) {
    System.out.println(o.getCustomer().getName()); // Триггер для N запросов
}

Решения для объединения в 1-2 запроса:

  • JOIN FETCH в HQL/JPQL: SELECT o FROM Order o JOIN FETCH o.customer
  • EntityGraph в Spring Data JPA: Аннотация @EntityGraph(attributePaths = {"customer"}) над методом репозитория.
  • Пакетная загрузка (Batch Fetching): Аннотация @BatchSize(size = 10) на поле или класс сущности. Hibernate загружает связанные сущности группами.