首先,让我总结一下JPA 2.0规范中关于AVG的内容(有关完整内容,请参见4.8.5 SELECT子句中的聚合函数)
The AVG function takes a state field path expression as an argument and calculates the average value of the sate field over the group. The state field must be numeric, and the result is returnd as a Double.
因此,在第一次阅读之后,我期待以下代码段传递:
Query q = em.createQuery("select avg(s.transfusionUnits) from Surgery s");
Double actual = (Double) q.getSingleResult();
assertEquals(2.5d, actual.doubleValue());
但事实并非如此,我得到的结果是2.0(Double,但不是预期的结果).
所以我查看了数据库级别并意识到SQL查询实际上没有返回2.5.事实上,这就是我的数据库文档中关于AVG的内容:
The average (mean) value. If no rows are selected, the result is NULL. Aggregates are only allowed in select statements. The returned value is of the same data type as the parameter.
我期待太多了. JPA会将结果作为Double返回,但它不会做任何魔术.如果查询未返回具有所需精度的结果,则不会在Java级别获取它.
因此,在不更改transfusionUnits类型的情况下,我必须运行此本机查询才能使工作正常:
Query q = em.createNativeQuery("SELECT AVG(CAST(s.transfusionUnits as double)) from Surgery s");
Double actual = (Double) q.getSingleResult();
assertEquals(2.5d, actual.doubleValue());
更新:在INT列上使用AVG时,似乎某些数据库(例如MySQL)确实返回带小数部分的值(这是有道理的,无论我在此处使用的数据库的记录行为如何).对于其他数据库,可以处理上述演员表
在“方言”中(例如,参见HHH-5173 for Hibernate),以避免在使用JPQL时数据库之间的可移植性问题.