29

ユーザーがこのエンティティの属性に対して複数の条件 (eq、ne、gt、lt、like など) を使用してそのエンティティを検索できるように、システム内のエンティティに「高度な検索」の種類の機能を実装しています。JPA の Criteria API を使用して Criteria クエリを動的に生成し、setFirstResult()&を使用setMaxResults()してページネーションをサポートしています。この時点まではすべて問題ありませんでしたが、結果グリッドに結果の合計数を表示したいのですが、基準クエリの合計数を取得する簡単な方法がわかりませんでした。
これは私のコードがどのように見えるかです:

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();

私の結果セットは大きくなる可能性があるので、カウントクエリのためにエンティティをロードしたくないので、Criteria のメソッドのような合計カウントを取得する効率的な方法を教えてくださいrowCount()(Hibernate の Criteria にあると思います)。

4

4 に答える 4

33

ありがとうウラジミール!私はあなたのアイデアを取り入れ、別のカウントクエリを使用して、既存の述語の配列を使用しました。最終的な実装は次のようになります。

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()

これは正常に機能していますが、それでもなぜ書かなければならないのかわかりません

em.createQuery(cq);

それを機能させるために。何か案が?

于 2011-03-18T13:56:17.517 に答える
16

カウントを使用しないのはなぜですか?

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();
于 2011-03-18T08:07:46.273 に答える
2

JPAプロバイダーとして Hibernate を使用している場合は、特にProjections.rowCount().

ただし、クエリを 2 回実行する必要がある場合があります。最初にカウントを取得してから結果を取得します。

プレーンな JPA の場合、他のアプローチが必要になる場合があることに注意してください。

于 2011-03-18T07:45:46.273 に答える