2010-05-07 2 views
5

JPA 2 엔티티가 이고 수술은입니다. 정수 인 transfusionUnits이라는 구성원이 있습니다.JPQL 평균 집계 함수가 정수와 함께 작동합니까?

데이터베이스에 두 개의 항목이 있습니다.

Select sum(s.transfusionUnits) from Surgery s 

나는 다음의 대답을 기대 :

2 
3 

다음 명령문은 5의 예상 답을 생성합니다

Select s.transfusionUnits from Surgery s 

이 예상 결과를 생성 :이 JPQL 문을 실행 성명서는 2.5이지만, 2.0을 반환합니다. 대신

Select avg(s.transfusionUnits) from Surgery s 

다른 (Float) 멤버에서 문을 실행하면 결과가 정확합니다. 왜 이런 일이 일어나고 있는지에 대한 아이디어가 있습니까? JPQL에서 일종의 캐스트를 수행해야합니까? 이것은 가능한가? 확실히 나는 여기서 사소한 것을 놓치고있다.

답변

7

첫째, 나 AVG가 (전체 내용에 대한 SELECT 절 섹션 4.8.5 집계 함수 참조)

은 AVG 함수는 상태 필드의 경로를 소요 대한 JPA 2.0 스펙의 말씀 요약하자 expression을 인수로 사용하여 그룹에 대한 sate 필드의 평균값을 계산합니다. 상태 필드는 숫자 여야하며 결과는 Double로 returnd됩니다.

그래서, 제 읽기 후에, 나는 통과 다음 코드를 기다리고 있었다 :

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

을하지만, 나는 예상 된 결과를 결과로 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()); 

업데이트 : 그것은 나타납니다 일부 데이터베이스 (예 : MySQL은)는를 반환 않는다 INT 열에서 AVG를 사용할 때 소수점 이하의 값을 사용합니다. 여기에서 사용한 데이터베이스의 동작에 관계없이 의미가 있습니다. 다른 데이터베이스의 경우 JPQL을 사용할 때 데이터베이스 간의 이식성 문제를 피하기 위해 위의 캐스트는 "dialect"에서 으로 처리 될 수 있습니다 (예 : 최대 절전 모드의 경우 HHH-5173 참조).

1

두 배로 평균 필드를 캐스팅하면 트릭을 수행합니다. 성능에 영향 확실하지 악 아무것도 안 : 그것은 나를 위해 작동하지 않습니다

Select avg(s.transfusionUnits + 0.0) from Surgery s 
+0

, 내가 거기에해야한다는 오류를 받고 있어요) 대신 + 기호보다 더합니다. –

+0

은 openjpa에서 나를 위해 일했고 공급자에 따라 다름 – MarianP

관련 문제