JPA 条件 API - 分页中具体查询的总记录数



我正在为存储库层中的分页编程功能。函数接收作为参数 spring 的可分页对象和一些值,如下所示:

public Page<Foo> filterFoo(Pageable pageable, String value) {
   CriteriaBuilder cb = entityManager.getCriteriaBuilder();
   CriteriaQuery<Foo> fooQuery = cb.createQuery(Foo.class);
   Root<Foo> foo = fooQuery .from(Foo.class);
   fooQuery .where(adding predicate for match value);
   List<Foo> result = entityManager.createQuery(fooQuery )
      .setFirstResult((pageable.getPageNumber() - 1) * pageable.getPageSize())
      .setMaxResults(pageable.getPageSize())
      .getResultList();
   return new PageImpl<>(result, pageable, xxxx);
}

函数返回弹簧的 PageImpl 对象,填充了我的结果。对于PageImpl,我还需要设置适合谓词的对象总数。当然,这个计数数字必须没有maxResult和firstResult。是否可以使用我的 fooQuery 创建另一个数据库调用以无限制地获取该查询的总数据库记录?在 JPA 中使用可分页和条件 API 的最佳做法是什么?谢谢你的建议。

由于生成的 SQL 使用别名 - 您可能需要单独查询以获取行总数。例如:

CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
countQuery.select(cb.count(countQuery.from(Foo.class)));
if (Objects.nonNull(filters)) {
    countQuery.where(filters);
}
return new PageImpl<>(result, pageable, em.createQuery(countQuery).getSingleResult());

其中filters等于您的adding predicate for match value表达式。

此外,您可以使用带有自定义 SQL 函数的元组查询来计算一个select查询中的行数。喜欢这个:

public class SqlFunctionsMetadataBuilderContributor implements MetadataBuilderContributor {
    @Override
    public void contribute(MetadataBuilder metadataBuilder) {
        metadataBuilder.applySqlFunction(
            "count_over",
            new SQLFunctionTemplate(
                StandardBasicTypes.LONG,
                "(count(?1) over())"
            )
        );
    }
}

和标准:

public Page<Foo> findAll(Specification<Foo> specification, Pageable pageable) {
    CriteriaQuery<Tuple> cq = cb.createTupleQuery();
    Root<Foo.class> fooRoot = cq.from(Foo.class);
    cq.select(cb.tuple(fooRoot, cb.function("count_over", Long.class, fooRoot.get("id"))));
    Predicate filters = specification.toPredicate(fooRoot, cq, cb);
    if (Objects.nonNull(filters)) {
        cq.where(filters);
    }
    TypedQuery<Tuple> query = em.createQuery(cq);
    query.setFirstResult((int) pageable.getOffset());
    query.setMaxResults(pageable.getPageSize());
    List<Tuple> result = query.getResultList();
    if (result.isEmpty()) {
        return new PageImpl<>(List.of());
    }
    return new PageImpl<>(
        result.stream().map(tuple -> (Foo) tuple.get(0)).collect(toUnmodifiableList()),
        pageable,
        (long) result.get(0).get(1)
    );
}

查看有关 SQLFunction 的更多信息:JPA 标准 API 中的 https://vladmihalcea.com/hibernate-sql-function-jpql-criteria-api-query/和用于订单的自定义 SQL

相关内容

  • 没有找到相关文章

最新更新