【问题标题】:JPA create count query from existing CriteriaQueryJPA 从现有的 CriteriaQuery 创建计数查询
【发布时间】:2021-04-03 22:12:22
【问题描述】:

我有一个包含一些谓词的查询,我需要计算分页的总记录数。

目前,我正在做的是为查询声明 2 个根以获取结果列表 (1) 和计数查询 (2),然后使用每个谓词,像这样用不同的根复制它

        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<A> cq = cb.createQuery(A.class);
        Root<A> root = cq.from(A.class);
        CriteriaQuery<Long> cq = cb.createQuery(A.class);
        Root<A> rootCount = countQuery.from(A.class);

        List<Predicate> predicates = new ArrayList<>();
        List<Predicate> predicatesCount = new ArrayList<>();
        
        Predicate p = cb.equal(root.get(A.ID), 1);
        predicates.add(p);
        Predicate p1 = cb.equal(rootCount.get(A.ID), 1);
        predicatesCount.add(p1);
        ...
        // execute both query to get result

所以问题是:

是否可以从查询(1)创建计数查询?或者通过计数查询重用谓词?

感谢阅读!

【问题讨论】:

    标签: java hibernate jpa criteriaquery


    【解决方案1】:

    我认为这个人用它的实用程序类回答了你的问题:

    Long count = JpaUtils.count(entityManager, criteriaQuery);
    

    https://stackoverflow.com/a/9246377/5611906

    【讨论】:

      【解决方案2】:

      您可以为您使用 Blaze-Persistence to generate the count query,因为要有效地实现这样的计数查询并不容易。

      Blaze-Persistence 是一个在 JPA/Hibernate 之上工作的库,并添加了对高级 SQL 构造、丰富的分页支持等等的支持。它还有一个 JPA Criteria 实现,您可以将其用作替代品。然后,您可以将此查询转换为允许生成计数查询的 Blaze-Persistence Core 查询构建器:https://github.com/Blazebit/blaze-persistence#jpa-criteria-api-quick-start

      【讨论】:

        【解决方案3】:

        下面的示例展示了设置标准构建器/谓词限制,然后重用它来执行计数查询。

        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
        CriteriaQuery<EntityStub> criteriaQuery = builder.createQuery(EntityStub.class);
        Root<EntityStub> entity_ = criteriaQuery.from(EntityStub.class);
        entity_.alias("entitySub"); //assign alias to entity root
        
        criteriaQuery.where(builder.equal(entity_.get("message"), "second"));
        
        // Generic retrieve count
        CriteriaQuery<Long> countQuery = builder.createQuery(Long.class);
        Root<T> entity_ = countQuery.from(criteriaQuery.getResultType());
        entity_.alias("entitySub"); //use the same alias in order to match the restrictions part and the selection part
        countQuery.select(builder.count(entity_));
        Predicate restriction = criteriaQuery.getRestriction();
        if (restriction != null) {
          countQuery.where(restriction); // Copy restrictions
        }
        Long count = entityManager.createQuery(countQuery).getSingleResult();
        

        看看是否对你有帮助,记下根别名,在进行计数查询时,确保实体类类型为 Long.class

        https://forum.hibernate.org/viewtopic.php?p=2471522#p2471522

        【讨论】:

        • 所以我不能使用相同谓词的原因是因为别名?您的代码将为两个 root 分配别名,以便 jpa 理解?我稍后再试试,谢谢!
        猜你喜欢
        • 1970-01-01
        • 2019-08-07
        • 2015-12-17
        • 1970-01-01
        • 1970-01-01
        • 2019-04-08
        • 2012-05-18
        • 2017-11-25
        • 2011-04-29
        相关资源
        最近更新 更多