JPQL avg聚合函数是否与Integers一起使用?

Kyl*_*fro 5 java orm jpa jpql jpa-2.0

我有一个名为Surgery的JPA 2实体.它有一个名为transfusionUnits的成员,它是一个Integer.

数据库中有两个条目.执行此JPQL语句:

Select s.transfusionUnits from Surgery s
Run Code Online (Sandbox Code Playgroud)

产生预期的结果:

2
3
Run Code Online (Sandbox Code Playgroud)

以下语句产生5的预期答案:

Select sum(s.transfusionUnits) from Surgery s
Run Code Online (Sandbox Code Playgroud)

我希望以下语句的答案是2.5,但它返回2.0.

Select avg(s.transfusionUnits) from Surgery s
Run Code Online (Sandbox Code Playgroud)

如果我在另一个(Float)成员上执行语句,结果是正确的.有关为什么会发生这种情况的任何想法?我需要在JPQL中进行某种转换吗?这甚至可能吗?当然,我在这里遗漏了一些微不足道的东西.

Pas*_*ent 9

首先,让我总结一下JPA 2.0规范中关于AVG的内容(有关完整内容,请参见4.8.5 SELECT子句中的聚合函数)

AVG函数将状态字段路径表达式作为参数,并计算组上的状态字段的平均值.state字段必须是数字,结果以double形式返回.

因此,在第一次阅读之后,我期待以下代码段传递:

Query q = em.createQuery("select avg(s.transfusionUnits) from Surgery s");
Double actual = (Double) q.getSingleResult();
assertEquals(2.5d, actual.doubleValue());
Run Code Online (Sandbox Code Playgroud)

但它没有,我得到2.0了结果(双倍,但不是预期的结果).

所以我查看了数据库级别并意识到SQL查询实际上没有返回2.5.事实上,这就是我的数据库文档中关于AVG的内容:

平均值(平均值).如果未选择任何行,则结果为NULL.仅在select语句中允许聚合.该返回的值是相同的数据类型作为参数.

我期待太多了.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());
Run Code Online (Sandbox Code Playgroud)

更新:在INT列上使用AVG时,似乎某些数据库(例如MySQL)确实返回带小数部分的值(这是有道理的,无论我在此处使用的数据库的记录行为如何).对于其他数据库,上面的演员可以在"方言"中处理(例如,参见HHK的HHH-5173),以避免在使用JPQL时数据库之间的可移植性问题.