Makis Arvanitis
Makis Arvanitis

Reputation: 1195

Hibernate "not in" problem

I am trying to create a "not in" query using hibernate Criteria. What I am trying to get is all the persons that don't know this language, so I have an entity that looks like:

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

public class Language {

    public Long id;
    public String label;
}

and my criteria code that looks like

Criteria cr = createCriteriaForPerson() // created criteria 

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

this returns all the persons including the ones that have the language.

If I try to search for the persons that have know the specific language, then the equivalent query returns the correct results

Criteria cr = createCriteriaForPerson() // created criteria 

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

What could be the problem?

Thanks Makis

Upvotes: 0

Views: 2705

Answers (1)

axtavt
axtavt

Reputation: 242726

I'm pretty sure that you cannot express this query in Criteria API without using sqlRestriction.

Naive approach produces a query like this:

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

It's obviously not what you want since other languages are still selected.

To express the desired query you need a complex join

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

or subquery

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

Since Criteria API doesn't support joins with extra conditions, the only way to express this query is to use sqlRestriction with a subqery (exact form of the subqery depends on your database schema):

cr.add(Restrictions.sqlRestriction(
    "not exists (select ... where l.person_id = {alias}.id and ...)"));

Upvotes: 2

Related Questions