7

对于分页数据(分页),我需要返回符合我的条件的记录总数和结果第一页。这对于向用户显示信息和计算期望的页面总数(在客户端上)很有用。

目前我两次运行相同的查询,一次用于总计数,一次用于实际记录。我希望有一个更有效的方法。

可以将这两个查询组合为对数据库的一次调用吗?

计数:

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Long> cq = cb.createQuery(Long.class);
    Root<VersionJpa> r = cq.from(VersionJpa.class);
    Predicate p = cb.conjunction();
    p = // some filtering code define by caller
    cq.where(p);
    cq.select(cb.count(r));
    TypedQuery<Long> tq = em.createQuery(cq);
    return tq.getSingleResult().intValue();

这页纸:

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<VersionJpa> cq = cb.createQuery(VersionJpa.class);
    Root<VersionJpa> root = cq.from(VersionJpa.class);
    Predicate p = cb.conjunction();
    p = // same filtering code as in the count above
    cq.where(p);
    TypedQuery<VersionJpa> tq = em.createQuery(cq);
    // paginatong
    tq.setFirstResults(first); // from caller
    tq.setMaxResults(max);     // from caller
    return tq.getResultList();
4

1 回答 1

2

即使假设存在一个检索记录计数和分页记录本身的有效查询,您也需要为用户访问的每个页面执行额外的数据库调用。这将使访问第一页期间获得的性能增益可以忽略不计。

我的意思是:要访问第一页,您需要:

  1. 没有分页的过滤项目的总数
  2. 具有第 1 页分页的过滤项目

要访问其他页面,您不再需要计数查询。您只需要第 x 页的过滤项目。

展开 n 个页面后,即使使用您正在寻找的优化,您也会执行 n 次调用,而不是未优化版本的 n+1 次调用。所以,我不会花太多时间考虑这个问题。

在您的实现中,您只需要小心,在不需要时不要执行记录计数:仅在用户更改过滤后才需要它。

于 2013-07-29T07:41:40.077 回答