如果用户操作可以删除其间的一行,如何处理数据库分页?

Nih*_*rma 9 java mysql pagination hibernate

我陷入困境.我希望我能在这里找到解决方案.我正在使用分页来显示用户个人资料页面上的一些数据.

使用基本分页来执行此操作:

public Page list(Query query, int pageNo, int perPage) {

    int totalResults = query.list().size();

    int firstResult = (pageNo - 1) * perPage;
    query.setFirstResult(firstResult);
    query.setMaxResults(perPage);
    List resultList = query.list();
    return new Page(resultList, perPage, pageNo, totalResults);
}
Run Code Online (Sandbox Code Playgroud)

页面类构造函数:

public Page(List resultList, int pageSize, int page, int totalResults)   {
    this.resultList = resultList;
    this.pageSize = pageSize;
    this.page = page;
    this.totalResults = totalResults;
    this.totalPages = (totalResults - 1) / pageSize + 1;
}
Run Code Online (Sandbox Code Playgroud)

现在,如果结果在哪里正常显示而没有任何删除,这将是正常的.但是用户可以从他的动作列表中删除项目.

让我们有这种情况.说有totalResults- 17,perPage- 6和totalPages- 3.

现在在第一页中,他删除了2个项目,总共有15个结果,而第2页面中的行ID已经转移到9而不是7(因为两个项目没有,总结果现在是15).

我希望情况很清楚.现在不需要这种中间换档.

我正在考虑实施它,remainingItems但我再次对此感到困惑.剩余的项将始终依赖于pageNoperPage和独立于的totalResult(因为总结果在之间被减小).我也不能在这里使用最后n行,因为行计数将再次减少移动我想要的结果.

我也不想在方法中保留太多参数.例如 - 假设我toSatrtWith在参数中传递id并perPage从那里获取行数,我可能得到所需的东西.但我想要一个更优雅的解决方案.

Ric*_*mes 11

简短回答:记住"你离开的地方",而不是计算位置.

答案很长:请参阅我的博客,了解为什么"通过LIMIT和OFFSET的分页是邪恶的":http: //mysql.rjweb.org/doc.php/pagination.(您正在使用与使用LIMIT和OFFSET相当的PHP,因此该博客适用.)

[Next]的url将包含id此页面上的最后一项,然后WHERE id > $id在构建下一页时使用.(或者id关闭这个页面的第一个项目,那么WHERE id >= $id,这种细微的差别有一行时,插入两者之间的影响很小.)也有这种在SQL: ORDER BY id ASC LIMIT 10.无论哪个页面,它都只能获取10行.如果没有这个技巧,您将获取当前页面之前所有页面的所有行.

[上一页]页面类似,但有一个标志说要倒退(ORDER BY id DESC LIMIT 10).

[第一]可能最好通过不指定id来完成; 然后代码会说"哦,我应该建立第一页."

[Last]可以包含Last id=-1或者其他的标志- 然后使用类似ORDER BY id DESC LIMIT 10SQL的东西.

如果没有这种技术,在当前页面之前删除或插入的行会导致列表被一个项目(向前或向后)移开,因此,用户错过(坏?)一行或获取一行重复(只是烦人) ).

  • @Muklas - 使用“OFFSET”会导致微妙的错误。如果您位于第 3 页,每页 10 行,则该页“之前”有 20 行。如果向后插入一行,则现在有 21 行。使用“OFFSET”,[Prev] 将请求第 21-30 行,跳过一行。使用“返回 10 行”,您将得到 22-31 并且不会跳过任何行。ETC。 (2认同)