1. 简介
在本篇文章中,我们将学习如何使用 Spring Data 对查询结果进行排序。
首先会介绍我们要操作的数据结构,然后深入探讨几种常见的排序方式。如果你已经熟悉 Spring Data 的基本用法,那么可以直接跳到排序部分。
2. 测试数据
我们准备了如下乘客座位表作为测试数据(虽然这里以表格形式展示,但你可以使用任何 Spring Data 支持的数据库来持久化这些数据):
First Name | Last Name | Seat Number |
---|---|---|
Jill | Smith | 50 |
Eve | Jackson | 94 |
Fred | Bloggs | 22 |
Ricki | Bobbie | 36 |
Siya | Kolisi | 85 |
我们要解决的问题是:“谁坐在哪个座位?”为了便于查看,我们会按照座位号升序排列。
3. 领域模型
要创建一个 Spring Data Repository,我们需要定义一个领域类和 ID 类型。
下面是一个基于 JPA 的 Passenger
实体类示例:
@Entity
class Passenger {
@Id
@GeneratedValue
@Column(nullable = false)
private Long id;
@Basic(optional = false)
@Column(nullable = false)
private String firstName;
@Basic(optional = false)
@Column(nullable = false)
private String lastName;
@Basic(optional = false)
@Column(nullable = false)
private int seatNumber;
// constructor, getters etc.
}
当然,你也可以将其建模为 MongoDB 文档或其他持久化模型。
4. 使用 Spring Data 排序
Spring Data 提供了几种灵活的方式来对查询结果进行排序。
4.1. 使用 OrderBy 方法关键字排序 ✅
第一种方式是利用 Spring Data 的方法派生机制,即通过方法名自动生成查询语句。
✅ 只需要在方法名中加入 OrderBy
关键字,并指定字段及排序方向(Asc 或 Desc)即可实现排序。
例如,我们可以创建一个方法,返回按座位号升序排列的所有乘客:
interface PassengerRepository extends JpaRepository<Passenger, Long> {
List<Passenger> findByOrderBySeatNumberAsc();
}
⚠️ 这个方法可以与其它查询条件组合使用。
比如,我们要查找指定姓氏的乘客,并按座位号升序排列:
List<Passenger> findByLastNameOrderBySeatNumberAsc(String lastName);
这种方式简单粗暴,适合固定排序规则的场景。
4.2. 使用 Sort 参数排序 ✅
第二种方式是在调用 Repository 方法时传入一个 Sort
对象,显式指定排序字段和方向。
例如,使用 findAll()
方法配合 Sort 参数:
List<Passenger> passengers = repository.findAll(Sort.by(Sort.Direction.ASC, "seatNumber"));
也可以将 Sort 作为一个参数添加到自定义方法中:
List<Passenger> findByLastName(String lastName, Sort sort);
此外,在分页查询中同样支持排序,只需将 Sort 包装进 Pageable
对象即可:
Page<Passenger> page = repository.findAll(PageRequest.of(0, 1, Sort.by(Sort.Direction.ASC, "seatNumber")));
这种方式更灵活,适用于动态排序需求。
5. 总结
总的来说,Spring Data 提供了两种主流的排序方式:
- ✅ 使用
OrderBy
关键字进行方法派生排序 - ✅ 通过
Sort
对象作为方法参数控制排序逻辑
两种方式各有优势:前者适合静态排序规则,后者更适合运行时动态排序。
📌 本文代码示例可从 GitHub 获取:https://github.com/eugenp/tutorials/tree/master/persistence-modules/spring-data-jpa-query
📌 小贴士:不要把
OrderBy
和Sort
混淆使用。前者是编译期确定的排序规则,后者是运行期动态指定的。根据业务场景选择合适的方式,避免踩坑。