Spring данные JPA и параметры, которые могут быть нулевыми

Я понимаю, что с помощью Spring данных JPA я не могу иметь метод запроса для извлечения всех строк, где столбец равен заданному параметру непустого метода, и использовать тот же метод для извлечения всех строк, где этот столбец равен NULL, когда параметр метода имеет значение null.

Правильно ли это?

Итак, я должен различать это в своем JAVA-коде, и я должен использовать отдельный метод запроса, явно запрашивающий нулевые значения, например, в примере ниже?

// Query methods
List<Something> findByParameter(Parameter parameter);
List<Something> findByParameterIsNull();

...

List<Something> result = new ArrayList<>();

if (parameter == null)
  result = findByParameterIsNull();
else
  result = findByParameter(parameter);

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

Ответы

Ответ 1

Вы правы.

Был сделан запрос для поддержки лучшей обработки нулевых параметров. https://jira.spring.io/browse/DATAJPA-121

В вашем случае я бы посоветовал вам написать реализацию репозитория и использовать пользовательский CriteriaQuery для обработки вашего случая.

Также вы можете использовать аннотацию @Query с синтаксисом is null:

@Query("[...] where :parameter is null"
public List<Something> getSomethingWithNullParameter();

РЕДАКТИРОВАТЬ

Начиная с Spring данных jpa 2.0, Spring теперь поддерживает аннотацию @Nullable. Это может быть полезно для обработки пустых параметров.

Из документации:

@Nullable - для использования с параметром или возвращаемым значением, которое может быть нулевым.

Ответ 2

Кажется, Query by Example может быть тем, что вам нужно.

Запрос по примеру - это новая функция в Spring Data (с версии Hopper, апрель 2016 года), которая позволяет создавать простые динамические запросы с таким кодом

Person person = new Person();                          
person.setFirstname("Dave");                           

ExampleMatcher matcher = ExampleMatcher.matching()     
  .withIncludeNullValues();                        

Example<Person> example = Example.of(person, matcher);

personRepository.count(example);
personRepository.findOne(example);
personRepository.findAll(example);

Методы count/findOne/findAll, которые принимают экземпляр org.springframework.data.domain.Example в качестве параметра (а некоторые из них также принимают параметры сортировки/разбиения на страницы) поступают из интерфейса org.springframework.data.repository.query.QueryByExampleExecutor<T>, который расширяется интерфейсом org.springframework.data.jpa.repository.JpaRepository<T, ID extends Serializable>.

Короче говоря, все экземпляры JpaRepository теперь имеют эти методы.

Ответ 3

я нашел что-то... если вы поместите параметр в методе jpa, как это

@Param("value") String value,

тогда оно может быть нулевым, и в запросе у вас будет следующее условие:

(table.value = :value OR :value IS NULL)

если значение равно нулю, оно автоматически вернет истину, а если не равно нулю, оно будет искать это значение в таблице.

Ответ 4

Сегодня по состоянию на июнь 2018 года, глядя на https://jira.spring.io/browse/DATAJPA-121, запрос автоматически сформируется is null если ваш параметр равен нулю.

Я сделал это в моем проекте, это правда:

compile group: 'org.springframework.data', name: 'spring-data-jpa', version: '2.0.7.RELEASE'

-

public interface AccountDao extends CrudRepository<T, ID> {

    //this can accept null and it will become isNull
    public List<MyAccount> findByEmail(String email);

}

если параметр равен нулю:

select
        myaccount0_.id as id1_0_,
        myaccount0_.email as email2_0_,
        myaccount0_.password as password3_0_,
        myaccount0_.user_id as user_id4_0_ 
    from
        my_account myaccount0_ 
    where
        myaccount0_.email is null

если параметр не нуль:

select
        myaccount0_.id as id1_0_,
        myaccount0_.email as email2_0_,
        myaccount0_.password as password3_0_,
        myaccount0_.user_id as user_id4_0_ 
    from
        my_account myaccount0_ 
    where
        myaccount0_.email=?
11:02:41.623 [qtp1507181879-72] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - [[email protected]] 

Затем возникает интересный вопрос: некоторые разработчики хотят, чтобы лучший элемент управления игнорировал параметр в запросе, если он нулевой, это все еще изучается в https://jira.spring.io/browse/DATAJPA-209.

Ответ 5

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

      @Query(value = "SELECT pr FROM ABCTable pr " +
            "WHERE LOWER(pr.xyz) = LOWER(:xyz) " +
            "and LOWER(pr.subscriptionReference) = LOWER(:subscriptionReference) " +
            "and pr.billId = :billId " +
            "and ((pr.membershipNumber = :membershipId) or (pr.membershipNumber = null and :membershipId = null))")
    List<PaymentRequest> getSomething (@Param("xyz") String xyz,
                                                 @Param("subscriptionReference") String subscriptionReference,
                                                 @Param("billId") Integer billId,
                                                 @Param("membershipId") String membershipNumber);