Java Hibernate 计数行

Posted

技术标签:

【中文标题】Java Hibernate 计数行【英文标题】:Java Hibernate Count Rows 【发布时间】:2017-04-18 09:20:26 【问题描述】:

我将 Java8 与 Hibernate5 和 JPA2 一起使用。我想计算结果集中的行数。我有以下有效的代码,但是,我想知道是否有更有效的方法?我认为下面的代码首先查询整个结果集并计算行数。

    final EntityManagerFactory entityManagerFactory = entityManager.getEntityManagerFactory();
    final CriteriaBuilder criteriaBuilder = entityManagerFactory.getCriteriaBuilder();
    CriteriaQuery<Rating> criteria = criteriaBuilder.createQuery(Rating.class);
    Root<Rating> root = criteria.from(Rating.class);
    ParameterExpression<Job> param = criteriaBuilder.parameter(Job.class);

    TypedQuery<Rating> queryRating = entityManager.createQuery(criteria);
    queryRating.setParameter(param, job);
    int results = queryRating.getResultList().size();

有没有办法让 SQL 执行 count(*)

更新

感谢下面的@chsdk,我有一个修改版的代码:

    CriteriaBuilder qb = entityManager.getCriteriaBuilder();
    CriteriaQuery<Long> cq = qb.createQuery(Long.class);
    cq.select(qb.count(cq.from(Rating.class)));
    cq.where(/*your stuff*/);
    return entityManager.createQuery(cq).getSingleResult();

问题

如何使用Job 参数设置where 子句?

更多信息:

+--------+   +------------+    +-----+
| rating |   | rating_job |    | job |
+--------+   +------------+    +-----+
|   ID   |   |   RAT_ID   |    |  ID |
|        |   |   JOB_ID   |    |     |
+--------+   +------------+    +-----+

Rating.java

@ManyToOne(fetch=FetchType.EAGER)
@JoinTable
(
    name="rating_job",
    joinColumns= @JoinColumn(name="RAT_ID", referencedColumnName="ID") ,
    inverseJoinColumns= @JoinColumn(name="JOB_ID", referencedColumnName="ID") 
)
private Job job;

更新

感谢@chsdk,这是我的版本:

    final EntityManagerFactory entityManagerFactory = entityManager.getEntityManagerFactory();
    final CriteriaBuilder criteriaBuilder = entityManagerFactory.getCriteriaBuilder();
    CriteriaQuery<Long> criteria = criteriaBuilder.createQuery(Long.class);
    Root<Rating> root = criteria.from(Rating.class);
    ParameterExpression<Job> param = criteriaBuilder.parameter(Job.class);
    criteria.select(criteriaBuilder.count(root)).where(criteriaBuilder.equal(root.get("job"), param));
    TypedQuery<Long> queryRating = entityManager.createQuery(criteria);
    queryRating.setParameter(param, job);
    Long results = queryRating.getSingleResult();

    return results;

【问题讨论】:

如果你想限制一些“工作”然后加入那个实体并应用 where 子句,否则你没有使用你的参数。日志会告诉您生成了什么 SQL,因此这应该是高效的基础 谢谢尼尔。这是我的问题,我该如何做where 子句?如何将Job 对象添加到where 子句? cq.where(/*rating is equal to job*/) @Richard 检查我的更新。 【参考方案1】:

JPA2 中使用 CriteriaQuery 你可以这样做:

final CriteriaBuilder criteriaBuilder = entityManagerFactory.getCriteriaBuilder();
CriteriaQuery<Long> criteria = qb.createQuery(Long.class);
Root<Country> root = criteria.from(Rating.class);
criteria.select(criteriaBuilder.count(root));

ParameterExpression<Job> param = criteriaBuilder.parameter(Job.class);
criteria.where(criteriaBuilder.equal(root.get("job"), param));

创建一个CriteriaQuery&lt;Long&gt; 而不是CriteriaQuery&lt;Rating&gt;,这样当您计算criteria.from(Rating.class) 结果的行数时,它会为您提供行数。

编辑:

我编辑了答案代码,以在查询中包含对Job 给定参数的测试,尊重您的实体映射。

然后要执行您的查询,您需要编写:

TypedQuery<Country> query = em.createQuery(criteria);
query.setParameter(param, yourJobObject);
Long resultsCount = query.getSingleResult();

请注意,您需要将 query.getSingleResult() 包装在 try ..catch 块中,因为它可能会引发错误。

参考:

请查看the answer here 和此JPA Criteria API Queries tutorial 以进一步阅读。

【讨论】:

谢谢,但是你把 Job 参数放在哪里了? 谢谢,但我不确定这是否可行,因为我的 Rating 表使用连接表。我会更新上面的描述。 我想它快到了。我现在得到:Named parameter [param0] not set。抱歉,我看到了你的修改,这可能会解决它。 @Richard 您是否按照我在编辑中的建议使用了query.setParameter(param, yourJobObject);【参考方案2】:

只是一个例子,我用它来检查实体的存在。

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Long> cQuery = builder.createQuery(Long.class);
Root<Tag> from = cQuery.from(Tag.class);
cQuery.where(from.get("ID").in(ids));

CriteriaQuery<Long> nbTags = cQuery.select(builder.count(from));

return em.createQuery(nbTags).getSingleResult();

如果它们不是任何标签,它只会向我发送0,否则会发送现有标签的数量。

【讨论】:

【参考方案3】:

只需像这样使用 rowCount 添加投影:

return (Long) criteria.setProjection(Projections.rowCount()).uniqueResult();

结果将是Long类型的行数对象

【讨论】:

谢谢,这看起来很有用。但是,我确实收到以下编译错误:The method setProjection(Projection) is undefined for the type CriteriaQuery&lt;Rating&gt; 因为它不是 JPA Criteria(答案是 Hibernates 自己的 API,所以放弃可移植性!) 我猜这也忽略了Job参数? 啊,我的错,这个答案是针对 org.hibernate.Criteria(hibernate) 而不是 javax.persistence.criteria.CriteriaQuery(JPA)。

以上是关于Java Hibernate 计数行的主要内容,如果未能解决你的问题,请参考以下文章

求教第一个hibernae程序的配置文件hibernate.cfg.xml出错了,求帮忙解决,如下

hibernate配置管理

Hibernae

Hibernaate 详解

idea创建Hibernate项目

spring+Hibernate 一对多计数行