2012-03-07 10 views
15

Pracuję ze stanem hibernacji i mam problemy z tworzeniem kwerendy hql, która pobiera wszystkie obiekty podrzędne mojego obiektu. Na przykład: Użytkownik obiektu ma listę samochodów i listę przyjaciół.Jak przejść w lewo przy pobieraniu wielu dzieci w trybie hibernacji?

Aby uzyskać użytkownika z jego samochodów chciałbym użyć następującego zapytania:
od użytkownika u lewej dołączyć dołączyć pobierania u.cars gdzie u.id =?

Działa to dobrze, więc pomyślałem, że to będzie łatwe, aby uzyskać użytkownikowi swoich samochodach i swoich przyjaciół z następującym zapytaniem:
od użytkownika u lewej przyłączyć sprowadzić u.cars LEFT JOIN sprowadzić u.friends miarę u.id =?

Ale to daje mi następujący błąd:
HibernateException: nie można jednocześnie pobierał kilka toreb

Teraz moje pytanie brzmi: co to jest właściwa droga do pobierania wielu dzieci w hibernacji?

+0

Duplikat: http://stackoverflow.com/questions/4334970/hibernate-cannot-simultaneously-fetch-multiple-bags. Z Hibernate Use: @LazyCollection (LazyCollectionOption.FALSE) – willome

Odpowiedz

10

Co najwyżej jedna z kolekcji dla dzieci musi być torebką (tj. Zadeklarowana jako lista). Zadeklaruj pozostałe kolekcje jako Zestawy i będzie działać.

Należy jednak pamiętać, że wykonanie takich sprzężeń pobierania powoduje powstanie iloczynu kartezjańskiego wierszy. Jeśli obie kolekcje mają 100 elementów, taka kwerenda pobiera 10 000 wierszy z bazy danych. Czasami skuteczniej jest wykonać pierwsze zapytanie, które pobiera jedną kolekcję, a drugą, która pobiera drugą (co zmniejsza liczbę wierszy pobranych do 200). Jest to również sposób na uniknięcie problemu:

+1

Miło wiedzieć. Nie jest intuicyjnie oczywiste, że zapytanie scond zapełni kolekcję przyjaciół w tych samych jednostkach użytkownika załadowanych przez pierwsze zapytanie.Ale tak to działa (dzięki pamięci podręcznej)! –

+1

Czy te dwa zapytania HSQL można zapisać wewnątrz jednego '@ NamedQuery'? – MyTitle

+0

@MyTitle: nie. Nazwane zapytanie jest pojedynczym zapytaniem, a nie dwoma. –

6

Właśnie trafiłeś do wydania Collection/List (bag).

Oto link do oficjalnego "problemu" Hibernate na ten temat: https://hibernate.atlassian.net/browse/HHH-1718. Jak widać, został otwarty w 2006 roku i jest nadal otwarty.

Oprócz tego, co proponuje JB Nizet, proponuję użyć Set zamiast Collection lub List w swoim modelu (jeśli możesz), w przeciwnym razie możesz również określić swoją kolekcję/listę jako FetchMode.SUBSELECT i jako ostatnią opcję (bolesne do wdrożenia), możesz użyć @IndexColumn na swoim @ OneToMany/@ ManyToMany.

Ten artykuł blog poprowadzi Cię do rozwiązań wykonawczych: http://jroller.com/eyallupu/entry/hibernate_exception_simultaneously_fetch_multiple

Innymi słowy, nie ma rozwiązania to zrobić dokładnie to, co chcesz zrobić, z wyjątkiem rozwiązania.

Mam nadzieję, że to pomoże!

Edit: literówka

0

Nie jest możliwe, ponieważ byłoby to zbyt ciężkie dla aplikacji/bazy danych, trzeba utworzyć 2 oddzielne kryteria i pobierać dane oddzielnie.

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(); 
Powiązane problemy