Получить доступ

Список из 100 заказов рендерится вместе с покупателем каждого, и в логе видно 101 SQL-запрос. Какие способы исправят проблему?

MiddleSpring Data JPA и HibernateHibernate / JPASpring Data
Ещё спрашивают так:
  • Как исправить N+1 в Spring Data JPA?
Коротко

JOIN FETCH в @Query, @EntityGraph на методе репозитория или пакетная загрузка (hibernate.default_batch_fetch_size). EAGER не решает — делает проблему постоянной.

  • DTO-проекция — выбрать только нужное одним запросом
  • JOIN FETCH коллекции с пагинацией — Hibernate пагинирует в памяти
  • Обнаруживать — лог SQL и проверка числа запросов в тестах

А ещё @EntityGraph(attributePaths = "customer") — без изменения запроса

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

N+1 возникает потому, что ленивая связь подгружается отдельным запросом на каждую строку. Замена на EAGER — самый частый неверный ответ: количество запросов остаётся тем же, просто они выполняются всегда, включая случаи, когда связь не нужна, и проблема расползается по всему приложению. JOIN FETCH и @EntityGraph решают задачу точечно, в конкретном сценарии, где данные действительно нужны. Пакетная загрузка помогает, когда переписать запрос нельзя. Отдельно стоит помнить про подводный камень JOIN FETCH с несколькими коллекциями: возникает декартово произведение, поэтому больше одной коллекции так не тянут, а используют пакетную загрузку или отдельные запросы. И самый радикальный вариант для чтения — сразу проецировать в DTO.

Что хотят услышать

  • Несколько способов исправления.
  • Почему EAGER не решение.
  • Ловушка пагинации.

Частые ошибки

  • Лечить N+1 переводом связей в EAGER.
  • Делать JOIN FETCH сразу по двум коллекциям.

Проверьте себя

Несколько верных вариантов. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✓JOIN FETCH в @Query — связанные сущности загружаются одним запросом
  • ✓@EntityGraph на методе репозитория
  • ✓Пакетная загрузка через @BatchSize или default_batch_fetch_size — вместо 100 запросов будет несколько
  • ✗Смена типа связи на EAGER

Что спросят дальше

  • Почему JOIN FETCH двух коллекций даёт декартово произведение?
  • Чем проекция в DTO выгоднее загрузки сущностей?

Разбор темы

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем