2014-12-31 11 views
6

Đây là một thực thể mẫu:JPA nhóm Tiêu chuẩn truy vấn bằng cách sử dụng chỉ id

public class Account{ 

    @Id 
    Long id 
    Double remaining; 
    @ManyToOne 
    AccountType type 
} 

public class AccountType{ 
    @Id 
    Long id; 
    String name; 
} 

Bây giờ tôi tạo một truy vấn tiêu chí với gia như follwing:

CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder(); 
CriteriaQuery criteriaQuery = criteriaBuilder.createquery(); 
Root<Account> accountRoot = criteriaQuery.from(Account.class); 
Join<Account, AccountType> typeJoin = accountRoot.join(Account_.type); 

criteriaQuery.multiSelect(
    typeJoin, 
    criteriaBuilder.sum(accountRoot.get(Account_.remaining)) 
); 

criteriaQuery.groupBy(typeJoin); 
Query query = getEntityManager().createQuery(criteriaQuery); 
query.getResultList(); 

Đoạn mã trên tạo ra lệnh Sql như sau:

select accType.id, accType.name, sum(acc.remaining) 
from account acc join accType on acc.accounttype_id = accType.id 
group by accType.id 

trên công việc mã trong PosgreSQL nhưng không thể chạy trong Oracle, bởi vì trong nó chọn accType.name điều đó không không xuất hiện trong nhóm theo mệnh đề.

cập nhật:
Tôi nghĩ câu hỏi của tôi không rõ ràng cho bạn. Câu hỏi của tôi không phải là về hành vi PostgreSQL hoặc Oracle trong group by. Câu hỏi của tôi là:
Tôi sử dụng mệnh đề typeJoin trong mệnh đề group by (điều này có nghĩa là tôi mong đợi sử dụng ngủ đông tất cả trường AccountType trong group by), nhưng tại sao hibernate chỉ sử dụng trường nhận dạng trên group by? nếu tôi sẽ sử dụng chỉ lĩnh vực nhận dạng trong group by sau đó tôi có thể sử dụng câu lệnh sau:

criteriaQuery.groupBy(typeJoin.get(AccountType_.id)) ; 

Trả lời

6

JPA/Hibernate không tự động bao gồm tất cả các thuộc tính đối tượng trong một nhóm bởi khoản, vì vậy bạn phải tự xác định họ:

CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder(); 
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(); 
Root<Account> accountRoot = criteriaQuery.from(Account.class); 
Join<Account, AccountType> typeJoin = accountRoot.join(Account_.type); 

criteriaQuery.multiSelect(
    typeJoin.get("id"), 
    typeJoin.get("name"), 
    criteriaBuilder.sum(accountRoot.get(Account_.remaining)) 
); 

criteriaQuery.groupBy(typeJoin.get("id"), typeJoin.get("name")); 
Query query = getEntityManager().createQuery(criteriaQuery); 
query.getResultList(); 
+0

đây không phải là ý tưởng hay. Trong giải pháp này bất cứ lúc nào AccountType thay đổi tôi hầu hết thay đổi tất cả các truy vấn của tôi. tất nhiên tôi có thể xử lý nó bằng cách phản ánh nhưng tôi nghĩ rằng phải có một giải pháp tốt hơn cho nó. bạn có chắc chắn hibernate cann't bao gồm tất cả các thuộc tính entitiy? –

+0

Bạn chỉ cần chỉ định accountType.id và sử dụng bộ nhớ cache cấp 2 để tải nó sau đó. –

+0

Tất nhiên bạn cũng có thể sử dụng JAM Metamodel để lấy tất cả các thuộc tính của kiểu thực thể và đặt chúng vào nhóm theo đó sẽ là chung chung. –

3

Nếu sử dụng GROUP BY, Oracle yêu cầu mọi cột trong danh sách lựa chọn phải nằm trong GROUP BY.
PostgreSQL giống nhau, ngoại trừ khi nhóm theo khóa chính, sau đó nó cho phép bạn chọn bất kỳ cột nào.

Từ Oracle docs

Trong một truy vấn có chứa một mệnh đề GROUP BY, các yếu tố của danh sách chọn có thể chức năng tổng hợp, GROUP BY biểu thức, hằng số, hoặc biểu thức liên quan đến một trong số này.

Từ PostgreSQL docs

Khi GROUP BY là hiện tại, hay bất kỳ chức năng tổng hợp có mặt, nó không hợp lệ cho các biểu thức danh sách SELECT để tham khảo cột ungrouped trừ trong phạm vi chức năng tổng hợp hoặc khi cột chưa được nhóm phụ thuộc vào chức năng trên các cột được nhóm, vì sẽ có nếu không có nhiều hơn một giá trị có thể để trả về cột không được nhóm. Một sự phụ thuộc chức năng tồn tại nếu các cột được nhóm (hoặc tập hợp con) là khóa chính của bảng chứa cột không được nhóm.

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