当前位置: 首页 > 面试题库 >

使用CriteriaBuilder的JPA + Hibernate count(*)-与generateAlias

单于山
2023-03-14
问题内容

当尝试count(*)使用CriteriaBuilder我创建类型查询时,出现以下别名问题。

我应该对以下代码进行哪些更改以获取计数?

限制条件:

  1. 我必须使用CriteriaBuilder / Query,因为必须根据值动态构建where子句。
  2. 我只需要COUNT,而不需要内存中的对象列表。

代码示例片段:

 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在两个地方使用相同的实例:

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();


 类似资料:
  • 问题内容: 我需要创建一个“真实的”动态JPA 。我得到的陈述。看起来像: 这是我实现的: 我试图构建一个big ,其中包含所有其他谓词,并将其添加到中,但这些谓词再次覆盖旧值。似乎没有可能添加而不是更改谓词:-( 实际的项目更加复杂,因为有些对需要使用,而另一些需要使用。但这还不够:可能有一个额外的声明,如like 。在这里,值必须拆分并创建如下语句: UPDATE和SOLUTION 得到两个列

  • 我是JPA的新手。使用where子句构建select查询。我需要从表Contacts中选择所有等于字符串名称值的ContactName。 以下是执行我的项目时出现的错误:java.lang.IllegalArgumentException:无法根据在org.hibernate.jpa.criteria.path.abstractPathimpl.unknownatAttribute(abstrac

  • 在我的示例中,如何使用JPA CriteriaBuilder(如hibernate Criteria)这样的标准进行选择? 和

  • 问题内容: 我有这样的SQL语句: 因此,它为personID提供了“区别”行: 如果我有这样的表: 它会回来 现在,我尝试通过JPA CriteriaBuilder进行此操作。 我的第一个想法是子查询: 但这会产生错误 怎么对这个? 马可 问题答案: 我认为解决方案比看起来简单。您忘记了包含在CriteriaBuilder子查询中。以下代码执行您要查找的查询。 此代码将创建以下查询: 我认为您正

  • 我有一个带有3列的示例MyTable-id、common_id、creation_date,其中common_id分组条目。 现在,我想使用CriteriaBuilder从每个组中选择所有最新的条目(即每个常见的\u id获取最新的创建日期)。 SQL查询如下所示: 现在我尝试通过编写类似(cb是CriteriaBuilder,root是Root)的内容来创建place谓词: 但不幸的是。数组不是

  • 我有一个包含员工信息的mysql数据库,每个员工都有一个技术id作为主键。在MySQL中选择行匹配条件,我可以使用以下语句(工作) 在Java我也可以使用这个作为一个本地语句来得到我想要的(作品): 然而,我想使用Criteriabuilder获得相同的结果,然后将其推广到多个columnName=columnEntry选择中。 使用“fist_name”——来自实体的列名注释——将生成以下jav