我正在为存储库层中的分页编程功能。函数接收作为参数 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