Используются ли кастомные запросы в Spring Data и JPA
Что проверяют
Знаете ли вы, что у Spring Data JPA несколько уровней запросов, и умеете ли выбрать подходящий, а не писать @Query на всё подряд. Следом обычно спрашивают про @Modifying, пагинацию в нативном запросе или динамические фильтры.
Как отвечать
Ответ «да, используются» слишком короткий. Покажите лестницу от простого к сложному:
- derived queries: запрос строится из имени метода,
findByEmailAndStatus. Хорош для двух-трёх условий, дальше имя становится нечитаемым; @Queryс JPQL: запрос по сущностям, а не по таблицам, синтаксис проверяется при старте контекста. Параметры через:nameи@Param(аннотацию можно опустить, если код собран с флагом-parameters);nativeQuery = true: когда нужны возможности конкретной СУБД, оконные функции,jsonb, CTE. Для возвратаPageпридётся задатьcountQuery;@Modifying: дляUPDATEиDELETE, обязательно внутри транзакции. ПараметрclearAutomatically = trueочищает контекст персистентности, иначе в нём остаются устаревшие сущности;- проекции: интерфейс или DTO через
select new ...вместо полной сущности, когда нужны три поля из двадцати; - Specification и Criteria API: динамические фильтры, где набор условий зависит от запроса пользователя. Альтернатива им Querydsl;
- фрагменты репозитория: свой интерфейс плюс класс с суффиксом
Impl, внутриEntityManager. Для логики, которую аннотацией не выразить.
Закончите тем, как проверяете результат: логирование SQL, @EntityGraph или join fetch против N+1, тест на @DataJpaTest с Testcontainers.
Где спотыкаются
Собирают нативный запрос конкатенацией строк с пользовательским вводом. Это SQL-инъекция, значения передаются только через параметры.
Пишут @Modifying без @Transactional и получают исключение, либо после массового UPDATE читают из того же контекста старые значения и не понимают почему.
Делают join fetch коллекции вместе с пагинацией. Hibernate предупреждает и режет страницу в памяти, выгрузив все строки, и на большой таблице это медленно.