Hibernate中的count聚合函数:是Integer还是Long?

文章讲述了在使用Hibernate进行HQL查询时出现的Long与Integer转换异常,原因是从Hibernate3.2开始,count()等函数返回值改为Long以兼容JPA。为解决此问题,文章提供了升级代码或配置经典函数的方案。

最近在上课的时候发现一个问题,其实这个问题很早以前就发现了。不过以前也懒得去理它,最近想想找找原因吧。就是我用HQL查询数据库的时候,sj写如下语句:
 

public int getCount() {
	Session session = super.getSession();
	int count = (Integer) session.createQuery("select count(h) from House h").uniqueResult();
	session.close();
	return count;
}


上课演示的时候没有任何问题,而不少同学在写相同代码的时候,却出现如下异常:

org.apache.jasper.JasperException: java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer


这意思是就不能将Long类型转成Integer类型

后来发现问题所有,原来是Hibernate版本的问题,我上课用的是Hibernate3.0,而多数同学用的是Hibernate3.3
上网找了下答案,如下:
经确认从3.2以后,Hibernate已经把以前返回 Integer的改成了 Long, 因为JPA里面的返回值规定是Long, Hibernate为了兼容这个,所以修改了返回值。 如果你从Hibernate 3.0.x/3.1.x升级到最新的3.2版,一定要注意,3.2版的很多sql函数如count(), sum()的唯一返回值已经从Integer变为Long,如果不升级代码,会得到一个ClassCastException。 
这个变化主要是为了兼容JPA,可以在hibernate.org的最新文档中找到说明。 
Hibernate Team也提供了一个与原来兼容的解决方案: 

Configuration classicCfg = new Configuration(); 
classicCfg.addSqlFunction( "count", new ClassicCountFunction()); 
classicCfg.addSqlFunction( "avg", new ClassicAvgFunction()); 
classicCfg.addSqlFunction( "sum", new ClassicSumFunction()); 
SessionFactory classicSf = classicCfg.buildSessionFactory();


希望对大家有帮助。

<think>好的,用户的问题是为什么使用同一个`criteria.uniqueResult()`方法,查询得到的结果类型不同,一个是`Stuinfo`对象,另一个是`Integer`。我需要详细分析可能的原因。 首先,回忆一下Hibernate的`Criteria`查询。`uniqueResult()`方法用于返回唯一结果,如果查询结果不唯一会抛出异常。用户的情况是两次调用返回不同类型,可能和查询的目标有关。 首先考虑查询的投影(Projection)设置。如果第一次查询没有设置投影,默认是查询实体对象,所以返回`Stuinfo`。第二次可能设置了`Projections.rowCount()`或类似的统计投影,这时候返回的是`Integer`类型的计数。 然后,检查是否两次查询的`Criteria`实例不同。如果第一次是查询实体,第二次是统计数量,可能是在不同的`Criteria`实例上调用,导致结果类型不同。 另外,可能涉及查询条件的不同。比如第一次查询返回单个实体,第二次通过聚合函数(如count)返回数值。需要确认两次查询的投影和条件设置。 还要考虑Hibernate的类型转换。如果投影返回的是数值类型,Hibernate会自动转换为`Integer`或`Long`等,但如果是实体查询,返回的是实体对象。 总结可能的原因:投影设置不同(实体vs统计)、不同的`Criteria`实例、聚合函数的使用。需要详细解释这些点,并举例说明。 </think>`criteria.uniqueResult()`方法返回结果类型不一致的核心原因是**两次查询的`Criteria`对象的投影(Projection)设置不同**,导致Hibernate最终执行的SQL语句和返回的结果类型完全不同。以下是具体分析: ### 一、`uniqueResult()`的本质 `Criteria.uniqueResult()`的作用是执行查询并返回**唯一结果**(若结果不唯一会抛出`NonUniqueResultException`异常)。但它的返回类型由查询的**投影(Projection)**决定,而非固定类型。投影定义了“查询的目标数据”(是实体对象、统计值,还是某列的字段值)。 ### 二、场景分析:为什么一个返回`Stuinfo`,另一个返回`Integer`? 假设两段代码分别为: ```java // 代码1:查询实体对象 Stuinfo info = (Stuinfo) criteria1.uniqueResult(); // 代码2:查询统计值(如数量) Integer count = (Integer) criteria2.uniqueResult(); ``` 两者结果类型不同的根本原因是`criteria1`和`criteria2`的**投影设置不同**。 #### 1. 场景1:无投影(查询实体对象) 若`criteria1`未显式设置投影(默认投影),Hibernate会执行`SELECT * FROM stuinfo WHERE ...`,返回完整的`Stuinfo`实体对象。此时`uniqueResult()`的返回类型是`Stuinfo`(实体类)。 **示例代码**: ```java Criteria criteria1 = session.createCriteria(Stuinfo.class); criteria1.add(Restrictions.eq("id", 1L)); // 查询id=1的学生 Stuinfo info = (Stuinfo) criteria1.uniqueResult(); // 返回Stuinfo对象 ``` #### 2. 场景2:设置统计投影(如计数) 若`criteria2`显式设置了统计投影(如`Projections.rowCount()`),Hibernate会执行`SELECT COUNT(*) FROM stuinfo WHERE ...`,返回的是统计值(通常为`Long`或`Integer`类型)。此时`uniqueResult()`的返回类型是`Integer`(或`Long`)。 **示例代码**: ```java Criteria criteria2 = session.createCriteria(Stuinfo.class); criteria2.add(Restrictions.eq("age", 18)); // 查询年龄=18的学生数量 criteria2.setProjection(Projections.rowCount()); // 设置投影为计数 Integer count = (Integer) criteria2.uniqueResult(); // 返回Integer类型的数量 ``` ### 三、关键差异:投影的作用 投影(`Projection`)通过`criteria.setProjection()`方法设置,决定了查询的“目标列”。常见投影类型包括: - **无投影(默认)**:查询完整实体对象(`SELECT *`),返回实体类类型(如`Stuinfo`)。 - **统计投影**:如`Projections.rowCount()`(计数)、`Projections.sum("score")`(求和),返回数值类型(如`Integer`、`Long`)。 - **字段投影**:如`Projections.property("name")`(查询单个字段),返回字段对应类型(如`String`)。 ### 四、其他可能原因 若两次使用的是**同一个`Criteria`实例**,但结果类型不同,可能是因为: 1. **重复设置投影**:第一次查询前未设置投影(返回实体),第二次查询前设置了统计投影(返回数值)。 ```java Criteria criteria = session.createCriteria(Stuinfo.class); // 第一次查询(无投影) Stuinfo info = (Stuinfo) criteria.uniqueResult(); // 第二次查询前设置投影 criteria.setProjection(Projections.rowCount()); Integer count = (Integer) criteria.uniqueResult(); // 结果类型变为Integer ``` 2. **查询条件导致结果唯一性变化**:若第一次查询条件严格(返回1条),第二次条件宽松(返回0条或多条),但`uniqueResult()`在结果为空时返回`null`(类型仍由投影决定),不会改变类型。 ### 五、总结 `uniqueResult()`返回类型由`Criteria`的**投影设置**决定: - 无投影 → 返回实体对象(如`Stuinfo`); - 统计/字段投影 → 返回对应数值或字段类型(如`Integer`、`String`)。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值