Spring Data JPA 忽略空参数

Posted

技术标签:

【中文标题】Spring Data JPA 忽略空参数【英文标题】:Spring Data JPA ignore null parameter 【发布时间】:2019-07-02 19:40:29 【问题描述】:

假设我有以下 JPA 方法:

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

此方法由用户调用,用户使用输入字段和选择字段过滤这些对象的列表:

在这种情况下,如果用户没有使用该字段进行搜索,则布尔值可以是 true、false 或 null。当我希望 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 个搜索选项的页面上,这将成为一场噩梦。字符串参数没有这个问题,因为当用户没有选择过滤器时,它们实际上是一个空字符串。这与 Containing 关键字配对,任何值都包含 "" 所以它的行为就好像该参数被忽略了,这正是我想要的其他类型。 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 数据规范 【参考方案1】:

你可以像这样使用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);

【讨论】:

我试过了,它总是返回一个空列表,即使我输入了对象具有的完全相同的值 在对 ExampleMatcher 进行一些研究时,我能够让它完全按照我想要的方式工作,并从我的应用程序中消除大量代码! Spring Data 非常强大,谢谢!

以上是关于Spring Data JPA 忽略空参数的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA - NUMBER 列类型的空参数问题

Spring Data Jpa

请教关于Spring Data JPA动态查询参数的问题

如何忽略 Spring JPQL 中的空参数?

Spring Data JPA JSONB参数化

Spring Data JPA如何传递日期参数