134

私はJPA2にかなり慣れていません。それは、CriteriaBuilder /CriteriaQueryAPIです。

CriteriaQueryjavadoc

CriteriaQueryJavaEE6チュートリアルで

CriteriaQueryの結果を実際に取得せずにカウントしたいと思います。それは可能ですか、私はそのような方法を見つけませんでした、唯一の方法はこれを行うことです:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();

CriteriaQuery<MyEntity> cq = cb
        .createQuery(MyEntityclass);

// initialize predicates here

return entityManager.createQuery(cq).getResultList().size();

そして、それはそれを行うための適切な方法ではありえません...

解決策はありますか?

4

7 に答える 7

249

タイプのクエリはMyEntityを返しMyEntityます。のクエリが必要ですLong

CriteriaBuilder qb = entityManager.getCriteriaBuilder();
CriteriaQuery<Long> cq = qb.createQuery(Long.class);
cq.select(qb.count(cq.from(MyEntity.class)));
cq.where(/*your stuff*/);
return entityManager.createQuery(cq).getSingleResult();

明らかに、例でスキップした制限やグループ化などを使用して式を構築する必要があります。

于 2010-05-21T17:58:16.203 に答える
35

cb.createQuery() を使用してこれを整理しました (結果の型パラメーターなし):

public class Blah() {

    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    CriteriaQuery query = criteriaBuilder.createQuery();
    Root<Entity> root;
    Predicate whereClause;
    EntityManager entityManager;
    Class<Entity> domainClass;

    ... Methods to create where clause ...

    public Blah(EntityManager entityManager, Class<Entity> domainClass) {
        this.entityManager = entityManager;
        this.domainClass = domainClass;
        criteriaBuilder = entityManager.getCriteriaBuilder();
        query = criteriaBuilder.createQuery();
        whereClause = criteriaBuilder.equal(criteriaBuilder.literal(1), 1);
        root = query.from(domainClass);
    }

    public CriteriaQuery<Entity> getQuery() {
        query.select(root);
        query.where(whereClause);
        return query;
    }

    public CriteriaQuery<Long> getQueryForCount() {
        query.select(criteriaBuilder.count(root));
        query.where(whereClause);
        return query;
    }

    public List<Entity> list() {
        TypedQuery<Entity> q = this.entityManager.createQuery(this.getQuery());
        return q.getResultList();
    }

    public Long count() {
        TypedQuery<Long> q = this.entityManager.createQuery(this.getQueryForCount());
        return q.getSingleResult();
    }
}

それが役に立てば幸い :)

于 2012-05-11T18:51:37.483 に答える
25
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
cq.select(cb.count(cq.from(MyEntity.class)));

return em.createQuery(cq).getSingleResult();
于 2010-05-21T17:56:45.950 に答える
5

使用する JPA 2 実装によっては、少し注意が必要です。これは EclipseLink 2.4.1 では機能しますが、Hibernate では機能しません。ここでは、EclipseLink の一般的な CriteriaQuery カウントを示します。

public static Long count(final EntityManager em, final CriteriaQuery<?> criteria)
  {
    final CriteriaBuilder builder=em.getCriteriaBuilder();
    final CriteriaQuery<Long> countCriteria=builder.createQuery(Long.class);
    countCriteria.select(builder.count(criteria.getRoots().iterator().next()));
    final Predicate
            groupRestriction=criteria.getGroupRestriction(),
            fromRestriction=criteria.getRestriction();
    if(groupRestriction != null){
      countCriteria.having(groupRestriction);
    }
    if(fromRestriction != null){
      countCriteria.where(fromRestriction);
    }
    countCriteria.groupBy(criteria.getGroupList());
    countCriteria.distinct(criteria.isDistinct());
    return em.createQuery(countCriteria).getSingleResult();
  }

先日、EclipseLink から Hibernate に移行し、count 関数を次のように変更する必要がありました。これは解決が難しい問題であるため、どちらかを自由に使用してください。あなたのケースではうまくいかない可能性があります。Hibernate から使用されています。 4.x では、どれがルートであるかを推測しようとしないことに注意してください。代わりに、クエリからそれを渡しているため、問題は解決しました。推測するにはあいまいなコーナーケースが多すぎます。

  public static <T> long count(EntityManager em,Root<T> root,CriteriaQuery<T> criteria)
  {
    final CriteriaBuilder builder=em.getCriteriaBuilder();
    final CriteriaQuery<Long> countCriteria=builder.createQuery(Long.class);

    countCriteria.select(builder.count(root));

    for(Root<?> fromRoot : criteria.getRoots()){
      countCriteria.getRoots().add(fromRoot);
    }

    final Predicate whereRestriction=criteria.getRestriction();
    if(whereRestriction!=null){
      countCriteria.where(whereRestriction);
    }

    final Predicate groupRestriction=criteria.getGroupRestriction();
    if(groupRestriction!=null){
      countCriteria.having(groupRestriction);
    }

    countCriteria.groupBy(criteria.getGroupList());
    countCriteria.distinct(criteria.isDistinct());
    return em.createQuery(countCriteria).getSingleResult();
  }
于 2012-11-21T10:11:32.243 に答える
0

プロジェクションも使用できます。

ProjectionList projection = Projections.projectionList();
projection.add(Projections.rowCount());
criteria.setProjection(projection);

Long totalRows = (Long) criteria.list().get(0);
于 2017-02-09T08:27:40.597 に答える