73

I'd like to use Hibernate's criteria api to formulate a particular query that joins two entities. Let's say I have two entities, Pet and Owner with a owner having many pets, but crucially that association is not mapped in the Java annotations or xml.

With hql, I could select owners that have a pet called 'fido' by specifying the join in the query (rather than adding a set of pets to the owner class).

Can the same be done using hibernate criteria? If so how?

Thanks, J

Fortyrunner
  • 12,375
  • 4
  • 29
  • 53
Snukker
  • 1,903
  • 3
  • 17
  • 18

5 Answers5

79

This is indeed possible with criteria:

DetachedCriteria ownerCriteria = DetachedCriteria.forClass(Owner.class);
ownerCriteria.setProjection(Property.forName("id"));
ownerCriteria.add(Restrictions.eq("ownername", "bob"));

Criteria criteria = getSession().createCriteria(Pet.class);
criteria.add(Property.forName("ownerId").in(ownerCriteria));

Update: This actually performs a sub-query instead of a join but it allows you to use Criteria on two entities that do not have a hibernate relationship defined.

Pierre Pretorius
  • 2,789
  • 18
  • 21
  • 2
    why there are so many up-votes? It still two different criteria right? – Reddy Mar 10 '11 at 09:04
  • 37
    Problem is this is not a join, but subquery - that means that you can't order your results by a column from first criteria. – Martin Lazar May 11 '11 at 08:13
  • 1
    I guess it becomes sub-query instead of a join – Reddy Jul 12 '11 at 13:12
  • I had to do a query between a table and a view and there was no explicit association. This worked fine. – Angela Jul 10 '12 at 04:07
  • How do i retrieve the result? Can i get it as List> ? – Trind Jun 18 '13 at 21:07
  • Agree with Jonas Stensved. – Ankit Sep 05 '14 at 06:08
  • I think @Pierre is right, although we should ALL be careful when using detached criterias or subqueries. Sometimes, we only need to join those tables in order to filter the results and not to retrieve the joined entity. Check the question. Fortyrunner asked how to filter owners with restrictions over unmapped relationships, not how to make an inner join. – coya Nov 23 '16 at 01:58
  • If owner and pet is mapped in java, are these codes doing join query? – Jiayi Zhou Dec 06 '16 at 01:49
62

My understanding is that if you do this using HQL, you are creating a Cartesian join with a filter, rather than an inner join. Criteria queries do not support doing this.

David M
  • 68,374
  • 13
  • 151
  • 181
1

In NHibernate you can use subqueries which are defined as DetachedCriteria. Not sure if it works the same in Java, most probably it is the same:

DetachedCriteria pets = DetachedCriteria.For<Pet>("pet")
  .SetProjection(Projections.Property("pet.ownername"))
  .Add(/* some filters */ );

session.CreateCriteria(typeof(Owner))
  .Add(Subqueries.PropertyIn("name", pets);

Assumed that it is joined using the name of the owner.

Stefan Steinegger
  • 60,747
  • 15
  • 122
  • 189
0
Criterion ownerCriterion = Restrictions.sqlRestriction(SELECT ownerId FROM   Owner WHERE ownerName ='bob');
Criteria criteria = getSession().createCriteria(Pet.class);
criteria.createCriteria("ownerId").add(ownerCriterion);
javasmith
  • 11
  • 2
-2

There's a SQLCriterion, which you can give arbitrary SQL, and add to your Criteria. In the SQL string, the token {alias} "will be replaced by the alias of the root entity."

Tom11
  • 2,199
  • 6
  • 26
  • 50
tpdi
  • 32,745
  • 10
  • 74
  • 117