当尝试count(*)使用CriteriaBuilder我创建类型查询时,出现以下别名问题。
count(*)
CriteriaBuilder
我应该对以下代码进行哪些更改以获取计数?
限制条件:
代码示例片段:
Class<ReqStatCumulative> entityClass = ReqStatCumulative.class; @Override public long getCountForAlertConfig(AlertConfig cfg) { long count = 0L; if (null != cfg) { CriteriaBuilder qb = entityManager.getCriteriaBuilder(); Metamodel model = entityManager.getMetamodel(); EntityType<ReqStatCumulative> reqStatEntType_ = model.entity(entityClass); CriteriaQuery<ReqStatCumulative> cq = qb.createQuery(entityClass); Root<ReqStatCumulative> rootReqStatEnt = cq.from(reqStatEntType_); Path<Long> processTimeSeconds = rootReqStatEnt.<Long> get("processTimeSeconds"); cq.where(qb.and(qb.greaterThan(processTimeSeconds, (long) cfg.getProcessTimeExceedsSec()),// qb.lessThan(processTimeSeconds, (long) cfg.getProcessTimeExceedsSec() + 100))// );// findCountByCriteria(entityManager, cq, qb); log.debug("\n\t#####Alert desc:" + cfg.getDescription()); log.debug("\n\t#####Alert count= " + count); } else { // Do nothing } return count; } public <T> Long findCountByCriteria(EntityManager em, CriteriaQuery<T> cqEntity, CriteriaBuilder qb) { CriteriaBuilder builder = qb; CriteriaQuery<Long> cqCount = builder.createQuery(Long.class); Root<?> entityRoot = cqCount.from(cqEntity.getResultType()); cqCount.select(builder.count(entityRoot)); cqCount.where(cqEntity.getRestriction()); return em.createQuery(cqCount).getSingleResult(); }
日志:我希望在所有where子句属性中使用generateAlias0而不是generateAlias1。
select count(*) from abc.domain.ReqStatCumulative as **generatedAlias0** where ( **generatedAlias1**.processTimeSeconds>5L ) and ( **generatedAlias1**.processTimeSeconds<200L ) 10:48:57.169 [main] DEBUG o.h.h.i.ast.QueryTranslatorImpl - parse() - HQL: select count(*) from abc.domain.ReqStatCumulative as generatedAlias0 where ( generatedAlias1.processTimeSeconds>5L ) and ( generatedAlias1.processTimeSeconds<200L ) 10:48:57.169 [main] DEBUG o.h.h.i.ast.QueryTranslatorImpl - --- HQL AST --- \-[QUERY] Node: 'query' +-[SELECT_FROM] Node: 'SELECT_FROM' | +-[FROM] Node: 'from' | | \-[RANGE] Node: 'RANGE' | | +-[DOT] Node: '.' | | | +-[DOT] Node: '.' | | | | +-[IDENT] Node: 'abc' | | | | \-[IDENT] Node: 'domain' | | | \-[IDENT] Node: 'ReqStatCumulative' | | \-[ALIAS] Node: '**generatedAlias0**' | \-[SELECT] Node: 'select' | \-[COUNT] Node: 'count' | \-[ROW_STAR] Node: '*' \-[WHERE] Node: 'where' \-[AND] Node: 'and' +-[GT] Node: '>' | +-[DOT] Node: '.' | | +-[IDENT] Node: '**generatedAlias1**' | | \-[IDENT] Node: 'processTimeSeconds' | \-[NUM_LONG] Node: '5L' \-[LT] Node: '<' +-[DOT] Node: '.' | +-[IDENT] Node: '**generatedAlias1**' | \-[IDENT] Node: 'processTimeSeconds' \-[NUM_LONG] Node: '200L' 10:48:57.169 [main] DEBUG o.h.hql.internal.ast.ErrorCounter - throwQueryException() : no errors 10:48:57.169 [main] DEBUG o.h.h.i.antlr.HqlSqlBaseWalker - select << begin [level=1, statement=select] 10:48:57.169 [main] DEBUG o.h.h.internal.ast.tree.FromElement - FromClause{level=1} : erf.domain.ReqStatCumulative (generatedAlias0) -> reqstatcum0_ 10:48:57.169 [main] ERROR o.h.hql.internal.ast.ErrorCounter - Invalid path: 'generatedAlias1.processTimeSeconds' 10:48:57.215 [main] ERROR o.h.hql.internal.ast.ErrorCounter - Invalid path: 'generatedAlias1.processTimeSeconds' org.hibernate.hql.internal.ast.InvalidPathException: Invalid path: 'generatedAlias1.processTimeSeconds'
您的代码失败,因为您Root为count和where子句使用了不同的实例:第一个(按定义顺序)生成generatedAlias1别名,另一个生成generatedAlias0。您需要重构代码,以便Root在两个地方使用相同的实例:
Root
generatedAlias1
generatedAlias0
CriteriaQuery<Long> cqCount = builder.createQuery(Long.class); Root<ReqStatCumulative> entityRoot = cqCount.from(cqEntity.getResultType()); cqCount.select(builder.count(entityRoot)); Path<Long> processTimeSeconds = entityRoot.get("processTimeSeconds"); cqCount.where(qb.and(qb.greaterThan(processTimeSeconds, (long) cfg.getProcessTimeExceedsSec()),// qb.lessThan(processTimeSeconds, (long) cfg.getProcessTimeExceedsSec() + 100))// );// return em.createQuery(cqCount).getSingleResult();