Hibernate 何时在JPA标准API中使用select子句?
不使用Hibernate 何时在JPA标准API中使用select子句?,hibernate,jpa,criteria,criteria-api,Hibernate,Jpa,Criteria,Criteria Api,不使用CriteriaQuery#select(): 现在,我不知道什么时候在JPA条件查询中使用select() 在指定查询结果的界面上,基本上有两种方式指定投影项(或者简单地说是选择项): CriteriaQuery<T> select(Selection<? extends T> selection); CriteriaQuery<T> multiselect(Selection<?>... selections); 仅出于完整性的考虑,我
CriteriaQuery#select()
:
现在,我不知道什么时候在JPA条件查询中使用select()
在指定查询结果的界面上,基本上有两种方式指定投影项(或者简单地说是选择项):
CriteriaQuery<T> select(Selection<? extends T> selection);
CriteriaQuery<T> multiselect(Selection<?>... selections);
仅出于完整性的考虑,我将尝试依次用每个示例演示它们
通过
construct()
:
CompoundSelection<Y> construct(Class<Y> result, Selection<?>... terms);
CompoundSelection<Object[]> array(Selection<?>... terms);
CompoundSelection<Tuple> tuple(Selection<?>... terms);
CriteriaQuery<Object[]> q = cb.createQuery(Object[].class);
Root<Employee> root = q.from(Employee.class);
q.select(cb.array(root.get(Employee_.empName), root.get(Employee_.salary));
List<Object[]> list = entityManager.createQuery(q).getResultList();
CriteriaQuery<Tuple> q = cb.createTupleQuery();
Root<Employee> root = q.from(Employee.class);
Selection<String> empName = root.get(Employee_.empName).alias("empName");
q.select(cb.tuple(empName, root.get(Employee_.salary).alias("salary");
List<Tuple> list = entityManager.createQuery(q).getResultList();
String employeeName = list.get(0).get("empName");//Referring to by using its alias (empName)
String employeeSalary = list.get(0).get(1);//Referring to by using its index (salary)
//Iterate over a list of tuples through a foreach loop using alias.
for (Tuple tuple : list) {
System.out.println(tuple.get("empName") + " : " + tuple.get("salary"));
}
该方法创建给定类参数的实例,并使用输入选择项中的值调用(非持久实体的)构造函数。例如,非持久实体(甚至不是实体,一个普通Java类)的构造函数的这些参数必须在数量、顺序和类型(数据类型)上与输入选择项对应的值相匹配
CriteriaQuery<EmployeeDetails> q = cb.createQuery(EmployeeDetails.class);
Root<Employee> root = q.from(Employee.class);
q.select(cb.construct(EmployeeDetails.class, root.get(Employee_.empName), root.get(Employee_.salary));
可以看到,查询返回一个列表
。此列表的每个元素都包含一个基于0的Object
s-Object[]
数组
将查询结果整形为:
CompoundSelection<Y> construct(Class<Y> result, Selection<?>... terms);
CompoundSelection<Object[]> array(Selection<?>... terms);
CompoundSelection<Tuple> tuple(Selection<?>... terms);
CriteriaQuery<Object[]> q = cb.createQuery(Object[].class);
Root<Employee> root = q.from(Employee.class);
q.select(cb.array(root.get(Employee_.empName), root.get(Employee_.salary));
List<Object[]> list = entityManager.createQuery(q).getResultList();
CriteriaQuery<Tuple> q = cb.createTupleQuery();
Root<Employee> root = q.from(Employee.class);
Selection<String> empName = root.get(Employee_.empName).alias("empName");
q.select(cb.tuple(empName, root.get(Employee_.salary).alias("salary");
List<Tuple> list = entityManager.createQuery(q).getResultList();
String employeeName = list.get(0).get("empName");//Referring to by using its alias (empName)
String employeeSalary = list.get(0).get(1);//Referring to by using its index (salary)
//Iterate over a list of tuples through a foreach loop using alias.
for (Tuple tuple : list) {
System.out.println(tuple.get("empName") + " : " + tuple.get("salary"));
}
由于结果的类型是EmployeeDetails
,因此multiselect()
方法将其参数投影项解释为EmployeeDetails
的构造函数参数
请注意,像第一个示例中使用的这样的构造,cb.construct(EmployeeDetails.class,root.get(Employee.empName),root.get(Employee.salary)
,在前面的示例中不必使用multiselect()
根据查询的返回类型自动解释其参数投影项,并在结果类-EmployeeDetails
中调用适当的构造函数
如果将查询指定为返回一个Tuple
(或Tuple
s的列表),则具有完全相同参数的multiselect()
方法将创建Tuple
实例,如下所示
CriteriaQuery<Tuple> q = cb.createTupleQuery();
Root<Employee> root = q.from(Employee.class);
q.multiselect(root.get(Employee_.empName), root.get(Employee_.salary));
在这两种情况下,muliselect()
方法根据前面提到的查询返回类型(分别是Tuple
和Object[])自动解释其参数投影项
还应注意的是,EcliseLink有一个仍有待修复的选项,而使用multiselect()
以这种方式获取单个Boolean
选择项,如中所示
根据不同的JPA提供程序,multiselect()
方法的行为随着Object
作为结果类型而变得更加有趣
- 如果将
multiselect()
方法与单个选择术语一起使用,则返回类型为所选术语本身
- 但是,如果
multiselect()
方法包含多个输入项/选择项/投影项,则结果类型为Object[]
我不太清楚不同的提供程序,但是multiselect()
方法指定的选择项可能不是数组或集合(或元组值复合项)。唯一允许作为multiselect()
参数的复合项是由构造()创建的
方法,基本上依次表示单个元素
除上述结构外,在使用标量/组/聚合/单值函数(如count()
、max()
、min()
等)和子查询时,使用非常常见。为简洁起见,子查询的使用不包括在本答案中
选择
定义查询选择的内容。选择可以是
任意对象表达式、属性表达式、函数、子选择、,
构造函数或聚合函数。可以为
选择
使用alias()API
CriteriaBuilder-CriteriaBuilder=entityManager.getCriteriaBuilder();
//数一数员工总数
CriteriaQuery CriteriaQuery=criteriaBuilder.createQuery();
Root employee=criteriaQuery.from(employee.class);
criteriaQuery.select(criteriaBuilder.count(employee));//cq.select(root);
在JPA条件中推断,该条件将选择关联实体中的所有字段,从而从相应的数据库表中选择。但是,当您想要选择其中一些时,您需要明确。谢谢Tiny,但我仍然不太清楚。任何供参考的URL都会有很大帮助。,。您在理解代码片段或长文本信息时是否发现一些困难?这是一个单一、简单且精简的示例,重复了多次。我回答基于我记得的一个博客。我本想引用该博客中的许多内容,但不幸的是,我现在找不到该链接。顺便说一下,具体问题由一句话来回答:“作为唯一投影项的候选持久实体本身是隐式推断的。”您好,Tiny,非常感谢。您的回答非常具有描述性,这对我理解JPA标准非常有帮助。特别是关于投影。我知道现在已经晚了,但如何在criteriaQuery.multiselect中传递root.get(“”)列表?
CriteriaQuery<Object[]> q = cb.createQuery(Object[].class);
Root<Employee> root = q.from(Employee.class);
q.multiselect(root.get(Employee_.empName), root.get(Employee_.salary));
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
// Count the total employees
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.select(criteriaBuilder.count(employee)); //<------
Query query = entityManager.createQuery(criteriaQuery);
Long result = query.getSingleResult();
// Maximum salary
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.select(criteriaBuilder.max(employee.get("salary")); //<------
Query query = entityManager.createQuery(criteriaQuery);
Long result = query.getSingleResult();