En primer lugar, permítanme resumir lo que la especificación JPA 2.0 dice acerca de AVG (véase la sección 4.8.5 funciones de agregado en la cláusula SELECT para el contenido completo)
La función AVG toma un camino campo de estado expresión como argumento y calcula el valor promedio del campo de estado sobre el grupo. El campo de estado debe ser numérico, y el resultado es retornar como un doble.
Así, después de una primera lectura, que estaba esperando el siguiente fragmento de pasar:
Query q = em.createQuery("select avg(s.transfusionUnits) from Surgery s");
Double actual = (Double) q.getSingleResult();
assertEquals(2.5d, actual.doubleValue());
pero no fue así, me estaba 2.0
como resultado (un doble, pero no el resultado esperado)
Así que miré en el nivel de la base de datos y me di cuenta de que la consulta SQL en realidad no estaba devolviendo 2.5
. Y de hecho, esto es lo que dice la documentación de mi base de datos sobre AVG:
El valor promedio (promedio). Si no se seleccionan filas, el resultado es NULO. Los agregados solo se permiten en declaraciones seleccionadas. El valor devuelto es del mismo tipo de datos que el parámetro.
Estaba esperando demasiado. JPA devolverá el resultado como un doble, pero no hará magia. Si la consulta no devuelve un resultado con la precisión requerida, no lo obtendrá en el nivel de Java.
Así que sin cambiar el tipo de transfusionUnits
, tenía que ejecutar esta consulta nativa para hacer las cosas de trabajo:
Query q = em.createNativeQuery("SELECT AVG(CAST(s.transfusionUnits as double)) from Surgery s");
Double actual = (Double) q.getSingleResult();
assertEquals(2.5d, actual.doubleValue());
Actualización: Parece ser que alguna base de datos (por ejemplo, MySQL) personas vuelven en una valor con una parte decimal cuando se usa AVG en una columna INT (lo que tiene sentido, independientemente del comportamiento documentado de la base de datos que utilicé aquí). Para otras bases de datos, el elenco anterior podría manejarse en el "dialecto" (por ejemplo, ver HHH-5173 para Hibernate) para evitar problemas de portabilidad entre la base de datos al usar JPQL.
No funciona para mí, me sale un error que debería haber) en lugar de + signo. –
funcionó para mí con openjpa, parece que depende del proveedor – MarianP