N+1 запрос через lazy-loading — почему тест на 3 записях его не покажет
Вопрос проверяет понимание жизненного цикла сессии Hibernate: коллекция с FetchType.LAZY выполняет отдельный SELECT при первом обращении к ней, а не при загрузке родительской сущности.
На 3 заказах в тесте это будет 4 запроса вместо одного — незаметно и в логах, и на глаз. На проде с 10000 заказов это уже 10001 запрос, и время ответа эндпоинта улетает в секунды.
Классика внутри цикла:
List orders = orderRepository.findAll();
for (Order order : orders) { // отдельный SELECT int count = order.getItems().size(); }
Ловушка: поставить FetchType.EAGER не решает проблему, а переносит N+1 на JOIN с картезианским произведением при нескольких коллекциях. Правильный ответ — JOIN FETCH в JPQL или @EntityGraph под конкретный сценарий использования.
N+1 не виден в одном запросе — он виден в количестве запросов за реквест, и это смотрят в APM, а не в SQL-логе одной строки.
Тренажёр: 600 вопросов, мок с таймером, план повторов
senior·base — что спрашивают на самом деле
В этом посте были ссылки, но мы их удалили по правилам Сетки