在讨论Stack Overflow后,我找到了以下解决问题的方法。我的要求是获取匹配行的总数,并返回前十个用于分页的目的。
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<T> cq = cb.createQuery(clazz);
CriteriaQuery<Long> counterCq = cb.createQuery(Long.class);
counterCq.select(cb.count(counterCq.from(clazz)));
Predicate predicate= null;
Predicate predicate1 = null;
Root<T> root = cq.from(clazz);
for (Map.Entry<String, String> e : filters.entrySet()){
predicate = cb.and(cb.like(root.<String>get(e.getKey()), e.getValue()+ "%"));
}
if(predicate != null){
cq.where(predicate);
counterCq.where(predicate);
}
int pn = ( em.createQuery(counterCq).getSingleResult()).intValue();
logger.debug("number of pages is {}", pn);
setRowCount(pn);
if(sortField !=null && !sortField.trim().equals("")){
if(sortOrder == SortOrder.DESCENDING){
cq.orderBy(cb.desc(root.get(sortField)));
} else{
cq.orderBy(cb.asc(root.get(sortField)));
}
}
Query q = em.createQuery(cq);
q.setFirstResult(first);
q.setMaxResults(first+ps);
List<T> cats= (List<T>)q.getResultList();
此代码片段通过
进行休眠java.lang.IllegalArgumentException:org.hibernate.hql.ast.QuerySyntaxException:无效路径:'generatedAlias1.title'[从媒体中选择count(generatedAlias0)as generatedAlias0 where generatedAlias1.title like:param0]
似乎cq.from(clazz)
无法应用于其他查询。
现在我的问题是:有没有办法在两个查询中使用相同的谓词?
答案 0 :(得分:4)
您的谓词列表未正确汇编。你必须将'和'谓词放在一起作为一个表达式。我还喜欢在执行选择之前构建我的谓词以获得更好的可读性。
这是您的代码的重构,以实现正确的结果:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<T> cq = cb.createQuery(clazz);
Root<T> root = cq.from(clazz);
// build predicate list - conjuction starts us with an empty 'and' predicate
Predicate predicate = cb.conjunction();
for (Map.Entry<String, String> e : filters.entrySet()) {
predicate = cb.and(predicate, cb.like(root.get(e.getKey()), e.getValue() + "%"));
}
// query total count
CriteriaQuery<Long> counterCq = cb.createQuery(Long.class);
counterCq.select(cb.count(root)).where(predicate);
int pn = (em.createQuery(counterCq).getSingleResult()).intValue();
logger.debug("number of pages is {}", pn);
setRowCount(pn);
// query results
cq.select(root).where(predicate);
if(sortField !=null && !sortField.trim().equals("")) {
if(sortOrder == SortOrder.DESCENDING) {
cq.orderBy(cb.desc(root.get(sortField)));
}
else {
cq.orderBy(cb.asc(root.get(sortField)));
}
}
TypedQuery<T> q = em.createQuery(cq);
q.setFirstResult(first);
q.setMaxResults(first+ps);
List<T> list = q.getResultList();