Java 如何使用游标实现Hibernate分页(这样,即使在分页的表中添加了新数据,结果仍然保持一致)?

Java 如何使用游标实现Hibernate分页(这样,即使在分页的表中添加了新数据,结果仍然保持一致)?,java,hibernate,pagination,cursor,Java,Hibernate,Pagination,Cursor,有没有办法在web请求之间使用Hibernate来维护数据库游标?基本上,我试图实现分页,但被分页的数据一直在变化(即,新记录被添加到数据库中)。我们正在尝试将其设置为,当您进行初始搜索(最多返回5000个结果)并翻阅结果时,这些相同的记录始终显示在同一页上(即,我们不会在每次单击“下一页”和“上一页”按钮时连续运行查询)。我们目前实现这一点的方法是,只需从正在分页的表中选择5000(最多)个主键,将这些键存储在内存中,然后一次只使用20个主键从数据库中获取它们的详细信息。但是,我们希望不必将这

有没有办法在web请求之间使用Hibernate来维护数据库游标?基本上,我试图实现分页,但被分页的数据一直在变化(即,新记录被添加到数据库中)。我们正在尝试将其设置为,当您进行初始搜索(最多返回5000个结果)并翻阅结果时,这些相同的记录始终显示在同一页上(即,我们不会在每次单击“下一页”和“上一页”按钮时连续运行查询)。我们目前实现这一点的方法是,只需从正在分页的表中选择5000(最多)个主键,将这些键存储在内存中,然后一次只使用20个主键从数据库中获取它们的详细信息。但是,我们希望不必将这些键存储在内存中,而更希望使用一个数据库游标,我们只需不断返回并在游标上前后移动即可生成页面


我尝试使用Hibernate的ScrollableResults执行此操作,但发现无法调用next()和previous()之类的方法,如果您在不同的web请求/Hibernate会话中,则会导致异常(这并不奇怪)。有没有办法将ScrollableResults对象重新附加到会话,就像重新附加分离的数据库对象使其持久化一样?有没有其他方法可以在不缓存主键的情况下使用一致的分页结果来实现此数据分页?

基本上这是您自己的事情。您要做的是查看OpenSessionInView过滤器并构建自己的过滤器,这样您就可以从与用户的web会话相关联的缓存中提取一个HibernateSession,而不是为每个请求创建一个新的HibernateSession


如果您没有像SpringWebflow这样的框架来提供一些对话结构,那么您也需要构建它。由于您可能希望在“web会话过期”之后以某种方式管理该Hibernate会话的生命周期。您也很可能不希望来自同一web会话但不同浏览器选项卡的两个用户线程共享一个Hibernate会话。(笑声很可能随之而来。)

永远不要使用偏移量,因为偏移量还会读取偏移量之前的所有数据,这是非常低效的

您需要按索引的唯一属性排序,并在API调用中返回最后一个item属性的值,并使用
WHERE
子句从您离开的地方开始。最后一项的属性值将是光标位置。例如,使用主键
id
作为光标的简单分页查询如下:

List<MyEntity> entities = entityManager
    .createQuery("""
        FROM
            MyEntity e
        WHERE
            e.id > :cursorPosition
        ORDER BY
            e.id ASC
    """, MyEntity.class)
    .setParameter("cursorPosition", cursorPosition)
    .setMaxResults(pageSize)
    .getResultList()
{
    "items": [ ... ],
    "nextPageToken": "aW5kZXhQcm9wZXJ0eT1pZCZjdXJzb3JQb3M9MTIzJmFnZUJpZ2dlclRoYW49NjU="
}
您的api调用将返回如下json:

List<MyEntity> entities = entityManager
    .createQuery("""
        FROM
            MyEntity e
        WHERE
            e.id > :cursorPosition
        ORDER BY
            e.id ASC
    """, MyEntity.class)
    .setParameter("cursorPosition", cursorPosition)
    .setMaxResults(pageSize)
    .getResultList()
{
    "items": [ ... ],
    "nextPageToken": "aW5kZXhQcm9wZXJ0eT1pZCZjdXJzb3JQb3M9MTIzJmFnZUJpZ2dlclRoYW49NjU="
}
客户端的下一个呼叫:

GET https://www.example.com/api/myservice/v1/myentity?pageToken=aW5kZXhQcm9wZXJ0eT1pZCZjdXJzb3JQb3M9MTIzJmFnZUJpZ2dlclRoYW49NjU=

连接和拆分光标字符串的部分可能很烦人,我真的不知道是否有一个库来处理创建标记和解析它的工作,我实际上在这个问题上,因为我一直在寻找它。但我猜GSON或Jackson可以为您节省这方面的代码行。

您解决了这个问题吗?我正在构建一个GraphQLAPI,它使用游标进行分页,因此偏移量/限制不合适。老实说,我不记得了。多年来我接触过Java。