如何在Spring JPA Specification的Criteria Builder中添加多组AND/OR条件
解决Spring Data JPA Specification中AND条件不生效的问题
你的问题核心是没有将AND组合的Predicate与OR条件合并到最终返回的结果中,而且OR条件的构建存在冗余写法。
问题分析
- 你通过
criteriaBuilder.and(andPredicates.toArray(...))生成了AND组合的Predicate,但没有保存这个对象,也没让它参与最终的条件组合 - 方法最后直接返回了OR条件的Predicate,完全忽略了AND部分,导致AND条件从未生效
- OR条件列表里的
criteriaBuilder.or(criteriaBuilder.equal(...))是多余的,单个equal不需要用or包裹,直接加入列表即可
修正后的代码
static class RtoReportsSpecification { public static Specification<ReportFilter> applyFilter(ReportFilter reportFilter, String userId) { return new Specification<ReportFilter>() { private static final long serialVersionUID = 1L; @Override public Predicate toPredicate(Root<ReportFilter> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) { // 构建AND条件列表并生成组合Predicate List<Predicate> andPredicates = new ArrayList<>(); andPredicates.add(criteriaBuilder.equal(root.get("field1"), reportFilter.getField1())); andPredicates.add(criteriaBuilder.equal(root.get("geography"), reportFilter.getGeography())); andPredicates.add(criteriaBuilder.equal(root.get("deptName"), reportFilter.getDeptName())); Predicate andPredicate = criteriaBuilder.and(andPredicates.toArray(new Predicate[0])); // 构建OR条件列表并生成组合Predicate(移除冗余的or包裹) List<Predicate> orPredicates = new ArrayList<>(); orPredicates.add(criteriaBuilder.equal(root.get("email1"), userId)); orPredicates.add(criteriaBuilder.equal(root.get("email2"), userId)); orPredicates.add(criteriaBuilder.equal(root.get("email3"), userId)); orPredicates.add(criteriaBuilder.equal(root.get("email4"), userId)); Predicate orPredicate = criteriaBuilder.or(orPredicates.toArray(new Predicate[0])); // 合并AND和OR条件:最终逻辑为 (所有AND条件同时满足) 并且 (任一OR条件满足) Predicate finalPredicate = criteriaBuilder.and(andPredicate, orPredicate); query.orderBy(criteriaBuilder.asc(root.get("empName"))); return finalPredicate; } }; } } public List<RtoReport> findRtoReportsData(ReportFilter reportFilter, String userId) { return rtoReportsRepo.findAll(RtoReportsSpecification.applyFilter(reportFilter, userId)); }
关键修改点
- 保存
criteriaBuilder.and()生成的AND Predicate对象,避免创建后被丢弃 - 简化OR条件的构建逻辑,去掉不必要的单个条件or包裹
- 将AND和OR条件合并为最终的Predicate并返回,确保两组条件都能参与查询过滤
内容的提问来源于stack exchange,提问作者Shailesh Vikram Singh
相关产品推荐
相关产品推荐

