问题描述
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)
创建CriteriaQuery<T>
和EntityManager#createQuery(CriteriaQuery<T> criteriaQuery)
创建TypedQuery<T>
。
TL; DR:
这两种类型不是彼此替代的,它们具有不同的用途:
CriteriaQuery<T>
用于以编程方式定义查询,而不是手动编写查询,并且TypedQuery<T>
用于避免强制转换,而在使用Query
时必须执行此操作。您甚至可以将两者结合使用,我将向您展示-方法。
现在,让我们详细了解一下。
TypedQuery<T>
JPA用Query
,TypedQuery<T>
或StoredProcedureQuery
实例(均来自javax.persistence
包,而后两个扩展{{1} }。
使用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
API方法将返回Query
或原始类型(无特殊类型)Object
实例,您必须将其强制转换为期望的类型。
List
与TypedQuery<T>
的不同之处在于,在创建查询时您提供了期望的返回值的类,并且跳过了强制转换部分,如下所示:
Query
重要的要点是,在所有这些情况下,您都必须手动编写HQL或JPQL查询,以构造相应的TypedQuery<SomeType> typedQuery = em.createQuery("your select query..");
SomeType result = typedQuery.getSingleResult(); //<-- no cast needed.
List<SomeType> result = typedQuery.getResultList(); //<-- no cast needed.
实例,然后,您将调用相应的方法。
Query
JPA Criteria API用于通过构建基于对象的查询定义对象来定义查询,而不是使用Java Persistence查询语言的基于字符串的方法。
CriteriaQuery<T>
在概念上与CriteriaQuery
相同(您构建用于从数据库获取数据或从数据库获取数据的查询),它是定义JPQL的另一种方法/ HQL查询。
Query
的主要目的是提供一种 programmatic 和 type-safe 方式来定义与平台无关的查询。因此,您无需以编程方式构造查询,而无需手动编写HQL / JPQL查询,如下所示:
CriteriaQuery<T>
回答您的最后一个问题-哪种方法可以访问数据库?:
在上述所有情况下,调用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();
,HQL
或JPQL
); - 您在该对象上调用API方法,这些方法实际上查询数据库。