我是JPA的新手,想要实现一个通用的JPA DAO,需要找到查询结果集的行数来实现分页.搜索网络后,我找不到切实可行的方法.以下是许多文章中建议的代码:
public <T> Long findCountByCriteria(CriteriaQuery<?> criteria) { CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<Long> countCriteria = builder.createquery(Long.class); Root<?> entityRoot = countCriteria.from(criteria.getResultType()); countCriteria.select(builder.count(entityRoot)); countCriteria.where(criteria.getRestriction()); return em.createquery(countCriteria).getSingleResult(); }
但是,使用join时该代码不起作用.有没有办法使用JPA Criteria API计算查询结果集的行数?
更新:
这是创建CriteriaQuery的代码:
CriteriaQuery<T> queryDeFinition = criteriaBuilder.createquery(this.entityClass); Root<T> root = queryDeFinition.from(this.entityClass);
并且可以将一些联接添加到根,直到执行查询为止:
public Predicate addPredicate(Root<T> root) { Predicate predicate = getEntityManager().getCriteriaBuilder().ge(root.join(Entity_.someList).get("id"),13); return predicate; }
并且生成的异常如下:
org.hibernate.hql.ast.QuerySyntaxException: Invalid path:
‘generatedalias1.id’ [select count(generatedalias0) from entity.Entity
as generatedalias0 where ( generatedalias0.id>=13L ) and (
(generatedalias1.id<=34L ) )]
其中generatedalias1应该在Entity上,generatedalias0应该在我加入的关联上.
请注意,我正确实现了Join,因为当我执行不带计数查询的查询时,它执行时没有错误,并且Join正常工作但是当我尝试执行count查询时它会抛出异常.
解决方法
我这样做了:
public Long getRowCount(CriteriaQuery criteriaQuery,CriteriaBuilder criteriaBuilder,Root<?> root){ CriteriaQuery<Long> countCriteria = criteriaBuilder.createquery(Long.class); Root<?> entityRoot = countCriteria.from(root.getJavaType()); entityRoot.alias(root.getAlias()); doJoins(root.getJoins(),entityRoot); countCriteria.select(criteriaBuilder.count(entityRoot)); countCriteria.where(criteriaQuery.getRestriction()); return this.entityManager.createquery(countCriteria).getSingleResult(); } private void doJoins(Set<? extends Join<?,?>> joins,Root<?> root_){ for(Join<?,?> join: joins){ Join<?,?> joined = root_.join(join.getAttribute().getName(),join.getJoinType()); doJoins(join.getJoins(),joined); } } private void doJoins(Set<? extends Join<?,Join<?,?> root_){ for(Join<?,joined); } }
当然,您不需要Root作为输入参数,您可以从条件查询中获取它,