1. 概述
在本教程中,我们将讨论一个非常有用的JPA功能 - Criteria Queries。
它不仅使我们能够在不执行原始SQL的情况下编写查询,而且还为我们提供了一些对查询的面向对象控制,这是Hibernate的主要特性之一。Criteria API允许我们以编程方式构建条件查询对象,我们可以在其中应用不同类型的过滤规则和逻辑条件。
从Hibernate 5.2开始,不推荐使用Hibernate Criteria API,新开发的重点是JPA Criteria API。我们将探索如何使用Hibernate和JPA来构建Criteria Queries。
2. Maven依赖
为了说明API,我们将使用参考JPA实现 - Hibernate。
要使用Hibernate,请确保将最新版本添加到pom.xml文件中:
1 | <dependency> |
可以在这里找到最新版本的Hibernate。
3. 使用 Criteria 的简单示例
让我们首先看一下如何使用Criteria查询检索数据。我们将看看如何从数据库中获取特定类的所有实例。
我们有一个Item类,它表示数据库中的元组“ITEM”:
1 | public class Item implements Serializable { |
让我们看一个简单的条件查询,它将从数据库中检索“ ITEM”的所有行:
1 | Session session = HibernateUtil.getHibernateSession(); |
以上查询是如何获取所有项目的简单演示。让我们一步一步看看做了些什么:
- 从SessionFactory对象创建Session实例
- 通过调用getCriteriaBuilder()方法创建C riteriaBuilder的实例
- 通过调用 CriteriaBuilder createQuery()方法创建CriteriaQuery实例
- 通过调用 Session createQuery()方法创建Query实例
- 调用查询对象的getResultList()方法,该方法为我们提供结果
现在我们已经介绍了基础知识,让我们继续讨论条件查询的一些功能。
3.1 使用表达式
CriteriaBuilder可用于限制基于特定条件的查询结果。 通过使用 CriteriaQuery where()方法并提供CriteriaBuilder 创建的 表达式。
以下是常用表达式的一些示例:
要获得价格超过1000的商品:
1 | cr.select(root).where(cb.gt(root.get("itemPrice"), 1000)); |
接下来,获取itemPrice小于1000的项目:
1 | cr.select(root).where(cb.lt(root.get("itemPrice"), 1000)); |
有项目itemNames中含有 chair:
1 | cr.select(root).where(cb.like(root.get("itemName"), "%chair%")); |
记录itemPrice在100到200之间:
1 | cr.select(root).where(cb.between(root.get("itemPrice"), 100, 200)); |
要检查给定属性是否为null:
1 | cr.select(root).where(cb.isNull(root.get("itemDescription"))); |
要检查给定属性是否为null:
1 | cr.select(root).where(cb.isNotNull(root.get("itemDescription"))); |
您还可以使用方法isEmpty()和isNotEmpty()来测试类中的List是否为空。
现在问题不可避免地出现了,我们是否可以将上述两种或两种以上的比较结合起来。答案当然是肯定的 - Criteria API允许我们轻松地链接表达式:
1 | Predicate[] predicates = new Predicate[2]; |
要使用逻辑运算添加两个表达式:
1 | Predicate greaterThanPrice = cb.gt(root.get("itemPrice"), 1000); |
具有上述定义条件的项目与Logical OR连接:
1 | cr.select(root).where(cb.or(greaterThanPrice, chairItems)); |
要获取与使用Logical AND连接的上述条件匹配的项目:
1 | cr.select(root).where(cb.and(greaterThanPrice, chairItems)); |
3.2 排序
现在我们已经了解了Criteria的基本用法,让我们来看看Criteria的排序功能。
在下面的示例中,我们按名称的升序排列列表,然后按价格的降序排列:
1 | cr.orderBy( |
在下一节中,我们将了解如何进行聚合函数。
3.3 投影、聚合和分组功能
到目前为止,我们已经涵盖了大部分基本主题。现在让我们看看不同的聚合函数:
行数:
1 | CriteriaQuery<Long> cr = cb.createQuery(Long.class); |
以下是聚合函数的示例:
求 平均 的聚合函数:
1 | CriteriaQuery<Double> cr = cb.createQuery(Double.class); |
其他有用的聚合方法是sum(),max(),min() ,count() 等。
3.4 CriteriaUpdate
从JPA 2.1开始,支持使用Criteria API 执行数据库更新。
CriteriaUpdate有一个set()方法,可用于为数据库记录提供新值:
1 | CriteriaUpdate<Item> criteriaUpdate = cb.createCriteriaUpdate(Item.class); |
在上面的代码片段中,我们从 CriteriaBuilder创建了CriteriaUpdate
3.5 CriteriaDelete
CriteriaDelete,顾名思义,使用Criteria API 启用删除操作。我们所需要的只是创建一个CriteriaDelete实例 并使用 where() 方法来应用限制:
1 | CriteriaDelete<Item> criteriaDelete = cb.createCriteriaDelete(Item.class); |
4. 相比HQL的优势
在前面的部分中,我们介绍了如何使用Criteria Queries。
显然,Criteria查询优于HQL的主要和最强硬的优势是漂亮,干净,面向对象的API。
与普通的HQL相比,我们可以简单地编写更灵活的动态查询。逻辑可以通过IDE重构,并具有Java语言本身的所有类型安全优势。
当然也存在一些缺点,特别是在更复杂的连接处。
因此,一般来说,我们将不得不使用最好的工具 - 在大多数情况下可以使用Criteria API,但肯定有一些情况我们必须降低水平。