如何通过nextPageToken实现分页?

and*_*w17 3 java sql spring pagination token

我正在尝试使用 nextPageToken 实现分页。

我有表:

CREATE TABLE IF NOT EXISTS categories
(
    id        BIGINT PRIMARY KEY,
    name      VARCHAR(30) NOT NULL,
    parent_id BIGINT REFERENCES categories (id)
);
Run Code Online (Sandbox Code Playgroud)

所以我有实体类别:

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;
    @Column(name = "name")
    private String name;
    @OneToOne
    @JoinColumn(name = "parent_id", referencedColumnName = "id")
    private Category category;
Run Code Online (Sandbox Code Playgroud)

我真的不明白我接下来要做什么。客户端请求令牌(保留什么?)

假设我有控制器:

@GetMapping
    public ResponseEntity<CategoriesTokenResponse> getCategories(
            @RequestParam String nextPageToken
    ) {
        return ResponseEntity.ok(categoryService.getCategories(nextPageToken));
    }
Run Code Online (Sandbox Code Playgroud)

服务:

public CategoriesTokenResponse getCategories(String nextPageToken) {
        return new CategoriesTokenResponse(categoryDtoList, "myToken");
    }
Run Code Online (Sandbox Code Playgroud)
@Data
@AllArgsConstructor
public class CategoriesTokenResponse {
    private final List<CategoryDto> categories;
    private final String token;
}
Run Code Online (Sandbox Code Playgroud)

我必须如何实现 sql 查询呢?我如何为每个 id 生成 nextPagetoken?

SELECT * FROM categories WHERE parent_id = what?
AND max(category id from previous page = token?)
ORDER BY id LIMIT 20;
Run Code Online (Sandbox Code Playgroud)

Nox*_*Nox 6

首先,您需要了解您在这里处理的是什么。每个实现都有某种限制或效率低下。例如,使用这样的页面标记仅适用于无限滚动页面。您无法跳转到任何特定页面。因此,如果我的浏览器崩溃并且我在第 100 页,我必须再次滚动浏览 100 页。对于海量数据集来说,它确实更快,但是如果您需要访问所有页面,这还有关系吗?或者如果您一开始就限制回报?比如只获取前30页?

基本上决定这一点:您是否只关心前几页,因为搜索/排序始终在使用?(就像用户从不使用超过 google 的前 1-5 页一样)该数据集很大吗?然后是很棒的用例。用户是否会选择“过去 6 个月内的所有项目”并且实际上需要所有这些项目,还是排序/搜索很弱?或者,您会返回所有页面而不限制最大返回 30 页吗?或者,开发速度比 0.1-3 秒(取决于数据大小)的速度提升更重要吗?然后使用内置的 JPA 页面对象。

我在 700k 记录上使用了 Page 对象,与 70k 记录相比,速度变化不到一秒。基于此,除非您计划使用庞大的数据集,否则我认为删除偏移量不会增加大量价值。我刚刚测试了我用可分页功能制作的新系统,它在 84 毫秒内返回第 1 页上的 10 个项目,没有页面限制器,可从我家通过 VPN 进入我的工作网络,记录 27k 条记录。一个包含超过 500k 条记录的表花费了 131 毫秒,这相当快了。想让它更快吗?强制总共最多返回 30 页,每页最多返回 100 个结果,因为通常情况下,他们不需要该表中的所有数据。他们想要别的东西吗?细化搜索。该寻呼与寻道/按键类型寻呼之间的速度差异不到一秒。这也是假设一个普通的 SQL 数据库。NoSQL 在这里有点不同。Baeldung 有大量关于 jpa 分页的文章,如下所示:https ://www.baeldung.com/rest-api-pagination-in-spring

JPA Paging 的学习和实施时间不会超过 30 分钟,它非常简单,并且在 JPA 存储库中提供。我强烈建议在搜索/按键样式分页上使用它,因为您可能没有构建像谷歌或 Facebook 那样的系统。

如果您绝对想使用seek/key样式分页,这里有一个很好的信息页面:https: //blog.jooq.org/2013/10/26/faster-sql-paging-with-jooq-using-the-寻找方法/

一般来说,您正在寻找的是使用 JOOQ 和 spring。这里的实现示例: https ://docs.spring.io/spring-boot/docs/1.3.5.RELEASE/reference/html/boot-features-jooq.html

基本上,创建一个 DSL 上下文:

private final DSLContext DSL;

@Autowired
public JooqExample(DSLContext dslContext) {
    this.DSL= dslContext;
}
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它:

private final DSLContext DSL;

@Autowired
public JooqExample(DSLContext dslContext) {
    this.DSL= dslContext;
}
Run Code Online (Sandbox Code Playgroud)

无需显式地表述查找谓词,只需传递前一个查询中的最后一条记录,jOOQ 将看到在给定 ORDER BY 子句的情况下,跳过该记录之前的所有记录(包括该记录)。

  • 当我制作第一个 api 时,我对这个主题做了很多研究,因为它是针对每年获取 160 万条记录的系统的。另外,我建议阅读有关链接标题的内容。我讨厌容器,所以不用容器来保存对象数据,而是在链接头中返回第一个、最后一个、下一个、上一个,而主体可以只保存对象数据。我也不使用 hatoas,除非它也是一个大系统。除非你有大量的消费者或不断变化的系统,否则它毫无用处。 (2认同)