I recently figured out how to perform subqueries with the criteria facility in hibernate aproximately 2.1.4 and later. Note this example works in hibernate 2.1.4 and later and has not been tested in hibernate 3.
For purposes of example, we have three tables/objects in our data model. We have a 'person', 'car', and 'carOwner' tables/objects. The carOwner table has two foriegn key colums, one to car and one to person, called 'car' and 'owner' repectively. Both these relationships are defined as one-to-many from the car/person table to the carOwner table, defined as 'cars' and 'owners' respectively. The carOwner table has many-to-one relationships mapping back to person and car.
For this example, we would like to query for cars that have been owned by the same three people. so the query will look something like the following:
Code:
cars = hibernateSession.createCriteria(Car.class)
.add(example)
.createCriteria("owners")
.add(Expression.eq("owner", person1))
.createCriteria("car")
.createCriteria("owners")
.add(Expression.eq("owner", person2))
.createCriteria("car")
.createCriteria("owners")
.add(Expression.eq("owner", person3))
.list();
This code only returns cars who have been owned by person1, person2, and person3 where person1, person2, person3 are person objects mapped to the person table. The leap of intuition for me was realizing I could in effect "walk" the object model back from the many-to-many table "carOwners" back to the car table by the createCriteria("car") statements, where I could then define a new subquery on the carOwner table.
The second line demonstrates the use of the example. the properties specified in the example are applied to the subqueries without needing to repeat the line in each subquery. For example this could allow me to modify the query so that only Fords owned by all three people are returned (assuming Ford is specified in the example).
-s