2016-05-12 41 views
6

Próbuję napisać kwerendę podobną doCriteria API wyniki graniczne w podzapytanie

select * from Table a 
where a.parent_id in 
    (select b.id from Table b 
    where b.state_cd = ? 
    and rownum < 100) 

pomocą Criteria API. Mogę osiągnąć zapytanie bez ograniczeń rownum na Podzapytanie grzywny stosując podobny kod do https://stackoverflow.com/a/4668015/597419 ale nie mogę wydawać się, aby dowiedzieć się, jak appose limit na Subquery

+0

Jeśli nie możesz dowiedzieć się, jak ograniczyć podzapytanie, a może użyć funkcji łączenia? – Traubenfuchs

+1

@Traubenfuchs W zapytaniu powinno być więcej niż 100 wyników. Pomyśl o tym, że podzapytanie jest rekordem nadrzędnym, a wyniki, które chcę, z powrotem jako dzieci. Niektórzy rodzice mają wiele dzieci. Nie rozumiem, w jaki sposób udało mi się znaleźć dzieci dla pierwszych 100 rodziców korzystających z join. – Danny

+0

Klauzula where jest dynamiczna i zazwyczaj jest to więcej niż pierwsze X wierszy w tabeli. Powinienem o tym wspomnieć w pytaniu. – Danny

Odpowiedz

7

W Hibernate, można dodać rzeczywiste ograniczenie SQL, ale warto zauważyć, że będzie to specyficzne dla Oracle. Jeśli przełączyłeś się na PostgreSQL, to by się zepsuło i potrzebowałbyś zamiast tego LIMIT 100.

DetachedCriteria criteria = DetachedCriteria.forClass(Domain.class) 
    .add(Restrictions.sqlRestriction("rownum < 100")); 

W JPA API, krótka odpowiedź jest taka, że ​​nie można ... W swoim pytaniu pan zaproponował używając API kryteria (wraz z podzapytania). Jednak dopiero gdy zadzwonisz pod numer EntityManager.createQuery(criteriaQuery), otrzymasz numer TypedQuery, w którym możesz podać wartość maxResult.

To powiedziawszy, można podzielić go na 2 pytania, pierwsze, gdzie można uzyskać wewnętrzne-select wyniki (max 100), a następnie 2-ta Criteria gdzie wziąć wynikowej liście w in():

// inner query 
CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery<YourClass> innerCriteriaQuery = cb.createQuery(YourClass.class); 
Root<YourClass> yourClass = innerCriteriaQuery.from(YourClass.class); 

innerCriteriaQuery.select(yourClass).where(
    cb.equal(yourClass.get(YourClass_.stateCode), someStateValue)); 

// list of 100 parent ids 
List<YourClass> list = em.createQuery(innerCriteriaQuery).setMaxResults(100).getResultList(); 

// outer query 
CriteriaQuery<YourClass> criteriaQuery = cb.createQuery(YourClass.class); 
Root<YourClass> yourClass = criteriaQuery.from(YourClass.class); 

criteriaQuery.select(yourClass).where(
    cb.in(yourClass.get(YourClass_.parentId)).value(list); 

return em.createQuery(criteriaQuery).getResultList(); 
+0

To jest za pomocą interfejsu API Hibernate, a nie [API Kryteriów] (http://docs.oracle.com/javaee/6/tutorial/doc/gjitv.html) – Danny

+0

Nadzór z mojej strony ... dodał informacje o API jako dobrze. Niestety, nie ma sposobu, aby to zrobić z jednym 'Criteria'. –

+0

To jest pomocne, ale nadal nie jest idealną odpowiedzią dla mnie. Są chwile, w których lista będzie wynosić ponad 1000 pozycji, niestety Oracle ma limit tylko 1000 pozycji w klauzuli "w". Nadal nie widzę niczego w API, które pozwala mi używać 'rownum' w podzapytaniu, więc prawdopodobnie będę musiał pójść tą trasą i wykonać wiele zapytań ograniczających każdy z nich do 1000 pozycji. – Danny