簡體   English   中英

JPA 標准 API:select 來自子查詢的計數(*),用於分頁實現

[英]JPA Criteria API: select count(*) from subquery with joins and group by for pagination implementation

我想在從數據庫返回的產品列表中實現分頁功能。 所以我需要知道查詢的總結果。

數據庫表是:

PRODUCT TABLE             
-----------------------------
ID             NAME
-------------- --------------
1              Product 1
2              Product 2

PRODUCT SUPPLIER TABLE
--------------------------------------------
ID             PRODUCT ID     PRICE
-------------- -------------- --------------
1              1              35
2              1              30
3              2              70
4              2              75

期望的結果是不同供應商的最低價格的產品列表。

Product 1    30
Product 2    70

主要查詢應該是這樣的:

select p.name, min(ps.price) from product
inner join product_supplier ps on ps.product_id = p.id
group by p.name

所以計數查詢應該是這樣的:

select count(*) from (
   select p.name, min(ps.price) from product
   inner join product_supplier ps on ps.product_id = p.id
   group by p.name
)

我用來獲取分頁結果的代碼是:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple> tupleQuery = cb.createTupleQuery();

Root<product> product = tupleQuery.from(product.class);
Join<product, productSupplier> productSuppliers = product.join("productSuppliers");

tupleQuery.multiselect(
   product,
   cb.min(productSuppliers.get("price")).alias("price")
);
tupleQuery.groupBy(product);
tupleQuery.orderBy(cb.asc(product.get("name")));

TypedQuery<Tuple> query = entityManager
                            .createQuery(tupleQuery)
                            .setMaxResults(pageable.getPageSize())
                            .setFirstResult(Long.valueOf(pageable.getOffset()).intValue());

List<Tuple> products = query.getResultList();
for (Tuple productResult : products) {
   Product product = productResult.get(product);
   Double minPrice = (Double)productResult.get("price");
   ProductDTO productDTO = new ProductDTO(product, minPrice);  
}

但我不確定如何從主查詢中獲取計數。 我正在使用的代碼是:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    
CriteriaQuery<Long> countQuery = cb.createQuery(Long.class)
    
Root<Product> product = countQuery.from(Product.class);
Join<Product, ProductSupplier> productSuppliers = product.join("productSuppliers");
    
countQuery.groupBy(product);
countQuery.select(cb.count(product));

long count = entityManager.createQuery(countQuery).getSingleResult();

但它會產生以下 SQL:

select
   count(product0_.id) as col_0_0_ 
from
   pu_products product0_ 
inner join
   pu_product_suppliers productsu1_ 
      on product0_.id=productsu1_.product_id
group by
   product0_.id

返回多個結果,拋出以下異常:

org.springframework.dao.IncorrectResultSizeDataAccessException: query did not return a unique result: 31

所以我不知道如何讓它工作。

謝謝。

像這樣的命名查詢怎么樣:

select count(distinct ps.product) from product_supplier ps where ps.price is not null

似乎不可能從通過標准 API 的聚合查詢中執行select count (*) from

所以最后我應用了這個答案中找到的這個解決方案

  • 通過 Criteria API 構建查詢后,得到最終的查詢字符串
  • select count(*) from ({final_query_string})包裹它。
  • 使用select select count (*) from .

解決方案的完整代碼來自@fliX此答案

問候。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM