1. 概述
在使用 JPA 进行数据库查询时,我们经常需要组合多个 AND 或 OR 条件来筛选数据。JPA 的 Criteria API 提供了非常灵活的方式来构造这类复杂查询。本文将通过几个实际例子,展示如何使用 Criteria API 组合多个 AND 和 OR 的查询条件。
如果你还不熟悉 Predicate
的基本用法,建议先阅读 基础 JPA Criteria 查询 相关内容。
2. 示例应用背景
我们以一个物品库存系统为例,其中每个物品是一个 Item
实体,包含以下字段:
@Entity
public class Item {
@Id
private Long id;
private String color;
private String grade;
private String name;
// 标准的 getter 和 setter 方法
}
字段说明如下:
id
: 主键color
: 颜色(如 red、blue)grade
: 等级(如 A、B、C)name
: 物品名称
3. 使用 AND 组合两个 OR 条件
假设我们要查询满足以下两个条件的物品:
- 颜色是 red 或 blue ✅
AND - 等级是 A 或 B ✅
这可以通过 JPA Criteria API 中的 and()
和 or()
方法来轻松实现。
首先,构建基本查询结构:
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Item> criteriaQuery = criteriaBuilder.createQuery(Item.class);
Root<Item> itemRoot = criteriaQuery.from(Item.class);
接着,构造颜色为 red 或 blue 的条件:
Predicate predicateForBlueColor
= criteriaBuilder.equal(itemRoot.get("color"), "blue");
Predicate predicateForRedColor
= criteriaBuilder.equal(itemRoot.get("color"), "red");
Predicate predicateForColor
= criteriaBuilder.or(predicateForBlueColor, predicateForRedColor);
再构造等级为 A 或 B 的条件:
Predicate predicateForGradeA
= criteriaBuilder.equal(itemRoot.get("grade"), "A");
Predicate predicateForGradeB
= criteriaBuilder.equal(itemRoot.get("grade"), "B");
Predicate predicateForGrade
= criteriaBuilder.or(predicateForGradeA, predicateForGradeB);
最后,将这两个 OR 条件通过 AND 组合,并执行查询:
Predicate finalPredicate
= criteriaBuilder.and(predicateForColor, predicateForGrade);
criteriaQuery.where(finalPredicate);
List<Item> items = entityManager.createQuery(criteriaQuery).getResultList();
4. 使用 OR 组合两个 AND 条件
再来看一个相反的例子:我们要查询满足以下任一条件的物品:
- 颜色是 red 且 等级是 D ✅
OR - 颜色是 blue 且 等级是 B ✅
这种场景下,我们需要先构造两个 AND 条件,再用 OR 将它们组合起来:
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Item> criteriaQuery = criteriaBuilder.createQuery(Item.class);
Root<Item> itemRoot = criteriaQuery.from(Item.class);
Predicate predicateForRedColor
= criteriaBuilder.equal(itemRoot.get("color"), "red");
Predicate predicateForGradeD
= criteriaBuilder.equal(itemRoot.get("grade"), "D");
Predicate predicateForRedAndD
= criteriaBuilder.and(predicateForRedColor, predicateForGradeD);
Predicate predicateForBlueColor
= criteriaBuilder.equal(itemRoot.get("color"), "blue");
Predicate predicateForGradeB
= criteriaBuilder.equal(itemRoot.get("grade"), "B");
Predicate predicateForBlueAndB
= criteriaBuilder.and(predicateForBlueColor, predicateForGradeB);
Predicate finalPredicate
= criteriaBuilder.or(predicateForRedAndD, predicateForBlueAndB);
criteriaQuery.where(finalPredicate);
List<Item> items = entityManager.createQuery(criteriaQuery).getResultList();
⚠️ 注意变量命名清晰,避免混淆(比如上面把 red 和 blue 写反了,已修正)。
5. 总结
在这篇文章中,我们展示了如何使用 JPA Criteria API 来组合 AND 和 OR 查询条件,从而实现更复杂的筛选逻辑。虽然写法略显啰嗦,但在需要动态构造查询的场景下,这种方式非常实用。
✅ 优点:
- 类型安全,避免字符串拼接错误
- 动态查询构造灵活
❌ 缺点:
- 代码量较大,可读性略差
📌 本文完整代码可从 GitHub 获取:https://github.com/eugenp/tutorials/tree/master/persistence-modules/java-jpa-2