2012-03-29 19 views
6

Czy ktoś może mi pomóc uzyskać zapytanie Kryteria WZP dla kwerendy WZP, o której mowa poniżej.Jak napisać to zapytanie za pomocą zapytania Kryteria JPA?

SELECT p,l FROM Person p 
LEFT JOIN Language l ON (p.language = l.language and l.locale like :locale) 
AND p.name like :name 
AND p.time BETWEEN :startDate 
AND :endDate order by name asc 
+0

Czy możesz pokazać swoje implementacje dla osoby i języka? –

Odpowiedz

10

Zakładając, że osoba ma związek z Języka Oto, co można zrobić w starszej Hibernate:

Criteria criteria = entityManager.createCriteria(Person.class); 
Criteria languageCriteria = criteria.createCriteria("language"); 

languageCriteria.add(Restrictions.like("locale", locale)); 

criteria.add(Restrictions.like("name", name)); 
criteria.add(Restrictions.between("time", startDate, endDate)); 

criteria.addOrder(Order.asc("name")); 

i moja pierwsza próba w JPA 2.0:

CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
CriteriaQuery<Person> criteria = builder.createCriteria(Person.class); 
Root<Person> pRoot = criteria.from(Person.class); 
Join<Person, Language> langJoin = criteria.join("language", JoinType.LEFT); 

Predicate conjunction = builder.conjunction(); 

criteria.where(builder.and(
    builder.like(langJoin.get(Language_.locale), locale), 
    builder.like(pRoot.get(Person_.name), name), 
    builder.between(pRoot.get(Person_.time), startDate, endDate)); 

criteria.orderBy(builder.asc(pRoot.get(Person_.name))); 

Proszę dać mi znać, jeśli to dla ciebie działa.

Edytuj: Zaktualizowane zapytanie, aby użyć tylko jednego połączenia where.

+4

Ograniczenia nie są częścią specyfikacji JPA, jest to funkcja Hibernacji – perissf

+0

Masz rację, muszę przetłumaczyć na JPA 2 –

+0

Hej, po pierwsze, dzięki, powinienem umieścić to w pytaniu. Istnieje ** brak związku ** b/w osoby i język. Zarówno osoba, jak i język mają wspólną kolumnę (język (varchar)), do której się przyłączam. Problem polega na tym, że muszę wykonać ** LEFT OUTO OUT **, więc jeśli nie ma dostępnych danych językowych dla osoby, nadal powinienem być w stanie uzyskać dane osoby z obiektem języka jako zero . – user1300877

6

Chociaż odpowiedź udzielona przez johncarl została przyjęta, nie wygląda mi to na poprawne. W Javadocs do CriteriaQuery.where() powiedzieć:

ją zmodyfikować, aby ograniczyć wynik zapytania według określonej logicznej ekspresji. Zastępuje wcześniej dodane ograniczenia, o ile takie istnieją.

Jak rozumiem, każdy z kolejnych wierszy (ograniczenia dające) zastąpi ograniczeń podanych poprzednio:

criteria.where(builder.like(langJoin.get(Language_.locale), locale)); 
criteria.where(builder.like(pRoot.get(Person_.name), name)); 
criteria.where(builder.between(pRoot.get(Person_.time), startDate, endDate)); 

Oznacza to, że w końcu tylko ostatnie ograniczenie (między data początkowa i końcowa) pozostanie.

threfore Proponuję następujące modyfikacje odpowiedź johncarl za:

CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
CriteriaQuery<Person> criteria = builder.createCriteria(Person.class); 
Root<Person> pRoot = criteria.from(Person.class); 
Join<Person, Language> langJoin = criteria.join("language", JoinType.LEFT); 

Predicate[] restrictions = new Predicate[] { 
    builder.like(langJoin.get(Language_.locale), locale), 
    builder.like(pRoot.get(Person_.name), name), 
    builder.between(pRoot.get(Person_.time), startDate, endDate) 
}; 

criteria.where(builder.and(restrictions)); 

criteria.orderBy(builder.asc(pRoot.get(Person_.name))); 

Jednak ten kod wygląda naprawdę brzydki! Zmodyfikuj je, jeśli są błędne i skomentuj je, jeśli znajdziesz lepsze rozwiązanie! Byłbym wdzięczny!

+0

Dziękuję za twoją podpowiedź. criteria.where (...) nie mogą być używane przyrostowo, ponieważ zastępują one kryteria potencjalnie przejęte przed zakończeniem. z drugiej strony działa jedna kwestia builder.and ("array of where predicates"). Świetne rozwiązanie, pho312 :) – Hartmut

+0

Dziękujemy za świetną wskazówkę! Całkowicie kochałem twoje podejście. Po prostu dodałbym, że można utworzyć ArrayList i po prostu dodawać kryteria w miarę ich pojawiania się. Z drugiej strony, nie wiem dlaczego, ale pRoot.get (Person_.name) nie działa dla mnie. Anume Otrzymuję błąd w składni Person_. – moldovean

Powiązane problemy