Spring Data JPA игнорирует нулевой параметр - PullRequest
0 голосов
/ 08 февраля 2019

Скажите, у меня есть метод JPA ниже:

public List<FrequencyCode> findAllByNameContainingAndAllowExplicitDosingTimesEqualsOrderByName(String name, Boolean allowExplicitDosingTimes);

Этот метод вызывается пользователем, фильтрующим список этих объектов с полем ввода и полем выбора:

enter image description here

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

@Override
public List<FrequencyCode> findAllWithFilters(String name, Boolean allowExplicitDosingTimes) 
{
    if (allowExplicitDosingTimes == null)
    {
        return ((FrequencyCodeRepository) baseRepository).findAllByNameContainingOrderByName(name);
    }
    else if (allowExplicitDosingTimes == true)
    {
        return ((FrequencyCodeRepository) baseRepository).findAllByNameContainingAndAllowExplicitDosingTimesTrueOrderByName(name);
    }
    else if (allowExplicitDosingTimes == false)
    {
        return ((FrequencyCodeRepository) baseRepository).findAllByNameContainingAndAllowExplicitDosingTimesFalseOrderByName(name);
    }

    return null;
}

Это работает, но, очевидно, на странице с 8 вариантами поиска это станет кошмаром.Параметры String не имеют этой проблемы, потому что они на самом деле являются пустой строкой, когда пользователь не выбирает фильтр.Это в сочетании с ключевым словом Contained, любое значение содержит "", поэтому он ведет себя так, как будто этот параметр игнорируется, что именно то, что я хочу для других типов.Есть ли способ для метода findAll ... () в JPA просто игнорировать нулевые параметры?

****** РЕШЕНИЕ ******

Вот как я сделалэта работа с помощью принятого ответа:

FrequencyCode fc = new FrequencyCode();
    fc.setName(name);
    fc.setAllowExplicitDosingTimes(allowExplicitDosingTimes);

    ExampleMatcher matcher = ExampleMatcher.matching()
        .withMatcher("name", match -> match.contains())
        .withMatcher("allowExplicitDosingTimes", match -> match.exact())
        .withIgnorePaths("id", "uuid")
        .withIgnoreNullValues();
    Example<FrequencyCode> example = Example.of(fc, matcher);

    List<FrequencyCode> frequencyCodes = ((FrequencyCodeRepository) baseRepository).findAll(example);

Вы ДОЛЖНЫ сказать ему игнорировать любые поля ID или действительно любые другие поля, с которыми вы не собираетесь искать, но это НЕВЕРОЯТНО мощно!

Спасибо!

1 Ответ

0 голосов
/ 08 февраля 2019

Вы можете использовать Example вот так

@Override
public List<FrequencyCode> findAllWithFilters(String name, Boolean allowExplicitDosingTimes) {

  FrequencyCode fc = new FrequencyCode();         
  //I assume that you have setters like bellow                 
  fc.setName(name);
  fc.setAllowExplicitDosingTimes(allowExplicitDosingTimes);                           

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

  Example<FrequencyCode> example = Example.of(fc, matcher);

  return ((FrequencyCodeRepository) baseRepository).findAll(example);
}
...