-->
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.  [ 18 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Restrictions to join part of the query?
PostPosted: Mon Nov 27, 2006 8:03 am 
Newbie

Joined: Mon Nov 27, 2006 6:16 am
Posts: 5
Edit: I solved the problem describe below using HQL and currently I am looking for answers to these questions:

1. Is there any way, how to apply extra join conditions using Criteria API? (The "with" keyword in HQL)
2. Is there any way, how to specify join order using parentheses in HQL / Criteria API?



I was not able to find this in the documentation or anywhere on the web and I wonder, why nobody has raised this question anywhere (though I found related problems on the forum, which have not been replied by anybody).

The problem is related to left outer join.

Simple scenario. Parent(id) and Child(id, age). There is a relation (1..n) called "children" between Parent and Child. Parent(A) has no children, Parent(B) has three Children aged 10, 20 and 30.

Code:
Criteria parentCriteria = session.createCriteria(Parent.class);
Criteria childCriteria = parentCriteria.createCriteria("children", Criteria.LEFT_JOIN);
childCriteria.add(Restrictions.ge("age", new Long(15)));


...generates...

Code:
select parent.id, child.id, child.age
from Parent parent
left outer join Child child on parent.id=child.fk_parent_id
where child.age>=15;


I only get 2 results:
    Parent(B)+Child(20)
    Parent(B)+Child(30)

The result I need is what I need from a left outer join:
    Parent(A)+null
    Parent(B)+Child(20)
    Parent(B)+Child(30)

... in other words, I need this generated SQL query:

Code:
select parent.id, child.id, child.age
from Parent parent
left outer join Child child on parent.id=child.fk_parent_id and child.age >15


My questions:
1. How can I achieve the needed result? Something, that would show me, that I missed some part of the Hibernate technology. A workaround would be nice too (a only came with adding a isNull() restriction to the criteria).


.... if question 1 has no solution in Hibernate/Criteria API/HQL

2. What is the point of adding restrictions to SubCriteria object, when they are always applied to the same where clause in the generated SQL. Is this only for the purpose of method chaining?

3. Does this mean, that the left outer join mode for fetching associations is useless once I apply a restriction to the resulting set ?


Last edited by igor.inas on Mon Nov 27, 2006 10:33 am, edited 3 times in total.

Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 27, 2006 8:17 am 
Regular
Regular

Joined: Sat May 20, 2006 3:49 am
Posts: 78
from the docu:
Code:
15.5. Dynamic association fetching
You may specify association fetching semantics at runtime using setFetchMode().

List cats = sess.createCriteria(Cat.class)
    .add( Restrictions.like("name", "Fritz%") )
    .setFetchMode("mate", FetchMode.EAGER)
    .setFetchMode("kittens", FetchMode.EAGER)
    .list();
This query will fetch both mate and kittens by outer join.


Try to use setFetchMode().


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 27, 2006 8:29 am 
Newbie

Joined: Mon Nov 27, 2006 6:16 am
Posts: 5
maitscha wrote:
Try to use setFetchMode().


That is not the problem I have. Again, the problem is, that I need to apply a restriction to a different part of a query. Not in the global where clause, but the on part of the join clause to limit the results of a subresult before joining it with the root table. I originally thought, that this could be achieved by calling add(Restriction) on particular SubCriteria objects.

Since it makes no difference which Criteria object gets a restriction applied, I am afraid, this is not possible in Hibernate at all, but I would like to hear a confirmation from someone else.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 27, 2006 8:59 am 
Newbie

Joined: Mon Nov 27, 2006 6:16 am
Posts: 5
Ok, I found how to supply extra join conditions in HQL. My bad :(

Code:
You may supply extra join conditions using the HQL with  keyword.

from Cat as cat
    left join cat.kittens as kitten
        with kitten.bodyWeight > 10.0


Now I will try to find a way, how to do it in Criteria API.... If anybody knows, before I post here again, please reply.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 27, 2006 11:23 am 
Senior
Senior

Joined: Tue Aug 23, 2005 8:52 am
Posts: 181
Did you checkout Section 15.4 of the reference docs
Code:
List<Cat> cats = sess.createCriteria(Cat.class)
                                   .createAlias("kittens", "kt")
                                   .add(Restrictions.gt("kt.bodyWeight", new Float(10.0)))
                                   .list();


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 27, 2006 12:37 pm 
Newbie

Joined: Mon Nov 27, 2006 6:16 am
Posts: 5
rajasaur wrote:
Did you checkout Section 15.4 of the reference docs
Code:
List<Cat> cats = sess.createCriteria(Cat.class)
                                   .createAlias("kittens", "kt")
                                   .add(Restrictions.gt("kt.bodyWeight", new Float(10.0)))
                                   .list();

When working with outer joins (left in this case), there is a difference if you put restriction to the where part of the SQL query or to the join condition part.

The example you supplied would put the restriction on the kittens weigth to the where clause of the whole query, and eliminating all cats that have no kittens. Cats with no kittens (cats + null results of the left join) get eliminated by the restriction.

This can be solved by with keyword in the HQL query. Remaining questions are:
1. Is the any equivalent for "with" keyword in Criteria API?
2. Is there any way how to specify join order in the HQL? The default is (((A join B) join) C) join D. Is it possible with HQL or Criteria API to perform e.g: (A join B) join (C join D) ? I checked the HQL grammar and it seems that parentheses are not allowed.


Top
 Profile  
 
 Post subject: "with" keyword functionality in Criteria
PostPosted: Fri Apr 27, 2007 3:29 am 
Newbie

Joined: Tue Apr 17, 2007 4:02 am
Posts: 10
igor.inas wrote:
rajasaur wrote:
1. Is the any equivalent for "with" keyword in Criteria API?


I'll second that - would love to see something equivalent to hql "with" keyword in Criteria. Or there is something like it in Criteria already?


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 01, 2007 5:45 am 
Newbie

Joined: Mon Apr 30, 2007 12:27 pm
Posts: 18
Hi!, Im facing the some problem that you had some time ago, did you come up with a solution for this eventually?

I can see no way to do this join with the criteria api, although with hql is so easy,

Any help would be very appreciate.

Cheers.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 21, 2008 5:15 am 
Newbie

Joined: Mon Jul 21, 2008 5:12 am
Posts: 13
Any progress on this issue?
I have a great improovement of perfomance if i use extra conditions in outer join instead of where cause...
from 41 seconds to 110ms...

Is it possible now?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 21, 2008 6:19 pm 
Newbie

Joined: Thu Aug 21, 2008 5:32 pm
Posts: 4
Location: Slovakia
I just spent several hours trying to track this down, and at last landed on this thread. I'm sad to see there hasn't been any solution posted for almost 2 years - if there isn't a solution here on this forum, it most likely means that it's still not possible to do this using the Criteria API. :(

I found a JIRA issue that I believe is closely related to this:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2308

I think the only thing we can do now is vote for it, right?


Top
 Profile  
 
 Post subject: Nice workaround
PostPosted: Sun Aug 24, 2008 8:31 am 
Newbie

Joined: Thu Aug 21, 2008 5:32 pm
Posts: 4
Location: Slovakia
Going through the comments posted under the JIRA listed above, Theo Platt came with a very nice workaround - actually the best workaround that I found so far, and works nicely for me. I'm posting it here for those in need, since I know how hard it was for me to find it.

The workaround is to apply a Hibernate filter on the collection - a filter allows you to put the condition/restriction on the JOIN part of the query rather than WHERE when applied to a collection (if you let hibernate display the SQL it generates, it will add this to the ON clause it generates for the join).

Here's what you need to do:
  1. Create a filter using either the @FilterDef annotation or <filter-def> if you're using XML files.
  2. Apply the filter to your collection (in the parent table) using @Filter annotation or <filter>
  3. When executing your Criteria API based query, make sure you enable your filter and supply the required parameter

I had a hard time figuring out the right way to specify the filter's condition applied to my collection to get it working, so if anyone needs more help, just let me know.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 11, 2008 5:09 am 
Newbie

Joined: Wed Oct 22, 2008 10:20 pm
Posts: 11
Hi immutability,

Is the Hibernate filter working for left outer join using criteria api?

Thanks.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 11, 2008 5:14 am 
Newbie

Joined: Mon Jul 21, 2008 5:12 am
Posts: 13
I do not know...
But about answer of question 1 of topicstarter -
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2308


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 15, 2008 9:22 am 
Newbie

Joined: Fri Aug 22, 2008 6:56 am
Posts: 5
igor.inas wrote:
Ok, I found how to supply extra join conditions in HQL. My bad :(

Code:
You may supply extra join conditions using the HQL with  keyword.

from Cat as cat
    left join cat.kittens as kitten
        with kitten.bodyWeight > 10.0


Now I will try to find a way, how to do it in Criteria API.... If anybody knows, before I post here again, please reply.


in NHibernate we do not have the "with" predicate.
is there any other workarund?!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 21, 2009 5:14 am 
Beginner
Beginner

Joined: Tue Jul 03, 2007 11:11 am
Posts: 22
I am facing the same issue,

How to add filter to the first part of the query:

Code:
SELECT cat.id
FROM cat LEFT OUTER JOIN kitten     
ON cat.id=kitten._parent_id AND kitten.weight >=50 
WHERE  cat.id IN(5,6,7)


Sharon


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 18 posts ]  Go to page 1, 2  Next

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.