«1. Обзор

В этой статье мы покажем способы обработки нулевых параметров в Spring Data JPA.

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

Ниже мы покажем, как реализовать каждый из них.

2. Быстрый пример

Допустим, у нас есть объект Customer:

@Entity
public class Customer {

    @Id
    @GeneratedValue
    private long id;
    private String name;
    private String email;

    public Customer(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // getters/setters

}

Кроме того, у нас есть репозиторий JPA:

public interface CustomerRepository extends JpaRepository<Customer, Long> { 

   // method1
   // method2
}

Мы хотим искать клиентов по имени и электронной почте.

Для этой цели мы напишем два метода, которые по-разному обрабатывают нулевые параметры.

3. Способы обработки нулевых параметров

Сначала мы создадим метод, который интерпретирует нулевые значения параметров как IS NULL, а затем мы создадим метод, который игнорирует нулевые параметры и исключает их из WHERE. пункт.

3.1. IS NULL Query

Первый метод создать очень просто, потому что пустые параметры в методах запроса по умолчанию интерпретируются как IS NULL.

Давайте создадим метод:

List<Customer> findByNameAndEmail(String name, String email);

Теперь, если мы передаем пустое электронное письмо, сгенерированный JPQL будет включать условие IS NULL:

customer0_.email is null

Чтобы продемонстрировать это, давайте создадим тест.

Сначала мы добавим в репозиторий несколько клиентов:

@Before
public void before() {
    entityManager.persist(new Customer("A", "[email protected]"));
    entityManager.persist(new Customer("D", null));
    entityManager.persist(new Customer("D", "[email protected]"));
}

Теперь давайте передадим «D» в качестве значения параметра name и null в качестве значения параметра электронной почты в наш метод запроса. Мы видим, что будет найден ровно один клиент:

List<Customer> customers = repository.findByNameAndEmail("D", null);

assertEquals(1, customers.size());

Customer actual = customers.get(0);

assertEquals(null, actual.getEmail());
assertEquals("D", actual.getName());

3.2. Избегайте нулевого параметра с помощью альтернативных методов

Иногда мы хотим игнорировать некоторые параметры и не включать соответствующие поля в предложение WHERE.


Мы можем добавить больше методов запроса в наш репозиторий. Например, для игнорирования электронной почты мы можем добавить метод, который принимает только имя:

 List<Customer> findByName(String name);

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

3.3. Игнорирование пустых параметров с помощью аннотации @Query

Мы можем избежать создания дополнительных методов, используя аннотацию @Query и добавив небольшое усложнение в оператор JPQL:

@Query("SELECT c FROM Customer c WHERE (:name is null or c.name = :name) and (:email is null"
  + " or c.email = :email)")
List<Customer> findCustomerByNameAndEmail(@Param("name") String name, @Param("email") String email);

Обратите внимание, что если параметр: email имеет значение null: ~ ~~

:email is null or s.email = :email

Тогда предложение всегда истинно и поэтому не влияет на все предложение WHERE.

Давайте удостоверимся, что это работает:

List<Customer> customers = repository.findCustomerByNameAndEmail("D", null);

assertEquals(2, customers.size());

Мы обнаружили двух клиентов по имени «D», которые игнорируют свои электронные письма.

Сгенерированное предложение JPQL WHERE выглядит следующим образом:

where (? is null or customer0_.name=?) and (? is null or customer0_.email=?)

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

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

Мы продемонстрировали, как Spring Data JPA интерпретирует пустые параметры в методах запроса, и показали, как изменить поведение по умолчанию.

Возможно, в будущем мы сможем указать, как интерпретировать нулевые параметры, используя аннотацию @NullMeans. Обратите внимание, что в настоящее время это предлагаемая функция, которая все еще находится на рассмотрении.

Подводя итог, можно сказать, что существует два основных способа интерпретации нулевых параметров, и оба они будут предоставлены предложенной аннотацией @NullMeans:

    IS (равно нулю) — вариант по умолчанию, продемонстрированный в разделе 3.1. IGNORED (исключить нулевой параметр из предложения WHERE) — достигается либо с помощью дополнительных методов запроса (раздел 3.2.), либо с помощью обходного пути (раздел 3.3.)

Как обычно, полный исходный код доступен на GitHub. .