使用する 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();
}