具有返回分页结果的典型方法,使用CriteriaBuilder
并执行2个查询:
- 一个计算结果总数的查询
- 另一个为指定页面获取子集的查询
我们注意到第一个查询,JPA根本没有进行优化,因为它正在使用exists(来自Oracle)。
Java代码:
Root<Foo> from = criteriaQuery.from(Foo.class);
//... predicates
CriteriaQuery<Long> countQuery = criteriaBuilder.createQuery(Long.class)
.select(criteriaBuilder.countDistinct(from))
.where(predicates.toArray(new Predicate[predicates.size()]));
Long numberResults = entityManager.createQuery(countQuery).getSingleResult();
SQL 生成的查询:
SELECT COUNT(t0.REFERENCE)
FROM foo t0
WHERE EXISTS (
SELECT t1.REFERENCE
FROM foo t1
WHERE ((((t0.REFERENCE = t1.REFERENCE) AND (t0.VERSION_NUM = t1.VERSION_NUM)) AND (t0.ISSUER = t1.ISSUER)) AND (t1.REFERENCE LIKE ? AND (t1.VERSION_STATUS = ?)))
);
我该如何避免使用exists
?Java代码有什么问题吗?
select count(*), count(case when <your conditions> then 1 end) from <your table>;
可能是你想要的。不过我不知道你如何在你的java/jpa/任何代码中生成它。 - BoneistcountDistinct()
是多余的。只用count()
,仍然会给我一个与 EXISTS 相同的查询。 - anat0lius//... predicates
部分。此外,exists
运算符对我来说似乎是标准 SQL 而不是 Oracle 特有的。你认为查询没有被优化吗?如果有的话,查询中似乎有一堆不必要的()
,因为你使用了AND
而没有用到OR
。虽然我不是很精通 SQL,但我认为这个查询SELECT COUNT(t0.REFERENCE) FROM foo t0 WHERE t0.REFERENCE LIKE ? AND t0.VERSION_STATUS = ?
应该与你的查询达到相同的效果。 - XtremeBaumer