Spring Data JPA ignore null parameter

Martin :

Say i have the below JPA method :

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

This method is called by a user filtering a list of these objects with an input field and a select field :

enter image description here

The boolean value can be true, false or null in this case if the user is not making a search with that field. It looks like JPA is ACTUALLY searching for a null value when i would like it to ignore any null values. I have been able to make this combined search work with the below code :

@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;
}

This works but, obviously, on a page with 8 search options this would become a nightmare. The String parameters do not have this problem because they are actually an empty String when the user doesn't choose a filter. This paired with the Containing keyword, any value contains "" so it behaves as if that parameter is ignored which is exactly what I want for other types. Is there a way for a JPA findAll...() method to simply ignore null parameters?

******SOLUTION******

Here is how i made this work with the help of the accepted answer :

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);

You HAVE to tell it to ignore any ID fields or really any other fields you do not intend to search with but this is INCREDIBLY powerful!

Thanks!

Saša Šijak :

You can use Example like this

@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);
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=82487&siteId=1