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

Существующий запрос в данных Spring

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

1. Введение

Во многих приложениях, ориентированных на данные, могут возникнуть ситуации, когда нам нужно проверить, существует ли уже конкретный объект.

В этом руководстве мы обсудим несколько способов добиться именно этого с помощью Spring Data и JPA.

2. Образец объекта

Чтобы подготовить почву для наших примеров, давайте создадим объект Car с двумя свойствами: model и power :

@Entity
public class Car {

@Id
@GeneratedValue
private int id;

private Integer power;
private String model;

// getters, setters, ...
}

3. Поиск по ID

Интерфейс JpaRepository предоставляет метод existsById , который проверяет, существует ли сущность с заданным идентификатором в базе данных:

int searchId = 2; // ID of the Car
boolean exists = repository.existsById(searchId)

Предположим, что searchId — это идентификатор автомобиля , который мы создали во время настройки теста. Ради воспроизводимости теста мы никогда не должны использовать жестко запрограммированное число (например, «2»), потому что свойство id автомобиля , скорее всего, генерируется автоматически и может меняться со временем. Запрос existsById — самый простой, но наименее гибкий способ проверки существования объекта `` .

4. Использование производного метода запроса

Мы также можем использовать функцию производного метода запроса Spring для формулировки нашего запроса. В нашем примере мы хотим проверить, существует ли автомобиль с данным названием модели, поэтому мы разрабатываем следующий метод запроса:

boolean existsCarByModel(String model);

Важно отметить, что название метода не произвольное — оно должно соответствовать определенным правилам . Затем Spring сгенерирует прокси для репозитория, чтобы он мог получить SQL-запрос из имени метода. Современные IDE, такие как IntelliJ IDEA, обеспечивают завершение синтаксиса для этого.

Когда запросы становятся более сложными — например, за счет включения упорядочения, ограничения результатов и нескольких критериев запроса — эти имена методов могут стать довольно длинными, вплоть до неразборчивости . Кроме того, производные методы запросов могут показаться волшебными из-за их неявной и «условной» природы.

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

5. Поиск по примеру

Пример — это очень мощный способ проверки существования, поскольку он использует средства сопоставления примеров для динамического построения запроса. Итак, всякий раз, когда нам требуется динамичность, это хороший способ сделать это. Подробное объяснение Spring ExampleMatcher и того, как их использовать, можно найти в нашей статье Spring Data Query . ``

5.1. Сопоставитель

Предположим, что мы хотим искать имена моделей без учета регистра. Начнем с создания нашего ExampleMatcher :

ExampleMatcher modelMatcher = ExampleMatcher.matching()
.withIgnorePaths("id")
.withMatcher("model", ignoreCase());

Обратите внимание, что мы должны явно игнорировать путь id, потому что id является первичным ключом, и по умолчанию они подбираются автоматически.

5.2. Зонд

Затем нам нужно определить так называемый «зонд», который является экземпляром класса, который мы хотим найти. В нем установлены все необходимые для поиска свойства. Затем мы подключаем его к нашему nameMatcher и выполняем запрос:

Car probe = new Car();
probe.setModel("bmw");
Example<Car> example = Example.of(probe, modelMatcher);
boolean exists = repository.exists(example);

С большой гибкостью приходит большая сложность, и каким бы мощным ни был API ExampleMatcher , его использование приведет к созданию нескольких строк дополнительного кода. Мы предлагаем использовать это в динамических запросах или если никакой другой метод не подходит .

6. Написание пользовательского запроса JPQL с существующей семантикой

Последний метод, который мы рассмотрим, использует JPQL (Java Persistence Query Language) для реализации пользовательского запроса с существующей семантикой :

@Query("select case when count(c)> 0 then true else false end from Car c where lower(c.model) like lower(:model)")
boolean existsCarLikeCustomQuery(@Param("model") String model);

Идея состоит в том, чтобы выполнить запрос счетчика без учета регистра на основе свойства модели , оценить возвращаемое значение и сопоставить результат с логическим значением Java . Опять же, большинство IDE довольно хорошо поддерживают операторы JPQL.

Пользовательские запросы JPQL можно рассматривать как альтернативу производным методам, и часто они являются хорошим выбором, когда нам удобно работать с операторами, подобными SQL, и не возражать против дополнительных аннотаций @Query .

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

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

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

Полный пример исходного кода можно найти на GitHub .