JPA中如何结合CriteriaBuilder与ArrayList实现城市列表条件筛选
CriteriaBuilder实现多城市列表筛选解决方案
问题核心
你之前注释的循环拼接equal的逻辑存在逻辑错误:多个equal条件通过and拼接,会要求数据同时匹配所有传入的城市名称,不可能返回符合条件的结果,多值匹配场景必须使用in运算符实现。
核心修正代码
找到Service层findAll方法中城市判断的分支,替换为以下代码:
// 追加空集合判断,避免空列表无返回的问题 if (city != null && !city.isEmpty()) { System.out.println("entra en el arreglo"); // 直接调用root属性的in方法,传入城市列表即可完成多值匹配 p = cb.and(p, root.get("city").in(city)); }
完整优化后的findAll方法
public List<Weather> findAll(String order, List<String> city, Date date ) { List<Weather> weather = this._weatherRepo.findAll((Specification<Weather>)(root, cq, cb) -> { Predicate p = cb.conjunction(); // 城市筛选 if (city != null && !city.isEmpty()) { System.out.println("entra en el arreglo"); p = cb.and(p, root.get("city").in(city)); } // 日期筛选 if (Objects.nonNull(date)) { p = cb.and(p, cb.equal(root.get("date"), date )); } // 排序逻辑,删除冗余的重复非空判断 if (!StringUtils.isEmpty(order)) { switch(order) { case "date": cq.orderBy(cb.asc(root.get("date"))); break; case "-date": cq.orderBy(cb.desc(root.get("date"))); break; default: cq.orderBy(cb.asc(root.get("id"))); } } return p; }); return weather; }
注意事项
- 确认
root.get("city")中的属性名和Weather实体类中对应城市字段的属性名完全一致,若字段配置了@Column别名,需要用实体类的属性名而非数据库字段名 - 追加了空集合判断,避免前端传入空的城市列表时查询无结果
- 原有排序逻辑中存在两层重复的
order非空判断,已删除冗余层
内容的提问来源于stack exchange,提问作者Gerardo Guevara
相关产品推荐
相关产品推荐

