You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JPA自定义findAll查询中用ExampleMatcher实现动态条件查询

问题:JPA单调用实现动态条件查询

需求:调用JPA仓库时,传入stateId则按该值过滤县数据;stateId为空时返回所有县数据,要求单次仓库调用完成,无需分两次执行。

当前尝试的代码

业务逻辑代码:

StateCountyId stateCountyId = new StateCountyId();
StateCounty stateCounty = new StateCounty();
if(null != stateId){
  stateCountyId.setStateId(stateId);
}
stateCounty.setStateCountyId(stateCountyId);
return countiesRepository.findAllByStateCountyIdStateIdOrderByStateCountyIdCountyNameAsc
 (Example.of(stateCounty,  ExampleMatcher.matchingAll().withIgnoreCase()))
 .stream().map(this::countyAsDropDown).collect(Collectors.toList());

仓库接口:

@Repository
public interface CountiesRepository extends JpaRepository<StateCounty, StateCountyId> {
List<StateCounty> findAllByStateCountyIdStateIdOrderByStateCountyIdCountyNameAsc(Example 
stateId);
}

实体类:

@Entity
@Builder
public class StateCounty implements Serializable {
@EmbeddedId
StateCountyId stateCountyId;
@Column(name = "CODE_NBR")
private String codeNbr;
}

@Embeddable
@EqualsAndHashCode
public class StateCountyId implements Serializable {
@Column(name = "STATE_ID")
private String stateId;
@Column(name = "COUNTY_NAME")
private String countyName;
}

直接传参的问题

若直接传入字符串stateId调用如下方法:

countiesRepository.findAllByStateCountyIdStateIdOrderByStateCountyIdCountyNameAsc
(stateId)
.stream().map(this::countyAsDropDown).collect(Collectors.toList());

stateId有效时可正常查询,但stateId为空时会返回空结果,不符合返回全量数据的预期。


解决方案

方案1:使用Example+忽略空值属性

修正仓库接口

无需自定义方法,直接使用JpaRepository自带的findAll方法:

@Repository
public interface CountiesRepository extends JpaRepository<StateCounty, StateCountyId> {
}

调整业务逻辑代码

关键是给ExampleMatcher添加withIgnoreNullValues(),让JPA忽略空值属性,不生成对应查询条件:

StateCounty stateCounty = new StateCounty();
StateCountyId stateCountyId = new StateCountyId();

if (stateId != null) {
    stateCountyId.setStateId(stateId);
}
stateCounty.setStateCountyId(stateCountyId);

// 配置匹配器:忽略空值属性,避免空stateId生成IS NULL条件
ExampleMatcher matcher = ExampleMatcher.matchingAll()
        .withIgnoreCase()
        .withIgnoreNullValues();

// 定义排序规则
Sort sort = Sort.by(Sort.Direction.ASC, "stateCountyId.countyName");

// 调用自带的findAll方法
return countiesRepository.findAll(Example.of(stateCounty, matcher), sort)
        .stream()
        .map(this::countyAsDropDown)
        .collect(Collectors.toList());

方案2:使用@Query编写动态SQL

这种方式更直观,直接在SQL中处理动态条件:

仓库接口新增方法

@Repository
public interface CountiesRepository extends JpaRepository<StateCounty, StateCountyId> {
    @Query("SELECT sc FROM StateCounty sc WHERE (:stateId IS NULL OR sc.stateCountyId.stateId = :stateId) ORDER BY sc.stateCountyId.countyName ASC")
    List<StateCounty> findCountiesByStateId(@Param("stateId") String stateId);
}

业务逻辑调用

直接调用该方法即可,无需额外处理:

return countiesRepository.findCountiesByStateId(stateId)
        .stream()
        .map(this::countyAsDropDown)
        .collect(Collectors.toList());

内容的提问来源于stack exchange,提问作者VKP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 18:15:48