views:

844

answers:

1

I want to build a method that can both retrieve a count(*) and select * from a criteria query. Using the hibernate criteria API I could easily do this using

criteria.setProjection(Projections.rowCount());

, but I recently started using the JPA2.0 Criteria API and am uncertain how to obtain a similar result. Below is a little code fragment to display my situation:

// Set up criteria (restrictions)
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<EntityStub> criteriaQuery = builder.createQuery(EntityStub.class);
Root<EntityStub> entity_ = criteriaQuery.from(EntityStub.class);
criteriaQuery.where(builder.equal(entity_.get("message"), "second"));

// Generic retrieve list (Works)
TypedQuery<T> entityQuery = entityManager.createQuery(criteriaQuery);
List<T> entities = entityQuery.getResultList();

// Generic retrieve count (doesn't work)
CriteriaQuery<Long> countQuery = builder.createQuery(Long.class);
Root<T> entity_ = countQuery.from(criteriaQuery.getResultType());
countQuery.select(builder.count(entity_));
Predicate restriction = criteriaQuery.getRestriction();
if (restriction != null) {
  countQuery.where(restriction); // Copy restrictions, throws: 'Invalid path: 'generatedAlias1.message'
}
Long count = entityManager.createQuery(countQuery).getSingleResult();

The listing of results is quite simple and straight forward, but I'm having trouble retrieving a count of all entities that match my criteria (restrictions). How I'm currently retrieving the count is by setting the root to the criteria query's result type (class) and copying its restrictions. This obviously doesn't work as my countQuery is unaware of the alias 'generatedAlias1', is there a work-around, or preferably a better solution, for my problem?

Yours, Jeroen

A: 

This is illegal under the JPA 2.0 spec. Section 6.8 on page 284 of JSR 317 Final Release:

Note, however, that query elements—-in this example, predicate conditions—are dependent on the CriteriaQuery instance, and are thus not portably reusable with different CriteriaQuery instances.

I did not modify that quote. The immediately preceding paragraph just happens to involve predicates.

In other words, you can't take predicates from object criteriaQuery and use them with the distinct object countQuery.

Dan LaRocque