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

时间:2015-02-26 06:53:58

标签: java mysql hibernate pagination

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

使用基本分页:

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

页面类构造函数:

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;
}

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

让我们了解情况。假设有totalResults - 17,perPage - 6和totalPages - 3。

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

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

我正在考虑将其作为remainingItems实施,但我再次对此感到困惑。剩余项目将始终取决于pageNoperPage,并且独立于totalResult(因为总结果在两者之间减少)。我也不能在这里使用最后n行,因为行计数将再次减少移动我想要的结果。

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

2 个答案:

答案 0 :(得分:10)

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

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

[Next]的网址将包含此页面上最后一项的id,然后在构建下一页时使用WHERE id > $id。 (或者id关闭此页面的第一项,然后是WHERE id >= $id。当在两者之间插入一行时,这种微小的差异会产生轻微的影响。)在SQL中也有这个:{{1} }。无论哪个页面,它都只能获取10行。如果没有这个技巧,您将获取当前页面之前所有页面的所有行。

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

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

[Last]可以包含Last或ORDER BY id DESC LIMIT 10或其他的标志 - 然后在SQL中使用类似id=-1的内容。

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

答案 1 :(得分:1)

我遇到了完全相同的问题。

我的解决方案是按相反的顺序处理每个页面,即我从最后一页开始,然后从倒数第二个一直到第一页。这样,即使我删除N + 1页中的某些行,也不会更改N页(或N-1,N-2,..,1)中的任何内容。