Spring Data JPA参数为null时不忽略查询条件返回空列表解决方案
解决方案(无需重构,仅修改现有代码即可,5分钟可完成)
核心问题定位
- 集合参数判断逻辑缺失空集合校验:当前JPQL只判断了集合参数是否为
null,如果前端传入的是空数组(而非null),会生成in ()的非法语法,直接返回空结果,所有集合类参数的判断都需要补充空集合校验。 - 左连接过滤条件位置错误:你把关联表(researchers、fundingAgencies)的过滤条件写在where子句中,会过滤掉关联表数据为空的行,等同于将左连接转为内连接,导致匹配的数据被误过滤,需要把关联表的过滤条件移到
join的on子句中。 - 关联查询返回重复数据:左连接后如果一个研究项目关联多个研究人员/资助机构,会返回重复的项目数据,需要加
distinct去重。
修改后的完整代码
@Query("select distinct r from Research r " + "left join r.fundingAgencies fundingAgencies on (:agencyNames is null or :agencyNames is empty or fundingAgencies.agencyName in :agencyNames) " + "left join r.researchers researchers on (:names is null or :names is empty or researchers.name in :names) " + "where (:budgetStart is null or :budgetEnd is null or r.budget between :budgetStart and :budgetEnd) " + "and (:startDate is null or r.startDate >= :startDate) " + "and (:endDate is null or r.endDate <= :endDate) " + "and (:unitNames is null or :unitNames is empty or r.deliveryUnit.unitName in :unitNames) " + "and (:researchStatuses is null or :researchStatuses is empty or r.researchStatus in :researchStatuses)") List<Research> findAdvanced( @Param("budgetStart") Double budgetStart, @Param("budgetEnd") Double budgetEnd, @Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate, @Param("agencyNames") Collection<String> agencyNames, @Param("unitNames") Collection<String> unitNames, @Param("names") Collection<String> names, @Param("researchStatuses") Collection<ResearchStatus> researchStatuses);
额外可选优化
如果你的业务需要支持单边界的预算查询(比如只查大于10w的预算,不需要同时传上下限),可以把预算判断逻辑改成如下,兼容性更强:
"and (:budgetStart is null or r.budget >= :budgetStart) " + "and (:budgetEnd is null or r.budget <= :budgetEnd) "
内容的提问来源于stack exchange,提问作者ruuuyin
相关产品推荐
相关产品推荐

