1.概述
本文说明了JPA可用于排序的各种方式。
2.使用JPA / JQL API排序
使用JQL进行排序是在Order By子句的帮助下完成的:
String jql ="Select f from Foo as f order by f.id";
Query query = entityManager.createQuery (jql);
基于此查询,JPA生成以下直接的SQL语句:
Hibernate: select foo0_.id as id1_4_, foo0_.name as name2_4_
from Foo foo0_ order by foo0_.id
请注意,JQL字符串中的SQL关键字不区分大小写,但实体的名称及其属性是。
2.1。设置排序顺序
默认情况下,排序顺序是升序,但可以在JQL字符串中显式设置。就像在纯SQL中一样,订购选项是asc和desc:
String jql = "Select f from Foo as f order by f.id desc";
Query sortQuery = entityManager.createQuery(jql);
该生成的SQL查询然后将包括顺序方向:
Hibernate: select foo0_.id as id1_4_, foo0_.name as name2_4_
from Foo foo0_ order by foo0_.id desc
2.2。按多个属性排序
要按多个属性排序,这些属性将添加到JQL字符串的o rder by子句中:
String jql ="Select f from Foo as f order by f.name asc, f.id desc";
Query sortQuery = entityManager.createQuery(jql);
两种排序条件都将出现在生成的SQL查询语句中:
Hibernate: select foo0_.id as id1_4_, foo0_.name as name2_4_
from Foo foo0_ order by foo0_.name asc, foo0_.id desc
2.3。设置空值的排序优先级
null的默认优先级是特定于数据库的,但可以通过HQL查询字符串中的NULLS FIRST或NULLS LAST子句进行自定义。
下面是一个简单的例子-通过订购名称的符按降序排列,并把空末S:
Query sortQuery = entityManager.createQuery
("Select f from Foo as f order by f.name desc NULLS LAST");
生成的SQL查询包括null为1 else 0 end子句(第3行):
Hibernate: select foo0_.id as id1_4_, foo0_.BAR_ID as BAR_ID2_4_,
foo0_.bar_Id as bar_Id2_4_, foo0_.name as name3_4_,from Foo foo0_ order
by case when foo0_.name is null then 1 else 0 end, foo0_.name desc
2.4。排序一对多关系
移过基本示例,现在让我们看一个涉及按一对多关系排序实体的用例- 包含Foo实体集合的Bar。
我们想要对Bar实体以及它们的Foo实体集合进行排序- JPA对于此任务特别简单:
1.对集合进行排序:在Bar实体中的Foo集合之前添加OrderBy注释:
@OrderBy("name ASC")
List <Foo> fooList;
2.对集合进行排序:在Bar实体中的Foo集合之前添加OrderBy注释:
String jql = "Select b from Bar as b order by b.id";
Query barQuery = entityManager.createQuery(jql);
List<Bar> barList = barQuery.getResultList();
请注意,@ OrderBy注释是可选的,但我们在这种情况下使用它,因为我们想要对每个Bar的Foo集合进行排序。
让我们看一下发送到RDMS 的SQL查询:
Hibernate: select bar0_.id as id1_0_, bar0_.name as name2_0_ from Bar bar0_ order by bar0_.id
Hibernate:
select foolist0_.BAR_ID as BAR_ID2_0_0_, foolist0_.id as id1_4_0_,
foolist0_.id as id1_4_1_, foolist0_.BAR_ID as BAR_ID2_4_1_,
foolist0_.bar_Id as bar_Id2_4_1_, foolist0_.name as name3_4_1_
from Foo foolist0_
where foolist0_.BAR_ID=? order by foolist0_.name asc
第一个查询对父Bar实体进行排序。生成第二个查询以对属于Bar的子Foo实体的集合进行排序。
3.使用JPA Criteria Query Object API排序
使用JPA Criteria - orderBy方法是设置所有排序参数的“一站式”替代方法:可以设置顺序方向和要排序的属性。以下是方法的API:
- orderBy( CriteriaBuilder.asc):按升序排序。
- orderBy( CriteriaBuilder.desc):按降序排序。
每个Order实例都是使用C riteriaBuilder对象通过其asc或desc方法创建的。
下面是一个简单的例子-分拣FOOS通过他们的名字:
CriteriaQuery<Foo> criteriaQuery = criteriaBuilder.createQuery(Foo.class);
Root<Foo> from = criteriaQuery.from(Foo.class);
CriteriaQuery<Foo> select = criteriaQuery.select(from);
criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name")));
get方法的参数区分大小写,因为它需要匹配属性的名称。
与简单的JQL相反,JPA Criteria Query Object API 强制查询中的显式订单方向。请注意,在此代码段的最后一行中,criteriaBuilder对象通过调用其asc方法指定要升序的排序顺序。
执行上面的代码时,JPA会生成如下所示的SQL查询。JPA Criteria Object生成带有显式asc子句的SQL语句:
Hibernate: select foo0_.id as id1_4_, foo0_.name as name2_4_
from Foo foo0_ order by foo0_.name asc
3.1。按多个属性排序
要按多个属性排序,只需将Order实例传递给orderBy方法,以便对每个要排序的属性进行排序。
这是一个快速示例 - 按名称和ID排序,分别按asc和desc顺序排序:
CriteriaQuery<Foo> criteriaQuery = criteriaBuilder.createQuery(Foo.class);
Root<Foo> from = criteriaQuery.from(Foo.class);
CriteriaQuery<Foo> select = criteriaQuery.select(from);
criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name")),
criteriaBuilder.desc(from.get("id")));
相应的SQL查询如下所示:
Hibernate: select foo0_.id as id1_4_, foo0_.name as name2_4_
from Foo foo0_ order by foo0_.name asc, foo0_.id desc