2012-03-07 25 views
15

Tôi đang làm việc với hibernate và tôi đang gặp khó khăn khi tạo một truy vấn hql lấy tất cả các con của đối tượng của tôi. Ví dụ: Người dùng đối tượng có danh sách Ô tô và danh sách Bạn bè.Làm thế nào để tham gia lại tìm nạp nhiều trẻ em trong Hibernate?

Để có được một người dùng với những chiếc xe của mình, tôi sẽ sử dụng truy vấn sau đây:
từ Người dùng u bên trái tham gia tìm nạp u.cars nơi u.id =?

này hoạt động tốt, vì vậy tôi nghĩ rằng nó sẽ được dễ dàng để có được một người dùng với chiếc xe của mình và với bạn bè của mình với truy vấn sau đây:
từ tài khoản u trái tham gia lấy u.cars LEFT JOIN lấy u.friends nơi u.id =?

Nhưng điều này mang lại cho tôi lỗi sau:
HibernateException: có thể không đồng thời lấy nhiều túi

Bây giờ câu hỏi của tôi là: đúng cách để lấy nhiều trẻ em trong Hibernate là gì?

+0

Trùng lặp: http://stackoverflow.com/questions/4334970/hibernate-cannot-simultaneously-fetch-multiple-bags. Sử dụng Hibernate: @LazyCollection (LazyCollectionOption.FALSE) – willome

Trả lời

10

Hầu hết một trong các bộ sưu tập trẻ em phải là một túi (ví dụ: được khai báo là Danh sách). Khai báo các bộ sưu tập khác dưới dạng Sets và nó sẽ hoạt động.

Hãy coi chừng, tuy nhiên, việc thực hiện các lần tìm nạp như vậy sẽ tạo ra một sản phẩm cartesiann của các hàng. Nếu cả hai bộ sưu tập có 100 phần tử, thì truy vấn đó sẽ truy lục 10.000 hàng fro cơ sở dữ liệu. Đôi khi sẽ thực hiện truy vấn đầu tiên hiệu quả hơn khi tìm nạp một bộ sưu tập và một truy vấn thứ hai tìm nạp bộ sưu tập kia (do đó làm giảm số lượng các hàng được truy xuất đến 200). Đây cũng là một cách để tránh sự cố bạn gặp phải:

select u from User u left join fetch u.cars where u.id = :id; 
select u from User u left join fetch u.friends where u.id = :id; 
+1

Rất vui được biết. Nó không trực quan rõ ràng rằng truy vấn scond sẽ thực sự cư tập hợp bạn bè trên cùng một thực thể người dùng được tải bởi truy vấn đầu tiên.Nhưng đó là cách nó hoạt động (nhờ vào bộ nhớ cache)! –

+1

Hai truy vấn HSQL này có thể được viết bên trong một '@ NamedQuery' không? – MyTitle

+0

@MyTitle: no. Truy vấn được đặt tên là một truy vấn duy nhất, không phải là hai. –

6

Bạn vừa nhấn vào vấn đề Thu gom/Danh sách (túi).

Đây là liên kết đến "vấn đề" chính thức của Hibernate về vấn đề này: https://hibernate.atlassian.net/browse/HHH-1718. Như bạn thấy, nó đã được mở vào năm 2006 và vẫn mở.

Ngoài những gì JB Nizet đề xuất, tôi khuyên bạn nên sử dụng Đặt thay vì Bộ sưu tập hoặc Danh sách trong mô hình của bạn (nếu bạn có thể), nếu không, bạn cũng có thể chỉ định Bộ sưu tập/Danh sách của bạn dưới dạng FetchMode.SUBSELECT và tùy chọn cuối cùng (đau đớn để thực hiện), bạn có thể sử dụng @IndexColumn trên OneToMany @ của bạn/@ ManyToMany.

bài viết blog này sẽ hướng dẫn bạn vào các giải pháp thực hiện: http://jroller.com/eyallupu/entry/hibernate_exception_simultaneously_fetch_multiple

Nói cách khác, không có giải pháp để thực hiện chính xác những gì bạn muốn làm, trừ cách giải quyết.

Hy vọng điều này sẽ hữu ích!

Edit: typo

0

Không thể vì nó sẽ là quá nặng cho các ứng dụng/cơ sở dữ liệu, bạn cần phải tạo ra 2 tiêu chí riêng và lấy dữ liệu riêng biệt.

Cat cat = sess.createCriteria(Cat.class) 
       .add(Restrictions.like("name", "F%")) 
       .uniqueResult(); 

List kitten = sess.createCriteria(Kitten.class) 
        .add(Restrictions.eq("cat", cat)) 
        .createCriteria("kittens") 
        .add(Restrictions.like("name", "F%")) 
        .list(); 

List mate = sess.createCriteria(Mate.class) 
       .add(Restrictions.eq("cat", cat)) 
       .createCriteria("mate") 
       .add(Restrictions.like("name", "F%")) 
       .list(); 
Các vấn đề liên quan