2016-05-12 3 views
6

Я пытаюсь написать запрос, похожий наКритерии API предельных результатов в подзапрос

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

с использованием Criteria API. Я могу достигнуть запрос без ограничения RowNum на подзапрос штрафа, используя аналогичный код для https://stackoverflow.com/a/4668015/597419, но я не могу понять, как соединять ограничение на Subquery

+0

Если вы не можете понять, как ограничить подзапрос, как насчет использования соединения? – Traubenfuchs

+1

@Traubenfuchs В запросе должно быть более 100 результатов. Подумайте о том, что подзапрос - это родительские записи и результаты, которые я хочу вернуть в качестве детей. У некоторых родителей несколько детей. Я не вижу, как я мог бы найти детей для первых 100 родителей, используя соединение. – Danny

+0

Предложение where является динамическим, и обычно это больше, чем только первые X строк в таблице. Я должен был упомянуть об этом в вопросе. – Danny

ответ

7

В Hibernate, вы можете добавить фактическое ограничение SQL, но стоит отметить, что это будет характерно для Oracle. Если вы перейдете на PostgreSQL, это сломается, и вам понадобится LIMIT 100.

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

В JPA API, короткий ответ, что вы не можете ... В своем вопросе вы предложили использовать Criteria API (наряду с подзапрос). Однако только после того, как вы на самом деле позвоните EntityManager.createQuery(criteriaQuery), вы получите TypedQuery, где вы можете указать значение maxResult.

Это говорит, вы можете разбить его на 2 запросов, то первое, где вы получите внутрипартийные выбрать результаты (не более 100), а затем второй Criteria, где вы берете полученный список в 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

Это API-интерфейс Hibernate, а не API [Criteria API] (http://docs.oracle.com/javaee/6/tutorial/doc/gjitv.html) – Danny

+0

Надзор с моей стороны ... добавил специфическую для API информацию Что ж. К сожалению, нет возможности сделать это с помощью одного «критерия». –

+0

Это полезно, но все же не идеальный ответ для меня. Бывают случаи, когда этот список будет содержать более 1000 наименований, к сожалению, у Oracle есть предел только 1000 позиций в предложении 'in'. Я все еще ничего не вижу в API, который позволяет мне использовать «rownum» в подзапросе, поэтому мне, вероятно, придется идти по этому маршруту и ​​выполнять несколько запросов, ограничивая каждый из 1000 элементов. – Danny

Смежные вопросы