Спящий "не в" проблема - PullRequest
0 голосов
/ 11 мая 2011

Я пытаюсь создать запрос «не в», используя критерии гибернации.То, что я пытаюсь получить, это все люди, которые не знают этот язык, поэтому у меня есть объект, который выглядит как:

public class Person {
    ...
    private List<Language> languages;
    ...
}

public class Language {

    public Long id;
    public String label;
}

, и мой код критерия, который выглядит как

Criteria cr = createCriteriaForPerson() // created criteria 

cr.createCriteria("languages").add(Restrictions.not(Restrictions.in("id", values)));

это возвращает всех людей, включая тех, кто владеет языком.

Если я пытаюсь найти людей, которые знают конкретный язык, то эквивалентный запрос возвращает правильные результаты

Criteria cr = createCriteriaForPerson() // created criteria 

cr.createCriteria("languages").add(Restrictions.in("id", values));

В чем может быть проблема?

Спасибо, Макис

1 Ответ

2 голосов
/ 11 мая 2011

Я почти уверен, что вы не можете выразить этот запрос в Criteria API без использования sqlRestriction.

Наивный подход приводит к следующему запросу:

select p from Person p join p.languages l where l.id not in :values

Это явно не то, что вы хотите, так как другие языки все еще выбраны.

Для выражения желаемого запроса вам необходимо сложное объединение

select p from Person p left join p.languages l with l.id in :values where l is null

или подзапрос

select p from Person p where not exists 
    (select l from Language l where l in elements(p.languages) and l.id in :values)

Поскольку Criteria API не поддерживает объединения с дополнительными условиями, единственный способ выразить этот запрос - использовать sqlRestriction с подзапросом (точная форма подзапроса зависит от схемы вашей базы данных):

cr.add(Restrictions.sqlRestriction(
    "not exists (select ... where l.person_id = {alias}.id and ...)"));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...