java - 如何通过nextPageToken实现分页?

标签 java sql spring pagination token

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

我有 table :

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

所以我有实体类别:

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

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

假设我有 Controller :

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

服务:

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

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

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

最佳答案

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

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

我在 700k 记录上使用了 Page 对象,与 70k 记录相比,速度变化不到一秒。基于此,除非您计划使用庞大的数据集,否则我认为删除偏移量不会增加大量值(value)。我刚刚测试了我用可分页功能制作的新系统,它在 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 那样的系统。

如果您绝对想要使用搜索/按键样式分页,这里有一个很好的信息页面: https://blog.jooq.org/2013/10/26/faster-sql-paging-with-jooq-using-the-seek-method/

一般来说,您正在寻找的是使用 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;
}

然后像这样使用它:

DSL.using(configuration)
   .select(PLAYERS.PLAYER_ID,
           PLAYERS.FIRST_NAME,
           PLAYERS.LAST_NAME,
           PLAYERS.SCORE)
   .from(PLAYERS)
   .where(PLAYERS.GAME_ID.eq(42))
   .orderBy(PLAYERS.SCORE.desc(),
            PLAYERS.PLAYER_ID.asc())
   .seek(949, 15) // (!)
   .limit(10)
   .fetch();

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

关于java - 如何通过nextPageToken实现分页?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60571871/

相关文章:

java - 使用 f.delete() 方法删除现有文件

java - 用于 Java 应用程序的 Amazon Kinesis Data Analytics : Avro issue in deserialization incoming messages

java - 获取两个像素之间的所有像素

c# - 如何格式化存储过程以映射 EF 对象和自定义数据

spring - 无法在测试类中导入 applicationContext

具有值的变量的 java.lang.NullPointerException (Eclipse)

mysql - MySQL 查询速度非常慢

java - Spring data mongoDB 数据库连接的惰性配置

spring - <jaxrs :client> not getting autowired

sql - 收到此错误 "first argument is not an open RODBC channel"