2013-08-16 12 views
11

Mam kryteria, które zwraca wszystkie dane aplikacja wymaga zasadniczo:Hibernate Kryteria: odrębne podmioty i następnie ograniczyć

Criteria criteria = session.createCriteria(Client.class); 
criteria.createAlias("address", "address"); 
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 
criteria.setFirstResult(init); 
criteria.setMaxResults(max); 
List<Client> clients = criteria.list(); 

Problem polega na tym, że klient relacja/adres jest dwukierunkowy: na klient ma jeden adres i jeden adres może należeć do więcej niż jednego klienta.

Chcę pobrać "pojedynczych" obiektów klienckich na podstawie ich pk oczywiście, pewną liczbę klientów, ponieważ są one wyświetlane w tabeli.

Ponieważ polecenia setFirstResult/setMaxResults są wykonywane jako pierwsze, otrzymuję zduplikowanych klientów w ramach już zastosowanych limitów. Po tym, jak (poziom aplikacji został użyty jako nie przez grupę), hibernacja uzyskuje zrzuty duplikatów klientów, więc kończę na mniejszej liczbie klientów niż maksymalna podana w setMaxResults.

Nie można grupować według grupy (grupy projekcji), ponieważ nie zwraca wszystkich kolumn wymaganych w kliencie/adresie, tylko grupa, do której zgrupowane jest zapytanie.

(Podsumowując, Moja tabela ma 100 wyników na stronę, ale po odrzuceniu duplikatów mam 98 wyników zamiast 100 ...), ponieważ limit: LIMIT 0,100 jest stosowany PRZED hibernacji, kiedy powinien zostać wykonany PO)

Odpowiedz

7

Jak wskazuje się w wątku połączonych „Ashish Thukral” następnym wierszu rozwiązuje to:

criteria.setFetchMode("address.clients", FetchMode.SELECT); 

To zapobiega łączeniu że przyczyną problemu zostać wykonany.

Oczywiście możliwe jest usunięcie fetch = "join" z pliku konfiguracyjnego xml, ale to rozwiązanie nie ma wpływu na inne miejsca, w których można pobierać ziarna.

+0

FetchMode.SELECT naprawił to dla mnie - inne tryby nie działają w tym przypadku. –

+0

FetchMode.SELECT jest świetny ... z wyjątkiem tego, że wymusza on szybkie pobieranie, z jakiegoś powodu. Zobacz https://docs.jboss.org/hibernate/core/3.3/api/org/hibernate/FetchMode.html Czy nie ma sposobu, aby powiedzieć hibernacji po prostu, aby zrobić "odrębny" na pk pobranego obiektu ?? Wydaje się to najbardziej oczywistą i banalną rzeczą, której pragniemy, a jak zwykle hibernacja czyni życie niezwykle skomplikowanym. – Marc

+0

Nawiasem mówiąc, robienie tego z HQL jest tak samo banalne jak się wydaje. Po prostu dodajesz słowo "odrębny" w zapytaniu. Dlaczego jest to tak boleśnie uciążliwe za pomocą API Criteria, jest poza mną. Czy wszyscy możemy zacząć korzystać z baz danych OO? – Marc

4

Jeśli szukasz klienta na podstawie identyfikatora w następujący sposób. W oparciu o twoje kryteria nie ma potrzeby stosowania maksymalnego i początkowego rozmiaru, ponieważ zawsze zwraca jednego klienta.

Criteria criteria = getSession().createCriteria(Client.class); 
criteria .add(Restrictions.eq("id", yourClientId); 
criteria.createAlias("address", "address"); 
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 
criteria.setFirstResult(init); 
criteria.setMaxResults(max); 
List<Client> clients = criteria.list(); 

Jeśli szukasz adresu na podstawie identyfikatora w następujący sposób.

Criteria criteria = getSession().createCriteria(Client.class); 
criteria.createAlias("address", "address"); 
criteria .add(Restrictions.eq("address.id", yourAddressId); 
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 
criteria.setFirstResult(init); 
criteria.setMaxResults(max); 
List<Client> clients = criteria.list(); 
+3

Dziękuję bardzo za odpowiedź, ale szukałem wszystkich klientów, zwracając je jako odpowiedź na stronach. Problem polega na tym, że strona powinna zwrócić 100 wyników, zwraca mniej po grupowaniu (DISTINCT_ROOT_ENTITY). Ta grupa powinna się wydarzyć przed limitem ... – kandan

+0

Drugi blok może spowodować mniejszą liczbę wierszy niż wysłanych przez @Kandan w jego pytaniu –

0

Jeśli dobrze rozumiem twoje relacje, będziesz miał listę klienta w adresie i jeden adres w każdej klasie Client Entity. Więc jeśli chcesz po prostu listę klientów, co w tym wielkiego, nie można po prostu je

Criteria criteria = session.createCriteria(Client.class); 
criteria.setFirstResult(init); 
criteria.setMaxResults(max); 
List<Client> clients = criteria.list(); 

Czemu stworzenie aliasu i korzystania distinct_root_entity? Jeśli potrzebujesz uzyskać ten adres, gdy uzyskasz dostęp do niego w DAO lub ServiceImpl, Hibernate i tak sprowadzi go leniwie dla ciebie.

Popraw mnie, jeśli się mylę.

+0

Dzięki. Tworzę alias wymuszający na hibernacji uzyskanie innych danych w zapytaniu, ponieważ może to być filtrowanie klientów na przykład za pomocą ich kodu pocztowego (jest to tabela z filtrami na stronach). Dostaję więc wszystkie dane, których potrzebuję: klientów z adresem.Problem polega na tym, że wraz z adresem pojawia się zestaw klientów, które mają ten adres i potrzebuję resulttransformer do ujednolicenia klientów według ich identyfikatora. Prawdopodobnie jest to możliwe, bez modyfikowania adnotacji, powiedz hibernacji, aby nie pobierał/dołączał do konkretnej kolumny dla klasy/tabeli, ale robił to w innych polach, niezależnie od tego, co określono domyślnie (leniwy lub nie). – kandan

+1

Myślę, że szukasz tego http://stackoverflow.com/questions/5567754/hibernate-criteria-n1-issue-with-maxresults?rq=1 –

+0

tak, dzięki za to. – kandan

Powiązane problemy