当用户操作可以删除两者之间的行时,如何处理数据库分页?

2022-09-03 14:15:04

我陷入了困境。我希望我在这里得到一个解决方案。我正在使用分页在用户配置文件页面上显示一些数据。

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

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

现在,如果结果正常显示而不在两者之间进行任何删除,则可以正常工作。但用户可以从其操作列表中删除项目。

让我们来看看情况。假设有 - 17,- 6和 - 3。totalResultsperPagetotalPages

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

我希望情况是清楚的。现在不需要这种中间移位。

我正在考虑实现它,但我再次对此感到困惑。剩余项目将始终依赖于 和 和 独立于 (因为总结果在两者之间会减少)。我不能在这里使用最后n行,因为行计数将再次减少,改变我想要的结果。remainingItemspageNoperPagetotalResult

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


答案 1

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

长答案:请参阅我的博客,了解为什么“通过限制和偏移进行分页是邪恶的”:http://mysql.rjweb.org/doc.php/pagination。(您正在执行PHP等效于使用LIMIT和OFFSET,因此博客适用。

[Next] 的 url 将包含此页面上最后一项的 url,然后在构建下一页时使用。(或此页面外的第一项,然后.当在两者之间插入一行时,这种微小的差异会产生很小的影响。在 SQL 中也有这个:.无论哪个页面,它都只会读取 10 行。如果没有此技巧,您将获取当前页面之前所有页面的所有行。idWHERE id > $ididWHERE id >= $idORDER BY id ASC LIMIT 10

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

[首先]最好不指定id;然后代码会说“哦,我应该构建第一页。

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

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


答案 2

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

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