Что такое join fetch в Hibernate?
Что проверяют
Знаете ли вы, как бороться с N+1, и понимаете ли цену решения. JOIN FETCH называют почти все, поэтому интервьюер сразу идёт дальше: что будет с пагинацией, можно ли так загрузить две коллекции и чем это отличается от @EntityGraph и @BatchSize.
Как отвечать
JOIN FETCH в JPQL и HQL велит Hibernate не просто соединить таблицы, а инициализировать ассоциацию тем же SQL-запросом. Связь, объявленная LAZY, приходит уже загруженной, и обращение к author.getBooks() не порождает отдельный SELECT на каждого автора.
@Query("select a from Author a left join fetch a.books where a.country = :c")
List<Author> findWithBooks(@Param("c") String country);Что проговорить:
join fetchпротивjoin: обычныйjoinнужен для фильтрации, коллекция остаётся ленивой, и N+1 никуда не девается;leftили внутренний:join fetchбезleftвыкинет авторов без книг;- дубли: SQL возвращает строку на каждую книгу. До Hibernate 6 писали
select distinct, с шестой версии корневые сущности дедуплицируются сами; - альтернативы:
@EntityGraph(attributePaths = "books")в Spring Data JPA делает то же без переписывания запроса, а@BatchSizeилиhibernate.default_batch_fetch_sizeпревращают N+1 в пару запросов сIN (...)там, где fetch join неудобен.
Покажите и стратегию: @ManyToOne в JPA по умолчанию EAGER, его обычно явно переводят в LAZY, а нужные связи подтягивают fetch join только в тех запросах, где они используются.
Где спотыкаются
Сочетают fetch join коллекции с пагинацией. Hibernate не может применить LIMIT к размноженным строкам, выгружает всё и режет страницу в памяти с предупреждением HHH90003004. Правильно сначала выбрать страницу идентификаторов, потом сущности с коллекциями по id in (...).
Загружают две коллекции-List одним запросом и получают MultipleBagFetchException. Замена на Set убирает исключение, но оставляет декартово произведение: у автора 100 книг и 50 отзывов, в ответе 5000 строк.
Фильтруют по алиасу fetch-коллекции в where. В сущность попадёт урезанная коллекция и так и останется в контексте персистентности, будто это все книги автора.