CriteriaBuilder.createQuery 和 EntityManager.createQuery 有什么区别?
What is the difference between CriteriaBuilder.createQuery and EntityManager.createQuery?
假设我有代码,例如:
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()
方法,它们之间有什么区别?
CriteriaBuilder#createQuery(Class<T> resultClass)
creates CriteriaQuery<T>
和
EntityManager#createQuery(CriteriaQuery<T> criteriaQuery)
creates TypedQuery<T>
.
TL;DR:
这两种类型不是彼此的替代品,它们的用途不同:
CriteriaQuery<T>
用于以编程方式定义查询,而不是手动编写,TypedQuery<T>
用于避免在使用 Query
时必须执行的强制转换。您甚至可以将两者结合使用,我会告诉您如何使用。
现在,让我们更详细地了解一下。
TypedQuery<T>
JPA 用 Query
、TypedQuery<T>
或 StoredProcedureQuery
实例表示 query(全部来自 javax.persistence
包,后两个扩展 Query
).
使用 Query
的简单示例如下所示:
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 方法 return Object
或原始类型(没有专用类型)List
实例,您必须对其进行转换到您期望的类型。
另一方面,TypedQuery<T>
在某种程度上不同于 Query
,您在创建查询时提供预期 return 值的 class,然后你跳过铸造部分,像这样:
TypedQuery<SomeType> typedQuery = em.createQuery("your select query..");
SomeType result = typedQuery.getSingleResult(); //<-- no cast needed.
List<SomeType> result = typedQuery.getResultList(); //<-- no cast needed.
这里重要的点是,在所有这些情况下,你必须手动编写 HQL 或 JPQL 查询才能构造相应的Query
个实例,之后您将在其上调用相应的方法。
CriteriaQuery<T>
The JPA Criteria API is used to define queries through the construction of object-based query definition objects, rather than use of the string-based approach of the Java Persistence query language.
CriteriaQuery
在概念上与 Query
相同( 你构建用于获取数据的查询 from/to 数据库 )并且它是定义 JPQL/HQL 查询的另一种方法。
CriteriaQuery<T>
的主要目的是提供一种程序化和type-safe方式来定义platform-independent查询。因此,您无需手动编写 HQL/JPQL 查询,而是以编程方式构建查询,如下所示:
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
(或其子对象)对象的方法时,实际查询会命中数据库。在我们的示例中,这些是:
query.getSingleResult();
query.getResultList();
typedQuery.getSingleResult();
typedQuery.getResultList();
记住两步:
- 您 define/construct 查询对象(使用
HQL
、JPQL
或 CriteriaQuery<T>
);
- 您对该对象调用了 API 方法,这实际上查询了数据库。
假设我有代码,例如:
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()
方法,它们之间有什么区别?
CriteriaBuilder#createQuery(Class<T> resultClass)
creates CriteriaQuery<T>
和
EntityManager#createQuery(CriteriaQuery<T> criteriaQuery)
creates TypedQuery<T>
.
TL;DR:
这两种类型不是彼此的替代品,它们的用途不同:
CriteriaQuery<T>
用于以编程方式定义查询,而不是手动编写,TypedQuery<T>
用于避免在使用 Query
时必须执行的强制转换。您甚至可以将两者结合使用,我会告诉您如何使用。
现在,让我们更详细地了解一下。
TypedQuery<T>
JPA 用 Query
、TypedQuery<T>
或 StoredProcedureQuery
实例表示 query(全部来自 javax.persistence
包,后两个扩展 Query
).
使用 Query
的简单示例如下所示:
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 方法 return Object
或原始类型(没有专用类型)List
实例,您必须对其进行转换到您期望的类型。
TypedQuery<T>
在某种程度上不同于 Query
,您在创建查询时提供预期 return 值的 class,然后你跳过铸造部分,像这样:
TypedQuery<SomeType> typedQuery = em.createQuery("your select query..");
SomeType result = typedQuery.getSingleResult(); //<-- no cast needed.
List<SomeType> result = typedQuery.getResultList(); //<-- no cast needed.
这里重要的点是,在所有这些情况下,你必须手动编写 HQL 或 JPQL 查询才能构造相应的Query
个实例,之后您将在其上调用相应的方法。
CriteriaQuery<T>
The JPA Criteria API is used to define queries through the construction of object-based query definition objects, rather than use of the string-based approach of the Java Persistence query language.
CriteriaQuery
在概念上与 Query
相同( 你构建用于获取数据的查询 from/to 数据库 )并且它是定义 JPQL/HQL 查询的另一种方法。
CriteriaQuery<T>
的主要目的是提供一种程序化和type-safe方式来定义platform-independent查询。因此,您无需手动编写 HQL/JPQL 查询,而是以编程方式构建查询,如下所示:
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
(或其子对象)对象的方法时,实际查询会命中数据库。在我们的示例中,这些是:
query.getSingleResult();
query.getResultList();
typedQuery.getSingleResult();
typedQuery.getResultList();
记住两步:
- 您 define/construct 查询对象(使用
HQL
、JPQL
或CriteriaQuery<T>
); - 您对该对象调用了 API 方法,这实际上查询了数据库。