首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CriteriaBuilder.createQuery和EntityManager.createQuery有什么区别?

CriteriaBuilder.createQuery和EntityManager.createQuery有什么区别?
EN

Stack Overflow用户
提问于 2020-09-04 15:10:11
回答 1查看 3.3K关注 0票数 2

假设我有密码,就像:

代码语言:javascript
复制
EntityManager em = ...;
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.select(pet);
TypedQuery<Pet> q = em.createQuery(cq);
List<Pet> allPets = q.getResultList();

请一些人解释一下为什么我们使用两种createQuery()方法,它们之间有什么区别?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-09-04 17:28:21

CriteriaBuilder#createQuery(Class resultClass)创建CriteriaQuery

EntityManager#createQuery(CriteriaQuery criteriaQuery)创建TypedQuery

TL;DR:

这两种类型不是彼此的选择,而是为了不同的目的:

CriteriaQuery<T>用于以编程方式定义查询,而不是手动编写查询,TypedQuery<T>用于避免在使用Query时必须进行的转换。你甚至可以将两者结合使用,我将向你展示-如何使用。

现在,让我们看一下更多的细节。

TypedQuery<T>

JPA用QueryTypedQuery<T>StoredProcedureQuery实例表示查询(全部来自javax.persistence包,后两个扩展Query)。

使用Query的简单示例如下所示:

代码语言:javascript
复制
Query query = em.createQuery("your select query.."); //you write query
SomeType result = (SomeType) query.getSingleResult(); //cast needed
List<SomeType> resultList = (List<SomeType>) query.getResultList(); //cast needed

注意,Query API方法返回Object或原始类型(没有专门类型) List实例,必须将其转换为预期的类型。

另一方面,TypedQuery<T>在某种程度上不同于Query,即在创建查询时提供预期返回值的类,然后跳过转换部分,如下所示:

代码语言:javascript
复制
TypedQuery<SomeType> typedQuery = em.createQuery("your select query..");
SomeType result = typedQuery.getSingleResult(); //<-- no cast needed.
List<SomeType> result = typedQuery.getResultList(); //<-- no cast needed.

在这里,重要的点是,在所有这些情况下,您必须手动编写或JPQL查询,以构造相应的Query实例,然后将调用相应的方法。

CriteriaQuery<T>

JPA规范2.2

JPA标准API用于通过构造基于对象的查询定义对象来定义查询,而不是使用Java持久性查询语言的基于字符串的方法。

CriteriaQuery在概念上与Query(您构建用于从数据库获取数据的查询)是一样的,它是定义JPQL/HQL查询的另一种方法。

CriteriaQuery<T>的主要目的是提供一种编程和类型安全的方法来定义与平台无关的查询。因此,不必手动编写HQL/JPQL查询,而是以编程方式构造查询,如下所示:

代码语言:javascript
复制
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<SomeType> cq = cb.createQuery(SomeType.class);
Root<SomeType> root = cq.from(SomeType.class);

//programmatically adding criterias and/or some filter clauses to your query
cq.select(root);
cq.orderBy(cb.desc(root.get("id")));

//passing cq to entityManager or session object
TypedQuery<SomeType> typedQuery = entityManager.createQuery(cq);
List<SomeType> list =  typedQuery.getResultList();

回答最后一个问题-哪些方法访问数据库?

在所有上述情况下,在调用Query (或其子对象)对象的方法时,实际查询都会命中数据库。在我们的例子中,这些是:

代码语言:javascript
复制
query.getSingleResult();
query.getResultList();
typedQuery.getSingleResult();
typedQuery.getResultList();

记住两个步骤:

  1. 定义/构造查询对象(使用HQLJPQLCriteriaQuery<T>);
  2. 调用该对象上的API方法,该对象实际上是查询数据库的。
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63743774

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档