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

如何在Spring JPA Specification的Criteria Builder中添加多组AND/OR条件

解决Spring Data JPA Specification中AND条件不生效的问题

你的问题核心是没有将AND组合的Predicate与OR条件合并到最终返回的结果中,而且OR条件的构建存在冗余写法。

问题分析

  1. 你通过criteriaBuilder.and(andPredicates.toArray(...))生成了AND组合的Predicate,但没有保存这个对象,也没让它参与最终的条件组合
  2. 方法最后直接返回了OR条件的Predicate,完全忽略了AND部分,导致AND条件从未生效
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 15:55:59