Spring Data JPA忽略null参数

5

假设我有以下 JPA 方法:

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

用户可以通过输入框和选择框来过滤这些对象列表并调用此方法:

enter image description here

在此情况下,布尔值可以为true、false或null,如果用户不使用该字段进行搜索,则为null。看起来JPA实际上正在搜索null值,而我希望它忽略任何null值。我已经能够通过以下代码使这个组合搜索工作:

@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个搜索选项的页面上,这将成为一种噩梦。字符串参数没有这个问题,因为当用户不选择筛选器时,它们实际上是一个空字符串。结合包含关键字,任何值都包含“”,所以它的行为就像忽略了该参数,这正是我想要的其他类型。是否有一种方法使JPA findAll...()方法简单地忽略空参数?
******解决方案******
以下是如何借助已接受的答案使其工作的方法:
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字段或者其他你不想用来搜索的字段,但这是非常强大的!

谢谢!


查看Spring Data规范。 - Patrick
1个回答

3
您可以像这样使用示例
@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);
}

我尝试过这个,即使我输入与对象完全相同的值,它总是返回一个空列表。 - Martin
1
在对ExampleMatcher进行一些研究后,我成功地让它按照我想要的方式工作,并从我的应用程序中消除了大量代码!Spring Data非常强大,谢谢! - Martin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接