views:

3928

answers:

4

I'm trying to build a query with hibernate criteria for the following scenario:

  • Two entities: Indicator and report (each with their own tables, classes etc.)
  • an indicator can be used in zero to many reports
  • a report uses zero to many indicators
  • therefore, I have an intersection table to store the relationship
  • the relationship is defined in both classes and their hibernate mappings
  • in the UI, the user can select one or many reports (among other things), and I would like to query the DB for the Indicators used in these reports

I've tried the following:

criteria.add(Restrictions.in("Reports", selectedReports));

but all I get is a strange SQL Statement with

where this_.Indicator_ID in (?)

and then a JDBC exception (missing parameter)

Any ideas? Thanks.

Note: I've looked into Querying ManyToManyrelationship with Hibernate Criteria, but the accepted solution there is to build a custom sql-string ...

A: 

Sounds like you're thinking about SQL too much and not enough about objects.

Hibernate is an ORM tool. An m:n relationship should be written in terms of the objects. If a Foo has a Set, and a Bar a Set, that's the proper starting place.

I know that Hibernate will generate a JOIN using a join table, but if you're only thinking in terms of the SQL why use Hibernate at all?

duffymo
The template notation didn't come through. That should read "Foo has a Set of Bar, and a Bar a Set of Foo..."
duffymo
Okay .. what's your suggestion? I somehow need to find all indicators that are used in a couple of reports (or all foos that are referenced by a couple of bars) ...
IronGoofy
If you know how to write the SQL, simply execute it and map the ResultSet into a form that your report can use.
duffymo
That's too "SQLy" .. I'd like to express the query in Hibernate using Criteria ...
IronGoofy
Then I'll disagree - I'd use the right tool for the job.
duffymo
+2  A: 
  Criteria c = session.createCriteria(Indicator.class);
    c.add(Restrictions.eq("someField", myObject).createCriteria("reports")
    .add(Restrictions.eq("reportName", name);
    c.list();

You need to create a sub criteria to the entity that is being held in a collection on some other entity.

String[] selectedReportsId = {"1", "2", "3"};
 c.add(Restrictions.eq("someField",myObject).createCriteria("reports")
    .add(Restrictions.in("id", selectedReportsId);

Then check out the bit about transforming the results from here: http://www.hibernate.org/hib_docs/v3/reference/en-US/html/querycriteria-associations.html

Also this may shed some light on what you can do w/ criteria: http://www.hibernate.org/hib_docs/v3/api/org/hibernate/criterion/Restrictions.html

zmf
Okay, this allows my to query fields of the report class - halfway there! But I have a Collection<Report> selectedReports that I'd like to use in my query ..
IronGoofy
Thanks for the links ..Any way to directly use the Collection<Report> I have? For a many-to-one property (e.g. Owner) I can simply use criteria.add(Restrictions.in("Owner", selectedOwners));
IronGoofy
NO new news .. think I'll just accept this answer. Thanks for the help!
IronGoofy
A: 

If you must, here are a couple of suggestions that Google came back with after searching for "hibernate hql many-to-many":

http://patf.net/blogs/index.php?blog=2&amp;c=1&amp;more=1&amp;pb=1&amp;tb=1&amp;title=many_to_many_in_hql

And from the Hibernate forums:

http://forum.hibernate.org/viewtopic.php?p=2340747&amp;sid=d4c8d2fcc16aed0201f73eb74619692a

And from the Spring forums:

http://forum.springframework.org/showthread.php?t=36870

Hope these help.

duffymo
Thanks for the links, but I'm trying to use Criteria (not HQL). I've tried to google, but no success so far ...
IronGoofy
You ARE using HQL when you use Criteria, because it uses HQL behind the scenes: http://www.developer.com/java/ent/article.php/3322131
duffymo
That may be true, but the code I'm trying to write does not use HQL directly. I may be stretching the limits, but I'd like to see how far I can take Criteria without reverting direct HQL (or SQL for that).
IronGoofy
Very good, sorry I'm not more helpful. I hope someone else can answer - we'll both learn something then. Good luck.
duffymo
I'll post if I figure something out .. zmf seems to be on the right track. Thanks anyways :-)
IronGoofy
A: 

For now, this is how I got it to work (thanks to zmf).

Criteria subcrit = criteria.createCriteria("Reports");
Disjunction dis = Restrictions.disjunction();
for (Reports r : selectedReports) {
    dis.add(Restrictions.idEq(r.getID()));
}
subcrit.add(dis);

This is almost exactly what zmf suggested, all I added was the disjunction to build the criteria from the Collection that is passed around.

All that's left to do is to try to use the collection directly ...

IronGoofy