我陷入了困境。我希望我能在这里找到解决方案。我正在使用分页来显示用户个人资料页面上的一些数据。
使用基本分页:
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
实施,但我再次对此感到困惑。剩余项目将始终取决于pageNo
和perPage
,并且独立于totalResult
(因为总结果在两者之间减少)。我也不能在这里使用最后n行,因为行计数将再次减少移动我想要的结果。
我也不想在方法中保留太多参数。例如 - 假设我在参数中传递toSatrtWith
id并从那里获取perPage
行数,我可能得到所需的东西。但我想要一个更优雅的解决方案。
答案 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)中的任何内容。