JPA Criteria Predicate And/Or组合异常 如何实现带括号分组的条件查询
问题修复方案
逻辑优先级澄清
SQL 中 AND 运算符的优先级天然高于 OR,所以你提到的未加分组括号的条件:
(sku = 'A' AND uom_code = 'B' OR sku = 'C' AND uom_code = 'D')
和你期望的分组逻辑:
(sku = 'A' AND uom_code = 'B') OR (sku = 'C' AND uom_code = 'D')
执行逻辑完全等价,不会出现结果偏差。如果需要显式生成带分组括号的SQL提升可读性,或者避免后续拼接其他条件时出现逻辑混淆,可以按下面的方案修改代码。
代码修改点
你原来的代码里存在冗余的无效cb.or封装,调整后完整代码如下:
public class VariantSpecification implements Specification<VariantModel> { private final VariantFilter filter; public VariantSpecification(VariantFilter filter) { this.filter = filter; } @Override public Predicate toPredicate( Root<VariantModel> root, CriteriaQuery<?> query, CriteriaBuilder cb ) { final List<Predicate> predicates = new ArrayList<>(); if (filter.getMerchantId() != null) { predicates.add(cb.equal(root.get("merchantId"), filter.getMerchantId())); } Predicate basePredicate = cb.and(predicates.toArray(new Predicate[0])); List<Predicate> skuUomPredicates = new ArrayList<>(); if (!CollectionUtils.isEmpty(filter.getSkusUoms())) { filter.getSkusUoms().forEach(pair -> { String sku = pair.getLeft(); String uom = pair.getRight(); Predicate groupPredicate = cb.and( cb.equal(root.get("sku"), sku), cb.equal(root.get("uomCode"), uom) ); skuUomPredicates.add(groupPredicate); }); } if (!skuUomPredicates.isEmpty()) { Predicate skuUomCondition = cb.or(skuUomPredicates.toArray(new Predicate[0])); return cb.and(basePredicate, skuUomCondition); } return basePredicate; } }
调整说明
- 删除了每个sku+uom组合条件外层多余的
cb.or封装,减少无效逻辑 - 调用
cb.or传入所有AND组合条件时,JPA Criteria API会自动为每个AND组合添加分组括号,最终生成的SQL格式会严格符合你的预期 - 调整了变量命名,提升代码可读性
内容的提问来源于stack exchange,提问作者Loint
相关产品推荐
相关产品推荐

