滚动是一种更细粒度的方法,用于循环访问更大的结果集块。 滚动包括稳定排序、滚动类型(基于偏移或键集的滚动)和结果限制。 可以使用属性名称定义简单的排序表达式,并通过查询派生使用 TopFirst 关键字定义静态结果限制。 您可以连接表达式以将多个条件收集到一个表达式中。Spring中文文档

滚动查询返回 a,它允许获取元素的滚动位置以提取下一个元素,直到应用程序使用完整个查询结果。 与通过获取下一批结果来使用 Java 类似,查询结果滚动允许您访问 a 到 .Window<T>Window<T>Iterator<List<…>>ScrollPositionWindow.positionAt(…​)Spring中文文档

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());

将元素与整个查询结果标识在一起的确切位置。 查询执行将位置参数视为独占的,结果将在给定位置之后开始。 并作为 a 的特殊化身,指示滚动操作的开始。ScrollPositionScrollPosition#offset()ScrollPosition#keyset()ScrollPositionSpring中文文档

WindowIterator提供了一个实用程序,通过消除检查是否存在下一个并应用 .WindowWindowScrollPositionSpring中文文档

WindowIterator<User> users = WindowIterator.of(position -> repository.findFirst10ByLastnameOrderByFirstname("Doe", position))
  .startingAt(ScrollPosition.offset());

while (users.hasNext()) {
  User u = users.next();
  // consume the user
}

将元素与整个查询结果标识在一起的确切位置。 查询执行将位置参数视为独占的,结果将在给定位置之后开始。 并作为 a 的特殊化身,指示滚动操作的开始。ScrollPositionScrollPosition#offset()ScrollPosition#keyset()ScrollPositionSpring中文文档

使用偏移量滚动

偏移滚动使用类似于分页的偏移计数器来跳过多个结果,并让数据源仅返回从给定偏移量开始的结果。 这种简单的机制可避免将大量结果发送到客户端应用程序。 但是,大多数数据库需要具体化完整的查询结果,然后服务器才能返回结果。Spring中文文档

例 1.与存储库查询方法一起使用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

和 之间是有区别的。 前者指示滚动操作的开始,指向没有特定的偏移量,而后者标识结果的第一个元素(在位置)。 鉴于滚动的排他性,using 跳过第一个元素并转换为 的偏移量。ScollPosition.offset()ScollPosition.offset(0L)0ScollPosition.offset(0)1Spring中文文档

1 从无偏移量开始,将元素包含在位置 。0

和 之间是有区别的。 前者指示滚动操作的开始,指向没有特定的偏移量,而后者标识结果的第一个元素(在位置)。 鉴于滚动的排他性,using 跳过第一个元素并转换为 的偏移量。ScollPosition.offset()ScollPosition.offset(0L)0ScollPosition.offset(0)1Spring中文文档

使用键集筛选进行滚动

基于偏移量要求大多数数据库需要具体化整个结果,然后服务器才能返回结果。 因此,虽然客户端只能看到请求结果的部分,但您的服务器需要构建完整的结果,这会导致额外的负载。Spring中文文档

Keyset-Filtering 通过利用数据库的内置功能来检索结果子集,旨在减少单个查询的计算和 I/O 要求。 此方法维护一组键,通过将键传递到查询中来恢复滚动,从而有效地修改筛选条件。Spring中文文档

Keyset-Filtering 的核心思想是使用稳定的排序顺序开始检索结果。 一旦要滚动到下一个块,您将获得一个用于重建排序结果中的位置。 捕获当前 . 若要运行查询,重建将重写 criteria 子句以包含所有排序字段和主键,以便数据库可以利用潜在索引来运行查询。 数据库只需要从给定的键集位置构造一个小得多的结果,而不需要完全实现一个大的结果,然后跳过结果直到达到特定的偏移量。ScrollPositionScrollPositionWindowSpring中文文档

键集筛选要求键集属性(用于排序的属性)为非空值。 由于比较运算符的存储特定值处理以及需要对索引源运行查询,因此适用此限制。 对可为 null 的属性进行键集筛选将导致意外结果。nullSpring中文文档

与存储库查询方法一起使用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 从头开始,不要应用额外的筛选。

当数据库包含与排序字段匹配的索引时,键集筛选效果最佳,因此静态排序效果很好。 应用键集筛选的滚动查询需要查询返回的排序顺序中使用的属性,并且这些属性必须映射到返回的实体中。Spring中文文档

您可以使用接口和 DTO 投影,但请确保包含已排序的所有属性,以避免键集提取失败。Spring中文文档

指定订单时,包含与查询相关的排序属性就足够了; 如果不想,则无需确保查询结果的唯一性。 键集查询机制通过包含主键(或复合主键的任何剩余部分)来修改排序顺序,以确保每个查询结果都是唯一的。SortSpring中文文档

键集筛选要求键集属性(用于排序的属性)为非空值。 由于比较运算符的存储特定值处理以及需要对索引源运行查询,因此适用此限制。 对可为 null 的属性进行键集筛选将导致意外结果。nullSpring中文文档

1 从头开始,不要应用额外的筛选。