Hibernate Criteria for "in subselect"
Asked Answered
S

3

11

I'm trying to do something like this, but using Criteria instead of HQL:

select user from User where user in (
    select user from UserDomain where domain.id = "XXX"
)

User being an entity having a one-to-many relationship to the join table UserDomain. The point here is simply to find Users that are linked to a Domain having id = "XXX".

This seems like it should be very simple... but I'm having no luck so far turning up any useful docs.

Spirituality answered 6/12, 2013 at 14:45 Comment(0)
S
3

I finally found it. Turns out it wasn't so hard after all... once you know!

criteria = criteria.createCriteria(User.USER_DOMAINS).add(Restrictions.eq(UserDomain.DOMAIN, domain));

Yep, there is was, staring me right in the face in the Javadoc: http://www.dil.univ-mrs.fr/~massat/docs/hibernate-3.1/api/org/hibernate/Criteria.html

Spirituality answered 6/12, 2013 at 15:22 Comment(0)
D
28

The subquery is very useful in cases, that you need to search the User, having one-to-many UserDomains. In that case, the WHERE UserId IN (subquery) brings big advanatage: we are still working with a flat User table/entity... so we can do the proper paging.

Here is the documentation 15.8. Detached queries and subqueries

The draft could be: subquery:

DetachedCriteria userSubquery = DetachedCriteria.forClass(UserDomain.class, "ud")
    // Filter the Subquery
    .add(Restrictions.eq(UserDomain.DOMAIN, domain))
    // SELECT The User Id  
    .setProjection( Projections.property("ud.userId") );

And the main query:

Criteria query = session.createCriteria(User.class, "u")
    .add( Subqueries.propertyIn("u.id", userSubquery) );

Now we have a query, which could be used for paging

Dittmer answered 6/12, 2013 at 15:34 Comment(2)
On small correction, I think you meant ".add(Subqueries.propertyIn("id", userSubquery))". Your example causes some cryptic class cast exceptions.Fridlund
As a side note: you may encounter 'Class Cast Exception' as I did if you try to change Subqueries.propertyIn("u.id", userSubquery) to Subqueries.eq("u.id", userSubquery) - don't do that even if there is a single match for a subquery.Bequest
J
3

In clauses usualy can be transformed into join. Tyr this:

Criteria c = session.createCriteria(User.class, "u");
c.createAlias("u.userDomain", "ud"); // inner join by default
c.add(Restrictions.le("ud.id", 1));
Jenny answered 6/12, 2013 at 15:2 Comment(1)
No, there is no "u.userDomain" relationship. User.userDomains is a to-many relationship to the join table UserDomain.Spirituality
S
3

I finally found it. Turns out it wasn't so hard after all... once you know!

criteria = criteria.createCriteria(User.USER_DOMAINS).add(Restrictions.eq(UserDomain.DOMAIN, domain));

Yep, there is was, staring me right in the face in the Javadoc: http://www.dil.univ-mrs.fr/~massat/docs/hibernate-3.1/api/org/hibernate/Criteria.html

Spirituality answered 6/12, 2013 at 15:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.