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 .