Hibernate "IN" предложение как ВСЕ, а не ЛЮБОЙ - PullRequest
1 голос
/ 22 октября 2009

Я хотел бы начать с извинения за то, что не знаком с Hibernate. Я только вхожу в это, и я далеко от эксперта.

У меня есть три таблицы: Контракт, Продукты и таблица связей между ними, чтобы определить отношение многие ко многим.

Я пытаюсь написать HQL-запрос, чтобы вернуть все контракты, которые содержат диапазон продуктов. К сожалению, синтаксис IN работает как Any вместо All. Поэтому, если мне нужны все контракты, в которых есть ProductA, ProductB и ProductC, ключевое слово IN вернет мне контракты, в которых есть какой-либо один из этих продуктов, вместо контрактов, в которых они есть.

Как мне структурировать мой HQL-запрос?

Ответы [ 4 ]

3 голосов
/ 22 октября 2009

Почему вы ожидаете, что IN будет вести себя как AND? Насколько мне известно, IN является своего рода OR, а не AND. IN может поэтому не быть тем, что вы ищете. Взгляните на выражения Hibernate и особенно:

  • HQL-функции, принимающие выражения пути с коллекционными значениями: size(), minelement(), maxelement(), minindex(), maxindex() вместе со специальными функциями elements() и indices, которые можно определить количественно некоторые, все, существуют, любые, в.

[...]

Функции SQL, какие-либо, некоторые, все, существуют, поддерживаются при передаче набора элементов или индексов коллекции (функций элементов и индексов) или результата подзапроса (см. Ниже):

[...]

from Show show where 'fizard' in indices(show.acts)
2 голосов
/ 10 ноября 2011

Для более чем 2000 идентификаторов в предложении in используйте подзапрос, такой как [from group where groupid in(select id from elemtable)]

В противном случае используйте критерии для устранения ошибки переполнения стека.

Пример:

 Session session = getHibernateTemplate().getSessionFactory().openSession();

 Criteria criteriaEaquals = session.createCriteria(Elements.class);
 criteriaEaquals.add(Restrictions.in("elementId", elemIds));
 criteriaEaquals.setProjection(Projections.distinct(Projections.property("type")));
 List list = criteriaEaquals.list();

 session.close();
 System.out.println("typelistis--->"+list.toString());

 return list;
2 голосов
/ 22 октября 2009

Вы можете использовать group by / имея :

select c
  from Contract c join c.products p
 where p.name in ('A', 'B', 'C')
 group by c.id, // list ALL Contract properties
 having count(*) = 3

В качестве альтернативы вы можете использовать подзапрос , чтобы избежать перечисления всех свойств в group by:

from Contract c where c.id in (
select c.id
  from Contract c join c.products p
 where p.name in ('A', 'B', 'C')
 group by c.id
 having count(*) = 3
)

Очевидно, что «3» нужно будет заменить на фактическое количество наименований продуктов, которые вы указываете в пункте in.

0 голосов
/ 22 октября 2009

В блоге Я просматривал такие спящие запросы, взгляните на пример # 4.

Вот снимок (замените статьи контрактами, а теги продуктами):

String[] tags = {"Java", "Hibernate"};
String hql = "select a from Article a " +
                "join a.tags t " +
                "where t.name in (:tags) " +
                "and a.id in (" +
                    "select a2.id " +
                    "from Article a2 " +
                    "join a2.tags t2 " +
                    "group by a2 " +
                    "having count(t2)=:tag_count) " +
                "group by a " +
                "having count(t)=:tag_count";
Query query = session.createQuery(hql);
query.setParameterList("tags", tags);
query.setInteger("tag_count", tags.length);
List<Article> articles = query.list();
...