Какие способы написания кастомных запросов в Spring Data JPA существуют?

«Какие способы написания кастомных запросов в Spring Data JPA существуют?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Spring Data JPA предоставляет несколько основных способов для создания пользовательских запросов.

1. Query Creation (Соглашения об именовании методов) Репозиторий автоматически строит запрос на основе имени метода. Подходит для простых условий.

List<User> findByLastNameAndActiveTrue(String lastName);
Page<User> findByEmailContaining(String email, Pageable pageable);

2. Аннотация @Query (JPQL или нативный SQL) Наиболее гибкий и часто используемый способ для сложных запросов.

// JPQL-запрос (работает с сущностями)
@Query("SELECT u FROM User u WHERE u.email = :email AND u.active = true")
Optional<User> findActiveUserByEmail(@Param("email") String email);

// Нативный SQL-запрос (работает с таблицами)
@Query(value = "SELECT * FROM users WHERE created_at > :date", nativeQuery = true)
List<User> findUsersCreatedAfter(@Param("date") LocalDateTime date);

3. Кастомные репозитории (Custom Repository Implementation) Позволяет инкапсулировать сложную логику запросов, используя EntityManager или JdbcTemplate.

// 1. Объявляем кастомный интерфейс
public interface UserRepositoryCustom {
    List<User> findUsersByComplexBusinessRule();
}

// 2. Реализуем его. Имя класса должно быть {ИмяОсновногоРепозитория}Impl
public class UserRepositoryImpl implements UserRepositoryCustom {
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public List<User> findUsersByComplexBusinessRule() {
        // Реализация с использованием Criteria API, QueryDSL или нативного SQL
        return ...;
    }
}

// 3. Основной репозиторий расширяет и JpaRepository, и кастомный интерфейс
public interface UserRepository extends JpaRepository<User, Long>, UserRepositoryCustom {}

Рекомендации по выбору:

  • Query Creation: Для простых, декларативных запросов.
  • @Query (JPQL): Для большинства сложных запросов, связанных с сущностями. Безопаснее и переносимее нативного SQL.
  • @Query (native): Когда необходим специфичный синтаксис СУБД или сложные SQL-оптимизации.
  • Кастомная реализация: Для максимальной гибкости, когда запрос невозможно выразить через JPQL или требуется работа с низкоуровневыми API.