-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: Subquery on an Embeddable object
PostPosted: Mon Jun 29, 2009 3:30 am 
Newbie

Joined: Mon Jun 29, 2009 3:11 am
Posts: 3
Hi forum,

I'm struggling to find the answer to this question, and I hope one of the experts here will show how it's done.

I have three (simplified for the question) classes:

Code:
@Entity
class Person {
  @Id
  long id;
  @CollectionOfElements(fetch = FetchType.LAZY)
  List<PersonSkill> skills;
}

@Embeddable
class PersonSkill {
  @ManyToOne
  Skill skill;
  short level;
}

@Entity
class Skill {
  @Id
  long id;
  String name;
}


I have a list of Person objects that I get with this:

Code:
Criteria criteria = sessionManager.getSession().createCriteria(Person.class);


I want to add a subquery to this, so I only get persons that have, for example, a Skill "Java coding" with skill level 3.

And to make things more difficult, I'll have any number of (skill, level) pairs that need to be matched. For example, "Java coding" at 3 and "SQL" at 5.

This is easy to do with SQL, but I haven't yet figured out how to do it with Hibernate. Here's one of my attempts at it:

Code:
Criteria criteria = sessionManager.getSession().createCriteria(Person.class);
DetachedCriteria skillCriteria = DetachedCriteria.forClass(PersonSkill.class, "skill");
skillCriteria.add(Restrictions.eq("skill.id", skillId));
skillCriteria.add(Restrictions.ge("skill.level", level));
criteria = criteria.add(Subqueries.exists(skillCriteria));


This gives me a MappingException "Unknown entity: ...PersonSkill".

I hope one of you will set me on the right track.

Thank you for your time.

Bo Thorsen,
Monty Program AB.


Top
 Profile  
 
 Post subject: Re: Subquery on an Embeddable object
PostPosted: Mon Jun 29, 2009 5:37 am 
Newbie

Joined: Mon Jun 29, 2009 3:11 am
Posts: 3
Just to make it clear, here is the SQL statement I need to execute. In this case, I'm searching for persons that have the skill with id 1 and a level higher than 2:

Code:
SELECT * FROM Person WHERE EXISTS (SELECT * FROM Person_skills WHERE Person_skills.Person_id = Person.id AND Person_skills.skill_id = 1 AND Person_skills.level > 2);


Adding more skill searches is just a matter of adding more of the last two parts of this statement.


Top
 Profile  
 
 Post subject: Re: Subquery on an Embeddable object
PostPosted: Tue Jun 30, 2009 4:53 am 
Newbie

Joined: Mon Jun 29, 2009 3:11 am
Posts: 3
I found the answer myself.

There is no way currently to create a Criteria based search using projections, aliases, subqueries or any other standard Criteria based class on a CollectionOfElements.

The only way to do this is to use Restrictions.sqlRestriction. In my case from above, I did this:

Code:
criteria.add(Restrictions.sqlRestriction(
  "id IN (SELECT Person_id from Person_skills WHERE level >= X AND skill_id = Y)"));


With X and Y replaced, of course.

This works by simply adding a WHERE clause to the search, and is not optimal for MariaDB (or MySQL), but at least it works.

Bo Thorsen,
Monty Program AB.


Top
 Profile  
 
 Post subject: Re: Subquery on an Embeddable object
PostPosted: Wed Jul 01, 2009 1:31 pm 
Newbie

Joined: Mon Jun 22, 2009 12:11 pm
Posts: 5
Great find. I had a similar problem, and this seems to be the only solution. What would be even more slick is if we could made X and Y bind variables.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.