2011-03-18 49 views
22

Tôi đang triển khai loại chức năng "Tìm kiếm nâng cao" cho thực thể trong hệ thống của tôi. về các thuộc tính của thực thể này. Tôi đang sử dụng API tiêu chí của JPA để tạo động truy vấn Tiêu chí và sau đó sử dụng setFirstResult() & setMaxResults() để hỗ trợ phân trang. Tất cả là tốt cho đến thời điểm này nhưng bây giờ tôi muốn hiển thị tổng số kết quả trên lưới kết quả nhưng tôi không thấy một cách thẳng về phía trước để có được tổng số truy vấn Tiêu chí.
Đây là cách mã của tôi trông giống như:Tổng số hàng cho phân trang bằng cách sử dụng API tiêu chí JPA

CriteriaBuilder builder = em.getCriteriaBuilder(); 
CriteriaQuery<Brand> cQuery = builder.createQuery(Brand.class); 
Root<Brand> from = cQuery.from(Brand.class); 
CriteriaQuery<Brand> select = cQuery.select(from); 
. 
. 
//Created many predicates and added to **Predicate[] pArray** 
. 
. 
select.where(pArray); 
// Added orderBy clause 
TypedQuery typedQuery = em.createQuery(select); 
typedQuery.setFirstResult(startIndex); 
typedQuery.setMaxResults(pageSize); 
List resultList = typedQuery.getResultList(); 

tập kết quả của tôi có thể là lớn vì vậy tôi không muốn tải thực thể của tôi cho truy vấn số, vì vậy cho tôi biết cách hiệu quả để có được tổng số như rowCount() phương pháp trên Tiêu chí (Tôi nghĩ rằng nó có trong tiêu chuẩn Hibernate).

Trả lời

24

Cảm ơn Vladimir! Tôi lấy ý tưởng của bạn và sử dụng truy vấn đếm riêng để sử dụng các vị từ hiện tại của tôi trong đó. thực hiện cuối cùng trông như thế này:

CriteriaBuilder builder = em.getCriteriaBuilder(); 
CriteriaQuery<Brand> cQuery = builder.createQuery(Brand.class); 
Root<Brand> from = cQuery.from(Brand.class); 
CriteriaQuery<Brand> select = cQuery.select(from); 
. 
. 
//Created many predicates and added to **Predicate[] pArray** 
. 
. 
CriteriaQuery<Long> cq = builder.createQuery(Long.class); 
cq.select(builder.count(cq.from(Brand.class))); 
// Following line if commented causes [org.hibernate.hql.ast.QuerySyntaxException: Invalid path: 'generatedAlias1.enabled' [select count(generatedAlias0) from xxx.yyy.zzz.Brand as generatedAlias0 where (generatedAlias1.enabled=:param0) and (lower(generatedAlias1.description) like :param1)]] 
em.createQuery(cq); 
cq.where(pArray); 
Long count = em.createQuery(cq).getSingleResult(); 
. 
. 
select.where(pArray); 
. 
. 
// Added orderBy clause 
TypedQuery typedQuery = em.createQuery(select); 
typedQuery.setFirstResult(startIndex); 
typedQuery.setMaxResults(pageSize); 
List resultList = typedQuery.getResultList() 

Mặc dù đây đang làm việc tốt nhưng tôi vẫn không chắc chắn lý do tại sao tôi phải viết

em.createQuery(cq); 

để làm cho nó làm việc. Bất kỳ ý tưởng?

+0

Bạn có thể tìm hiểu tại sao chính xác bạn cần thêm 'em.createQuery (cq);'? Cảm ơn – Ittai

+0

Hey, đây chỉ là những gì tôi cần ... bu Tôi cũng muốn biết tại sao dòng này là cần thiết!? –

+0

Tôi nghi ngờ nó là để làm với thực tế là 'Predicate' đang được xây dựng bằng cách sử dụng 'Root <>' từ phần này 'Root từ = cQuery.from (Brand.class);' và sau đó được sử dụng cho cả hai truy vấn đếm và truy vấn được phân trang. AFAIK bạn cần xây dựng các vị từ hai lần bằng cả hai đối tượng 'Root <>'. Cái thứ hai được ẩn trong dòng này 'cq.select (builder.count (cq.from (Brand.class))); Tại sao chính xác 'em.createQuery (cq);' công việc tôi không biết, IMO nó nên ném một ngoại lệ. – Neilos

2

Nếu bạn đang sử dụng Hibernate làm nhà cung cấp JPA của bạn, hãy xem projections, đặc biệt là Projections.rowCount().

Bạn có thể phải thực hiện truy vấn hai lần, tuy nhiên, trước tiên hãy đếm số lượng rồi nhận kết quả.

Lưu ý rằng đối với JPA đơn giản, bạn có thể cần một số cách tiếp cận khác.

+3

-1. OP khá rõ ràng tuyên bố anh ta đang tìm kiếm ansers đối với "JPA Tiêu chuẩn API", bạn không nghĩ rằng câu trả lời của bạn là hơi gây hiểu lầm? (Ngụ ý các dự báo ngủ đông là cách để làm điều này). Tôi đang nói điều này bởi vì khi tôi vấp vào câu hỏi tôi đã thấy câu trả lời của bạn trước và nó làm tôi bối rối nghĩ rằng đó là cách (đặc biệt là vì có sự thêm vào giữa bạn và câu trả lời tiếp theo khiến bạn trở thành câu trả lời duy nhất). – Ittai

+0

@ Ittai tốt, ông đề cập đến Hibernate và thậm chí gắn cờ câu hỏi cho phù hợp ... – Thomas

+0

Tôi nghĩ rằng khi bạn đọc câu hỏi bạn thấy rằng nó không phải về hibernate, Nó chỉ là rất nhiều lần trong SO bạn thấy rằng mọi người trả lời những gì họ nghĩ rằng OP cần và không phải những gì OP yêu cầu. Vì có vẻ như một sai lầm trung thực nếu bạn chỉnh sửa câu hỏi của mình, tôi sẽ thay đổi phiếu bầu của mình. – Ittai

14

Tại sao bạn không sử dụng tính?

CriteriaBuilder builder = em.getCriteriaBuilder(); 
CriteriaQuery<Long> cQuery = builder.createQuery(Long.class); 
Root<Brand> from = cQuery.from(Brand.class); 
CriteriaQuery<Long> select = cQuery.select(builder.count(from)); 
. 
. 
//Created many predicates and added to **Predicate[] pArray** 
. 
. 
select.where(pArray); 
// Added orderBy clause 
TypedQuery<Long> typedQuery = em.createQuery(select); 
typedQuery.setFirstResult(startIndex); 
//typedQuery.setMaxResults(pageSize); 
// here is the size of your query 
Long result = typedQuery.getSingleResult(); 
Các vấn đề liên quan