Hibernate.org社区文档

第九章 标准查询

9.1. 类型化标准查询
9.1.1. 选择实体
9.1.2. 选择值
9.1.3. 选择多个值
9.1.4. 选择包装器
9.2. 元组标准查询
9.2.1. 访问元组元素
9.3. FROM 子句
9.3.1. 根
9.3.2. 连接
9.3.3. 获取
9.4. 路径表达式
9.5. 使用参数

标准查询是一种以编程方式表示查询的类型安全方法。它们在使用接口和类来表示查询的各个结构部分(如查询本身、select 子句或 order-by 等)方面是类型安全的。正如我们稍后将看到的,它们在引用属性方面也可以是类型安全的。老版 Hibernate 的 org.hibernate.Criteria 查询 API 的使用者将认可通用方法,尽管我们相信在从该 API 中吸取经验教训后 JPA API 更胜一筹。

标准查询基本上是一个对象图,其中图的每个部分表示进行查询时粒度更细微的部分(在我们深入此图时)。执行标准查询的第一步是构建此图。要开始使用标准查询,需要熟悉的第一件事是 javax.persistence.criteria.CriteriaBuilder 接口。它的作用是为所有独立的标准项充当一个工厂。通过调用 javax.persistence.EntityManagerFactorygetCriteriaBuilder 方法获取 javax.persistence.criteria.CriteriaBuilder 实例

CriteriaBuilder builder = entityManagerFactory.getCriteriaBuilder();

下一步是获取 javax.persistence.criteria.CriteriaQuery。为此,通过 javax.persistence.criteria.CriteriaBuilder 上的 3 种方法之一进行。

CriteriaQuery<T> createQuery(Class<T>)
CriteriaQuery<Tuple> createTupleQuery()
CriteriaQuery<Object> createQuery()

根据预期的查询结果类型,每种方法都有不同的用途。

注意

[JPA 2 规范] 中的第 6 章 标准 API 已包含大量参考材料,涉及标准查询的各个部分。因此,与其在此重复所有内容,不如让我们来看看 API 中一些更广泛预期的用法。

CriteriaQuery<T> createQuery(Class<T>)

标准查询(又称 <T>)的类型表示查询结果中预期的类型。这可以是实体、整数或任何其他对象。

选择值的简单形式是从实体中选择特定属性。但这还可能是聚合、数学运算等。



实际上,有几种不同的方法可以使用条件查询选择多个值。我们将在本文中探讨 2 种方法,但推荐的替代方法是使用元组,如第 9.2 节“元组条件查询”中所述



对于 第 9.1.3 节,“选择多个值”,更好的方法是使用包装器(我们在 第 9.1.4 节,“选择包装器” 中刚刚看到)或使用 javax.persistence.Tuple 合约。


javax.persistence.Tuple 合约提供了 3 种基本形式来访问基础元素

类型化
<X> X get(TupleElement<X> tupleElement)

这允许对基础元组元素进行类型化访问。我们在 示例 9.7,“选择元组” 中的 tuple.get( idPath )tuple.get( agePath ) 调用中看到了这一点。几乎所有内容都是 javax.persistence.TupleElement

位置
Object get(int i)
<X> X get(int i, Class<X> type)

非常与我们在 示例 9.4,“选择一个数组”示例 9.5,“选择一个数组 (2)” 中看到的位置访问类似。这里只有第二种形式提供类型,因为用户在访问时明确地提供了类型。我们可以在 示例 9.7,“选择一个元组” 中在 tuple.get( 0 )tuple.get( 1 ) 调用中看到这点。

别名
Object get(String alias)
<X> X get(String alias, Class<X> type)

同样,这里只有第二种形式提供类型,因为用户在访问时明确地提供了类型。我们没有看到使用它的示例,但其很简单。例如,我们只需对任一路径应用别名,如 idPath.alias( "id" ) 和/或 agePath.alias( "age" ),我们即可通过那些指定的别名访问各个元组元素。

 

CriteriaQuery 对象定义对一个或多个实体、可嵌入或基本抽象架构类型的查询。查询的根对象是实体,可通过导航访问其他类型。

 
 --[JPA 2 规范,第 6.5.2 节 查询根,第 262 页]

根定义了可查询中的所有联接、路径和属性的基础。在条件查询中,根始终为实体。根由 javax.persistence.criteria.CriteriaQuery 上重载的 from 方法定义并添加到条件中。

<X> Root<X> from(Class<X>)
<X> Root<X> from(EntityType<X>)

条件查询可定义多个根,其作用是在新添加的根与其他根之间创建 笛卡尔积。以下是匹配所有单身男性和所有单身女性的示例

CriteriaQuery query = builder.createQuery();

Root<Person> men = query.from( Person.class );
Root<Person> women = query.from( Person.class );
Predicate menRestriction = builder.and(
    builder.equal( men.get( Person_.gender ), Gender.MALE ),
    builder.equal( men.get( Person_.relationshipStatus ), RelationshipStatus.SINGLE )
);
Predicate womenRestriction = builder.and(
    builder.equal( women.get( Person_.gender ), Gender.FEMALE ),
    builder.equal( women.get( Person_.relationshipStatus ), RelationshipStatus.SINGLE )
);
query.where( builder.and( menRestriction, womenRestriction ) );