views:

883

answers:

2

The use case here is to find some restricted set of Boys who have Kites with lengths in a certain range, and then optionally retrieve all of the Kites in that range belonging to those boys.

Do not assume that I know much about SQL or Hibernate.

I would like to form a Hibernate Criteria query where an associated collection has been restricted. For example, say I have a Boy class with a bidirectional one-to-many association to the Kites class. I want to get a List of the Boys whose kites' lengths are in a range.

I can get fields (but not Boys) satisfying this goal with an HQL query:

select Boy.name from Boy 
       inner join Kite on Boy.id=Kite.boyId 
             where length >= 1;

However this attempt with Criteria always returns list.size() of zero (even though Boy Huck has a range of kites with lengths 0.1-2.0):

Criteria crit = session.createCriteria(Boy.class);
crit.add(Restrictions.eq("name", "Huck"))
    .createCriteria("kites")
    .add(Restrictions.ge("length", new BigDecimal(1.0)));
List list = crit.list();

Ideally and additionally, for each boy in this list (assuming my code worked!) I would like all of the Kites in boy.getKites() to satisfy the length restriction. This second goal may be wishful thinking.

My guess at the problem with my Criteria attempt is that the join isn't correct: I'm seeing the ff., but don't know how to fix it.

Hibernate: 
    select
        this_.id as id3_1_,
        this_.name as name3_1_,
        ...
        kites1_.id as id4_0_,
        kites1_.boyId as boyid2_4_0_,
        kites1_.length as length3_4_0_,
        ...
    from
        Boy this_ 
    inner join
        Kite kites1_ 
            on this_.id=kites1_.id         <--- Should be =boyid?
    where
        this_.name=? 
        and kites1_.length>=?
+1  A: 

Try to change to

Criteria crit = session.createCriteria(Boy.class);
crit.add(Restrictions.eq("name", "Huck"))
    .createAlias("kites", "k")
    .add(Restrictions.ge("k.length", new BigDecimal(1.0)));
List list = crit.list();

or write explicitly in HQL:

Query query = HibernateUtil.getSession().createQuery("SELECT b FROM Boy b INNER JOIN b.kites k WHERE b.name=:name AND k.length>=:length");
query.setString("name", "Huck");
query.setBigDecimal("length", BigDecimal.ONE);

If it doesn't work, you have an issue in Boys-Kites mapping (hibernate beleive that join column in both tables is "id").

FoxyBOA
Thanks, this was an excellent answer. You were absolutely right, I had an error in my association configuration. Your Criteria snippet also worked (though it gave more duplicate answers) and I learned about query parameters in the second snippet.
Glenn
A: 

Thanks for the answers. This was really a two part question: why didn't my Criteria query work and how do I get restricted associated Sets. The first part is solved by fixing the join error I pointed out and FoxyBOA encouraged me to find.

The second, more interesting question I've re-asked here.

Glenn