如何在旧版的Hibernate(约2009年)中计算行数?

243
例如,如果我们有一个名为Books的表,我们如何使用Hibernate计算书籍记录的总数?
8个回答

310

对于旧版本的Hibernate(<5.2):

假设类名为Book:

return (Number) session.createCriteria("Book")
                  .setProjection(Projections.rowCount())
                  .uniqueResult();

它至少是一个Number,很可能是一个Long


10
正如@Salandur所建议的,“至少是一个数字”,Number类型有“intValue()”、“longValue()”方法,因此我们可以轻松地得到所需的原始类型:((Number) criteria.uniqueResult()).intValue()。 - Jerry Tian
5
如果使用字符串参数无法找到实体映射,请使用session.createCriteria(Book.class)方法。 - Tobias M
5
就像@MontyBongo所说的,我实际上需要像这样引用类:return (Number) session.createCriteria(Book.class).setProjection(Projections.rowCount()).uniqueResult(); - bcmoney
实际上,Hibernate还将类名(在此情况下为Book)映射为实体名称。因此,您可以同时使用实体名称(“Book”)和类名(Book.class)。但是,如果您在同一类上有2个实体映射,则应使用实体名称,否则将加载两个实体映射。 - Salandur
2
那么你就不应该使用有理数据库 ;). long 的最大值为 9,223372037×10¹⁸,这是一个非常大的数字。 - Salandur
显示剩余5条评论

102
在Java中,我通常需要返回整数并使用以下形式:
int count = ((Long)getSession().createQuery("select count(*) from Book").uniqueResult()).intValue();

1
这个问题的被采纳答案对我没用,但是你的确管用。谢谢! - Jason Nichols
59
如果最终还是要编写SQL语句,那么使用ORM的意义何在? - thermz
这是我的主要关注点(使用SQL而不是HQL)。我不得不使用嵌套SELECT来计算左外连接后的行数(我没有在Hibernate中找到适当的左外连接实现)。 - Pramod
15
首先,这个解决方案不使用SQL,而是HQL。而且在使用@EmbeddedId和不支持元组计数的数据库(例如MySQL,其中类似于“select count((a,b)) from table1”的查询无法使用)时,使用count(*)代替“select count(e) from E e”或标准也可以起作用。 - Bruno Medeiros
在撰写本文时,最新版本的Hibernate(5.1.9.final)使得简单条件查询变得非常困难,因此我更喜欢使用这种方法。 - Jerry Chin
显示剩余3条评论

42

这是官方 Hibernate 文档告诉我们的:

您可以在不返回查询结果的情况下计算其数量:

( (Integer) session.createQuery("select count(*) from ....").iterate().next() ).intValue()

然而,它并不总是返回Integer实例,因此为了安全起见最好使用java.lang.Number

1
如果能给出Hibernate团队推荐的方法,那么回答会得到加1分。 - Tom
3
对我来说,这产生了"java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer"的错误,但是将其转换为Long类型就可以正常工作... - rogerdpack
2
@rogerdpack 这是因为Hibernate在3.5中更改了返回类型为Long:https://community.jboss.org/wiki/HibernateCoreMigrationGuide35 - machinery
1
计数函数的返回类型可以在 org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions.CountFunction (StandardBasicTypes.LONG) 中找到。 - Guillaume Husta

12

你可以尝试使用count(*)

Integer count = (Integer) session.createQuery("select count(*) from Books").uniqueResult();

这里的 Books 是指一个类的名称,而不是数据库中的表。


抱歉,但它与Java和Hibernate不兼容 :((我已将int替换为Integer,因为在Java中需要类型转换。) - craftsman
这应该可以使用Integer代替int来完成吗?在HQL中,您需要放置类名而不是表名——这是我所能想到的唯一可能有问题的地方。 - Jon Spokes
1
我认为直接在下面的帖子更符合核心的Hibernate原则。 - Matt Sidesinger
对我来说,使用Java和Hibernate无法正常工作。那么应该怎么做呢? - rParvathi

6
Long count = (Long) session.createQuery("select count(*) from  Book").uniqueResult();

应该这样写:Long count = (Long) session.createQuery("select count(1) from Book").uniqueResult(); 这样可以提高性能。 - rajadilipkolli

6
如果您正在使用Hibernate 5+,那么查询将被修改为:
Long count = session.createQuery("select count(1) from  Book")
                    .getSingleResult();

如果您需要 TypedQuery

Long count = session.createQuery("select count(1) from  Book",Long.class)
                        .getSingleResult();

1

非常简单,只需运行以下JPQL查询:

int count = (
(Number)
    entityManager
    .createQuery(
        "select count(b) " +
        "from Book b")
    .getSingleResult()
).intValue();

我们之所以要转换为 Number,是因为一些数据库会返回 Long 而另一些会返回 BigInteger,为了可移植性起见,您最好将其转换为 Number 并获取一个 intlong,具体取决于您期望计数的行数。

1

这在Hibernate 4中有效(已测试)。

String hql="select count(*) from  Book";
Query query= getCurrentSession().createQuery(hql);
Long count=(Long) query.uniqueResult();
return count;

getCurrentSession() 是什么:

@Autowired
private SessionFactory sessionFactory;


private Session getCurrentSession(){
return sessionFactory.getCurrentSession();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接