JPA 2 CriteriaQuery, using a limit

我正在使用 JPA 2。出于安全原因,我使用 CriteriaQuery 的类型安全工作(因此,我不搜索任何类型化查询的解决方案等等)。

我最近遇到了一个问题,需要设置 SQL-LIMIT。

经过大量的寻找,我仍然没有找到一个成功的解决方案。

CriteriaQuery<Product> query = getEntityManager().getCriteriaBuilder().createQuery(Product.class);
Root<Product> product = query.from(Product.class);
query.select(product);


return em.createQuery(query).getResultList();

Can anyone help me?

104474 次浏览

质疑上定义 限制偏移:

return em.createQuery(query)
.setFirstResult(offset) // offset
.setMaxResults(limit) // limit
.getResultList();

根据文件:

TypedQuerysetFirstResult (int startPosition)

设置要检索的第一个结果的位置。参数: startPosition -第一个结果的位置,从0开始编号

TypedQuery setMaxResults (int maxResult)

Set the maximum number of results to retrieve.

为了完整起见,我想回答关于 JPA Criteria API 的最初问题。

首先 ,您可以根据用例事先说明何时使用 JPQL 以及何时使用 Criteria API。在 ObjectDB 文档的网站上有一篇很好的文章说:

使用标准 API 的一个主要优点是可以在编译期间而不是运行时更早地检测到错误。另一方面,对于许多开发人员来说,基于字符串的 JPQL 查询(与 SQL 查询非常相似)更容易使用和理解。

I recommend this article in general because it describes concisely how to use the JPA Criteria API. There is a similar article about the 查询 API.

回到问题 :

CriteriaQuery提供了一组限制,例如,可以通过使用 where()方法访问这些限制。正如你可能直觉地猜测的那样: 你不能用这样的限制将查询限制在一个特定数量的结果上——除非你有一个像限制唯一标识符这样的小例子(这会使 Criteria API 的使用过时)。简单地解释一下: 限制不是一个标准,因此不包括在该 api 中。更多细节参见旧的但是金色的 Java EE 文档

Solution

However, you can of course use your CriteriaQuery object as a foundation for a JPQL query. So first, you create your CriteriaQuery as is:

CriteriaQuery<Product> criteriaQuery =
getEntityManager().getCriteriaBuilder().createQuery(Product.class);
Root<Product> product = criteriaQuery.from(Product.class);
criteriaQuery.select(product);

Then use the JPA Query constructor for CriteriaQuery objects:

Query limitedCriteriaQuery = getEntityManager().createQuery(criteriaQuery)
.setMaxResults(resultLimit); // this is the important part
return limitedCriteriaQuery.getResultList();

根据文档和提供的文章,这基本上就是您应该如何使用这两种 API 的方式。

或者,使用 getResultStream ()而不是 getResultList ()。

instead of return em.createQuery(query).getResultList();

Do (“ ...”代表程序中有意义的内容)

    List< ... > resultL = new ArrayList<>();
try (Stream< ... > qrs =
em.createQuery(query).getResultStream()) {
qrs.forEach((rslt) -> {
resultL.add(rslt);
throw new RuntimeException(
"not a prob, just stop after 1");
});
} catch (RuntimeException rte) {
/* suppress propagation */ }
return resultL;