Какие методы используются для поиска данных в Spring Data JPA Repository?

Ответ

Spring Data JPA предоставляет несколько механизмов для поиска, от простых до сложных:

  1. Стандартные CRUD-методы: findById(ID id), findAll(), existsById(ID id).

  2. Query Methods (методы по соглашению): Создайте метод в интерфейсе репозитория, и Spring сгенерирует запрос JPQL на основе его имени.

    public interface UserRepository extends JpaRepository<User, Long> {
        // Простой поиск по полю
        List<User> findByLastName(String lastName);
        // Поиск с условиями
        List<User> findByAgeGreaterThan(int age);
        List<User> findByEmailAndActiveTrue(String email);
        // Сортировка и пагинация
        Page<User> findByLastName(String lastName, Pageable pageable);
    }
  3. Аннотация @Query для кастомных JPQL или SQL запросов:

    @Query("SELECT u FROM User u WHERE u.email = :email")
    User findUserByEmail(@Param("email") String email);
    
    @Query(value = "SELECT * FROM users WHERE active = 1", nativeQuery = true)
    List<User> findAllActiveUsersNative();
  4. Specification API и JpaSpecificationExecutor: Для построения динамических, типобезопасных запросов на уровне бизнес-логики.

    public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {}
    // Использование в сервисе:
    List<User> users = userRepository.findAll(
        Specification.where(hasName("John").and(isActive()))
    );

Рекомендация по выбору: Используйте Query Methods для простых запросов, @Query для сложных или оптимизированных, а Specification API — для динамических фильтров.

Ответ 18+ 🔞

Так, слушай, вот эта твоя Spring Data JPA, она же, блядь, как шведский стол — всего навалом, только выбирай. Но если бездумно хватать, можно и обосраться, честно. Вот смотри, как тут всё устроено, по полочкам.

Во-первых, самое простое, что даже дурак не проебёт. Это стандартные штуки из коробки: найти по айдишнику (findById), достать всех (findAll), проверить, есть ли такая сущность вообще (existsById). Это как хлеб с маслом, базис, хуле.

А вот дальше начинается магия, или, как я это называю, «ленивое колдунство». Query Methods. Ты просто пишешь в интерфейсе репозитория метод с правильным именем, а Spring, сука, сам догадывается, какой тебе JPQL-запрос сгенерить. Просто пиздец!

public interface UserRepository extends JpaRepository<User, Long> {
    // Найдём всех по фамилии — логично же?
    List<User> findByLastName(String lastName);
    // А тут всех, кто старше какого-то возраста. Бабки, блядь!
    List<User> findByAgeGreaterThan(int age);
    // Имейл конкретный И чтоб активный был. Два условия — не хуй собачий.
    List<User> findByEmailAndActiveTrue(String email);
    // А это уже с пагинацией, чтоб не грузить всё разом, как говно в унитаз.
    Page<User> findByLastName(String lastName, Pageable pageable);
}

Чувствуешь? Ни одной аннотации, нихуя! Просто называешь метод — и он работает. Но если тебе кажется, что это слишком просто и хочется своей, особенной, ебаной логики запроса...

Тогда тебе в помощь @Query. Тут ты уже сам бог и царь. Хочешь JPQL, хочешь нативный SQL — только скажи.

@Query("SELECT u FROM User u WHERE u.email = :email")
User findUserByEmail(@Param("email") String email);

// А это когда JPQL уже не канает и надо рубить с плеча нативным SQL
@Query(value = "SELECT * FROM users WHERE active = 1", nativeQuery = true)
List<User> findAllActiveUsersNative();

Но бывает, блядь, такая ситуация: фильтры приходят с фронта, их дохуя, и они все опциональные. Писать кучу if и склеивать строки запроса — это же пиздец, прости господи. На это есть Specification API.

Подключаешь к репозиторию волшебный интерфейс JpaSpecificationExecutor:

public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {}

А потом в сервисе строишь эти спецификации, как из кубиков Лего:

// Где-то там у тебя методы, которые возвращают Specification<User>
List<User> users = userRepository.findAll(
    Specification.where(hasName("John").and(isActive())) // Примерно так
);

Это для сложных, динамических фильтров, где на лету надо условия добавлять или убирать. Мощная хуйня, но и сложнее.

Так какую же хуйню выбрать, спросишь ты? А я тебе скажу:

  • Query Methods — для всего простого, очевидного. Не еби мозг.
  • @Query — когда твой запрос слишком хитрожопый для соглашений или тебе надо выжать максимум производительности (особенно с nativeQuery).
  • Specification API — это когда у тебя на сайте фильтры, как у маркетплейса: «показать только красные, но не китайские, с рейтингом выше 4.5, но чтоб со скидкой». Вот тут оно.

Вот и вся философия. Не усложняй, где не надо, а где надо — используй тяжёлую артиллерию.