对于最新的稳定版本,请使用 Spring Data Commons 3.3.4! |
对于最新的稳定版本,请使用 Spring Data Commons 3.3.4! |
滚动是一种更精细的方法,用于迭代较大的结果集块。
滚动包括稳定排序、滚动类型(基于 Offset 或 Keyset 的滚动)和结果限制。
您可以使用属性名称定义简单的排序表达式,并通过查询派生使用 Top
或 First
关键字定义静态结果限制。
您可以连接表达式以将多个条件收集到一个表达式中。
滚动查询返回 a,该请求允许获取滚动位置以恢复获取下一个滚动位置,直到您的应用程序使用完整个查询结果。
与通过获取下一批结果来使用 Java 类似,查询结果滚动允许您访问 a 到 。Window<T>
Window<T>
Iterator<List<…>>
ScrollPosition
Window.positionAt(…)
Window<User> users = repository.findFirst10ByLastnameOrderByFirstname("Doe", ScrollPosition.offset());
do {
for (User u : users) {
// consume the user
}
// obtain the next Scroll
users = repository.findFirst10ByLastnameOrderByFirstname("Doe", users.positionAt(users.size() - 1));
} while (!users.isEmpty() && users.hasNext());
WindowIterator
提供了一个实用程序,通过消除检查是否存在 next 并应用 .Window
Window
ScrollPosition
WindowIterator<User> users = WindowIterator.of(position -> repository.findFirst10ByLastnameOrderByFirstname("Doe", position))
.startingAt(OffsetScrollPosition.initial());
while (users.hasNext()) {
User u = users.next();
// consume the user
}
使用 Offset 滚动
偏移滚动使用类似于分页的 Offset 计数器来跳过许多结果,并让数据源仅返回从给定 Offset 开始的结果。 这种简单的机制可避免将大型结果发送到客户端应用程序。 但是,大多数数据库都需要在服务器返回结果之前具体化完整的查询结果。
OffsetScrollPosition
interface UserRepository extends Repository<User, Long> {
Window<User> findFirst10ByLastnameOrderByFirstname(String lastname, OffsetScrollPosition position);
}
WindowIterator<User> users = WindowIterator.of(position -> repository.findFirst10ByLastnameOrderByFirstname("Doe", position))
.startingAt(OffsetScrollPosition.initial()); (1)
1 | 从位置 的初始偏移量 开始。0 |
1 | 从位置 的初始偏移量 开始。0 |
使用 Keyset-Filtering 进行滚动
基于偏移量要求大多数数据库需要先具体化整个结果,然后服务器才能返回结果。 因此,虽然客户端只能看到请求结果的部分,但您的服务器需要构建完整的结果,这会导致额外的负载。
Keyset-Filtering 方法通过利用数据库的内置功能来生成子集检索,旨在减少单个查询的计算和 I/O 要求。 此方法通过将键传递到查询中来维护一组键以恢复滚动,从而有效地修改筛选条件。
Keyset-Filtering 的核心思想是使用稳定的排序顺序开始检索结果。
一旦你想滚动到下一个块,你就会得到一个,用于重建排序结果中的位置。
捕获当前 .
为了运行查询,重建会重写 criteria 子句以包含所有排序字段和主键,以便数据库可以利用潜在索引来运行查询。
数据库只需要从给定的键集位置构造一个小得多的结果,而无需完全实现一个大的结果,然后跳过结果直到达到特定的偏移量。ScrollPosition
ScrollPosition
Window
Keyset-Filtering 要求键集属性(用于排序的属性)不可为空。
由于比较运算符的存储特定值处理以及需要对索引源运行查询,因此存在此限制。
对可为 null 的属性进行 Keyset-Filtering 将导致意外结果。 |
KeysetScrollPosition
interface UserRepository extends Repository<User, Long> {
Window<User> findFirst10ByLastnameOrderByFirstname(String lastname, KeysetScrollPosition position);
}
WindowIterator<User> users = WindowIterator.of(position -> repository.findFirst10ByLastnameOrderByFirstname("Doe", position))
.startingAt(ScrollPosition.keyset()); (1)
1 | 从头开始,不要应用其他筛选。 |
当您的数据库包含与排序字段匹配的索引时,Keyset-Filtering 效果最佳,因此静态排序效果很好。 应用 Keyset-Filtering 的滚动查询需要查询返回的排序顺序中使用的属性,并且这些属性必须映射到返回的实体中。
您可以使用接口和 DTO 投影,但请确保包含您排序所依据的所有属性,以避免键集提取失败。
指定顺序时,包含与查询相关的排序属性就足够了;
如果您不想,则无需确保查询结果唯一。
键集查询机制通过包含主键(或复合主键的任何剩余部分)来修改排序顺序,以确保每个查询结果都是唯一的。Sort
Keyset-Filtering 要求键集属性(用于排序的属性)不可为空。
由于比较运算符的存储特定值处理以及需要对索引源运行查询,因此存在此限制。
对可为 null 的属性进行 Keyset-Filtering 将导致意外结果。 |
1 | 从头开始,不要应用其他筛选。 |