Перейти к основному содержимому

Производные методы запросов в репозиториях Spring Data JPA

· 6 мин. чтения

Задача: Наибольшая подстрока без повторений

Для заданной строки s, найдите длину наибольшей подстроки без повторяющихся символов. Подстрока — это непрерывная непустая последовательность символов внутри строки...

ANDROMEDA 42

1. Обзор

Для простых запросов легко определить, каким должен быть запрос, просто взглянув на соответствующее имя метода в нашем коде.

В этом руководстве мы рассмотрим, как Spring Data JPA использует эту идею в форме соглашения об именах методов.

2. Структура производных методов запросов в Spring

Имена производных методов состоят из двух основных частей, разделенных первым ключевым словом By :

List<User> findByName(String name)

Первая часть, такая как find , является вводным , а остальные, такие как ByName , являются критериями .

Spring Data JPA поддерживает поиск , чтение , запрос , подсчет и получение . Итак, мы могли бы сделать queryByName , и Spring Data вел бы себя так же.

Мы также можем использовать Distinct , First или Top , чтобы удалить дубликаты или ограничить наш набор результатов :

List<User> findTop3ByAge()

Часть критериев содержит специфические для сущности выражения условий запроса. Мы можем использовать ключевые слова условия вместе с именами свойств объекта.

Мы также можем объединить выражения с помощью And и Or , как мы сейчас увидим.

3. Образец заявления

Во-первых, нам, конечно же, понадобится приложение, использующее Spring Data JPA .

В этом приложении давайте определим класс сущности:

@Table(name = "users")
@Entity
class User {
@Id
@GeneratedValue
private Integer id;

private String name;
private Integer age;
private ZonedDateTime birthDate;
private Boolean active;

// standard getters and setters
}

Давайте также определим репозиторий.

Он расширит JpaRepository , один из типов Spring Data Repository :

interface UserRepository extends JpaRepository<User, Integer> {}

Здесь мы разместим все наши производные методы запроса.

4. Ключевые слова условия равенства

Точное равенство — одно из наиболее часто используемых условий в запросах. У нас есть несколько вариантов выражения операторов = или IS в запросе.

Мы можем просто добавить имя свойства без ключевого слова для условия точного совпадения:

List<User> findByName(String name);

И мы можем добавить Is или Equals для удобства чтения:

List<User> findByNameIs(String name);
List<User> findByNameEquals(String name);

Эта дополнительная читабельность пригодится, когда нам нужно вместо этого выразить неравенство:

List<User> findByNameIsNot(String name);

Это немного более читабельно, чем findByNameNot(String) !

Поскольку равенство null — это особый случай, мы не должны использовать оператор =. Spring Data JPA по умолчанию обрабатывает нулевые параметры . Итак, когда мы передаем нулевое значение для условия равенства, Spring интерпретирует запрос как IS NULL в сгенерированном SQL.

Мы также можем использовать ключевое слово IsNull , чтобы добавить в запрос критерий IS NULL:

List<User> findByNameIsNull();
List<User> findByNameIsNotNull();

Обратите внимание, что ни IsNull , ни IsNotNull не требуют аргумента метода.

Также есть еще два ключевых слова, которые не требуют аргументов.

Мы можем использовать ключевые слова True и False , чтобы добавить условия равенства для логических типов:

List<User> findByActiveTrue();
List<User> findByActiveFalse();

Конечно, иногда нам хочется чего-то более снисходительного, чем точное равенство, так что давайте посмотрим, что еще мы можем сделать.

5. Ключевые слова условия подобия

Когда нам нужно запросить результаты с шаблоном свойства, у нас есть несколько вариантов.

Мы можем найти имена, начинающиеся со значения, используя StartingWith :

List<User> findByNameStartingWith(String prefix);

Грубо говоря, это переводится как «ГДЕ имя НРАВИТСЯ «значение%» ».

Если нам нужны имена, которые заканчиваются значением, нам нужен EndingWith :

List<User> findByNameEndingWith(String suffix);

Или мы можем найти, какие имена содержат значение с помощью Containing :

List<User> findByNameContaining(String infix);

Обратите внимание, что все приведенные выше условия называются предопределенными шаблонными выражениями. Таким образом, нам не нужно добавлять оператор % внутри аргумента при вызове этих методов.

Но давайте предположим, что мы делаем что-то более сложное. Скажем, нам нужно получить пользователей, чьи имена начинаются с a , содержат b и заканчиваются на c .

Для этого мы можем добавить наш собственный LIKE с ключевым словом Like :

List<User> findByNameLike(String likePattern);

И затем мы можем передать наш шаблон LIKE при вызове метода:

String likePattern = "a%b%c";
userRepository.findByNameLike(likePattern);

На сегодня хватит об именах. Давайте попробуем другие значения в User .

6. Ключевые слова условия сравнения

Кроме того, мы можем использовать ключевые слова LessThan и LessThanEqual для сравнения записей с заданным значением с помощью операторов < и <= :

List<User> findByAgeLessThan(Integer age);
List<User> findByAgeLessThanEqual(Integer age);

В противоположной ситуации мы можем использовать ключевые слова GreaterThan и GreaterThanEqual :

List<User> findByAgeGreaterThan(Integer age);
List<User> findByAgeGreaterThanEqual(Integer age);

Или мы можем найти пользователей в возрасте между двумя возрастами с помощью Between :

List<User> findByAgeBetween(Integer startAge, Integer endAge);

Мы также можем предоставить набор возрастов для сопоставления с использованием In :

List<User> findByAgeIn(Collection<Integer> ages);

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

Для этого мы использовали бы « До» и « После »:

List<User> findByBirthDateAfter(ZonedDateTime birthDate);
List<User> findByBirthDateBefore(ZonedDateTime birthDate);

7. Несколько выражений условий

Мы можем комбинировать столько выражений, сколько нам нужно, используя ключевые слова And и Or :

List<User> findByNameOrBirthDate(String name, ZonedDateTime birthDate);
List<User> findByNameOrBirthDateAndActive(String name, ZonedDateTime birthDate, Boolean active);

Порядок приоритета - And then Or , как в Java.

Хотя Spring Data JPA не накладывает ограничений на количество добавляемых выражений, здесь не следует сходить с ума. Длинные имена нечитаемы и их трудно поддерживать. Вместо сложных запросов взгляните на аннотацию @Query .

8. Сортировка результатов

Далее займемся сортировкой.

Мы могли бы попросить, чтобы пользователи были отсортированы в алфавитном порядке по имени с помощью OrderBy :

List<User> findByNameOrderByName(String name);
List<User> findByNameOrderByNameAsc(String name);

Восходящий порядок — это параметр сортировки по умолчанию, но вместо этого мы можем использовать Desc , чтобы отсортировать их в обратном порядке:

List<User> findByNameOrderByNameDesc(String name);

9. findOne против findById в CrudRepository

Команда Spring внесла несколько серьезных изменений в CrudRepository с помощью Spring Boot 2.x. Один из них — переименование findOne в findById .

Ранее в Spring Boot 1.x мы вызывали findOne , когда хотели получить объект по его первичному ключу:

User user = userRepository.findOne(1);

Начиная с Spring Boot 2.x, мы можем сделать то же самое с findById :

User user = userRepository.findById(1);

Обратите внимание, что метод findById() уже определен для нас в CrudRepository . Таким образом, нам не нужно явно определять его в пользовательских репозиториях, расширяющих CrudRepository .

10. Заключение

В этой статье мы объяснили механизм вывода запросов в Spring Data JPA. Мы использовали ключевые слова условия свойства для написания производных методов запроса в репозиториях Spring Data JPA.

Исходный код этой статьи доступен в проекте GitHub .