2010-05-07 15 views
5

Tôi có một thực thể JPA 2 có tên là Phẫu thuật. Nó có một thành viên có tên là transfusionUnitsSố nguyên.Hàm JPQL avg aggregate có hoạt động với các số nguyên không?

Có hai mục nhập trong cơ sở dữ liệu. Thực hiện tuyên bố JPQL này:

Select s.transfusionUnits from Surgery s 

tạo ra kết quả dự kiến:

2 
3 

Tuyên bố sau đây tạo ra câu trả lời mong đợi của :

Select sum(s.transfusionUnits) from Surgery s 

Tôi hy vọng câu trả lời trong những cách sau tuyên bố là 2.5, nhưng trả về 2.0 thay thế.

Select avg(s.transfusionUnits) from Surgery s 

Nếu tôi thực hiện câu lệnh trên thành viên (Float) khác, kết quả là chính xác. Bất kỳ ý tưởng về lý do tại sao điều này đang xảy ra? Tôi có cần phải làm một số loại dàn diễn viên trong JPQL không? Điều này thậm chí có thể? Chắc chắn tôi đang thiếu một cái gì đó tầm thường ở đây.

Trả lời

7

Đầu tiên, hãy để tôi tóm tắt những gì các đặc điểm kỹ thuật JPA 2.0 nói về AVG (xem phần 4.8.5 Chức năng tổng hợp trong mệnh đề SELECT cho toàn bộ nội dung)

Hàm AVG có một con đường lĩnh vực nhà nước biểu hiện dưới dạng đối số và tính toán giá trị trung bình của trường sate trong nhóm. Trường trạng thái phải là số và kết quả sẽ được trả về làm Số hai.

Vì vậy, sau khi đọc đầu tiên, tôi đã mong đoạn sau đây để vượt qua:

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

Nhưng nó không, tôi đã nhận được 2.0 kết quả (một đôi, nhưng không phải là kết quả mong đợi).

Vì vậy, tôi đã xem xét cấp cơ sở dữ liệu và nhận ra rằng truy vấn SQL thực sự không trả về 2.5. Và thực sự, đây là những gì tài liệu của cơ sở dữ liệu của tôi nói về AVG:

Giá trị trung bình (trung bình). Nếu không có hàng nào được chọn, kết quả là NULL. Tổng hợp chỉ được phép trong các câu lệnh chọn. Giá trị trả về có cùng loại dữ liệu với tham số.

Tôi đã mong đợi quá nhiều. JPA sẽ trả về kết quả dưới dạng Double, nhưng nó sẽ không thực hiện bất kỳ phép thuật nào. Nếu truy vấn không trả lại kết quả với độ chính xác được yêu cầu, bạn sẽ không nhận được kết quả ở cấp Java.

Vì vậy mà không thay đổi loại transfusionUnits, tôi đã phải chạy truy vấn nguồn gốc này để có được những thứ làm việc:

Query q = em.createNativeQuery("SELECT AVG(CAST(s.transfusionUnits as double)) from Surgery s"); 
Double actual = (Double) q.getSingleResult(); 
assertEquals(2.5d, actual.doubleValue()); 

Cập nhật: Dường như một số cơ sở dữ liệu (ví dụ như MySQL) làm trả lại một giá trị với một phần thập phân khi sử dụng AVG trên một cột INT (có ý nghĩa, bất kể hành vi tài liệu của cơ sở dữ liệu tôi đã sử dụng ở đây). Đối với các cơ sở dữ liệu khác, dàn diễn viên trên có thể được xử lý trong "phương ngữ" (ví dụ: xem HHH-5173 cho Hibernate) để tránh các vấn đề về tính di động giữa cơ sở dữ liệu khi sử dụng JPQL.

1

Truyền trường trung bình để tăng gấp đôi mẹo. Không chắc chắn về tác động của hiệu suất, nhưng không được có bất kỳ điều gì xấu:

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

Nó không có tác dụng với tôi, tôi gặp lỗi phải có) thay vì + dấu. –

+0

đã hoạt động đối với tôi với openjpa, có vẻ như nhà cung cấp phụ thuộc vào nhà cung cấp – MarianP

Các vấn đề liên quan