-->
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.  [ 9 posts ] 
Author Message
 Post subject: Duplicating simple parent child query
PostPosted: Wed Jul 13, 2005 2:20 pm 
Newbie

Joined: Wed Jul 13, 2005 2:00 pm
Posts: 6
I've tried a lot of things to tune this query and I'm sure someone can point me to an answer. What I would like to do is get the same number of selects (for performance) as I do in standard SQL.

Here's the standard SQL query:
Code:
select * from child
join parent
on child.id=parent.id
where child.specialID=?


When I do a find query in HQL using this:
Code:
from com.Child child
join child.parent as parent
where
child.uID = ?


It does the above SQL query and then does many selects on table child for each ID.

I've got a parent class with the the following:
Code:
      <set name="childHolder" inverse="true" cascade="all-delete-orphan">
          <key column="id"/>
          <one-to-many class="com.Child"/>
      </set>


I've got a child class with the following:
Code:
      <many-to-one
            name="parent"
            column="u_id"
            not-null="true"
            insert="false"
            update="false"
            />


Thanks for your help.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 28, 2005 6:23 pm 
Newbie

Joined: Wed Jul 13, 2005 2:00 pm
Posts: 6
Can I provide any additional information? I'd really like to get this solved.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 28, 2005 6:38 pm 
Senior
Senior

Joined: Thu May 12, 2005 11:40 pm
Posts: 125
Location: Canada
Try 'left join fetch'. Other than that, make sure that you're not calling setCacheable(true) if the underlying class is not configured for caching.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 28, 2005 11:08 pm 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
Nebob wrote:
Try 'left join fetch'

To be precise, the equivelant would be 'inner join fetch':
Code:
from com.Child child
inner join fetch child.parent as parent
where
child.uID = ?

In this case, a left join would be useful only if you had children with no parents (an unlikely situation if I read your post correctly).


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 29, 2005 4:47 pm 
Newbie

Joined: Wed Jul 13, 2005 2:00 pm
Posts: 6
That's a great idea. In my tests, the results turn out the same with left join fetch or inner join fetch. Would upgrading to 3.0 help this situation?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 29, 2005 6:16 pm 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
fydoken wrote:
That's a great idea. In my tests, the results turn out the same with left join fetch or inner join fetch. Would upgrading to 3.0 help this situation?

The results should be the same in this case. left join in HQL has the same meaning as in SQL -- include all data in the class (table) on the left, regardless whether there is a matching object on the right. Inner join means return rows only if there is a match on both sides. In your case,
Code:
from com.Child child
left join fetch child.parent as parent
where child.id = ?

should have equivelent results to inner join because there should never be a child with no parent. If the query was:
Code:
from com.Parent parent
left join fetch parent.children
where parent.id = ?

Your query would return the Parent object and its children, if any. However,
Code:
from com.Parent parent
inner join fetch parent.children
where parent.id = ?

would retrieve the parent object (and its children) only if it has children.

Back to your query, though. Since you want the child and it's parent, and you know the parent is there, the difference is in the generated SQL. An HQL join becomes the same type in the generated SQL. So,
Code:
from com.Child child
left join fetch child.parent as parent
where child.id = ?

becomes something like
Code:
SELECT Child.field1, Child.field2, Parent.field1, Parent.field2 ...
FROM Child LEFT JOIN Parent ON
    Child.parent_id = Parent.id
WHERE Child.id = ?

while
Code:
from com.Child child
inner join fetch child.parent as parent
where child.id = ?

becomes something like
Code:
SELECT Child.field1, Child.field2, Parent.field1, Parent.field2 ...
FROM Child INNER JOIN Parent ON
    Child.parent_id = Parent.id
WHERE Child.id = ?

Since most databases perform an INNER JOIN faster than a LEFT JOIN, you can expect the INNER JOIN to perform slightly better.

Hibernate guys, please check my assumptions and let me know if I'm telling fydoken something wrong.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 29, 2005 6:20 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
All looks correct to me.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 01, 2005 10:04 am 
Newbie

Joined: Wed Jul 13, 2005 2:00 pm
Posts: 6
I really appreciate your response but I don't believe I explained myself well. I meant to say that the results were the same regardless of the query I used. It always does one select like I would expect joining the parent and child and then does multiple selects on the child using any of the following queries.

Code:
from com.Child child
join child.parent as parent
where child.id = ?


or

Code:
from com.Child child
left join fetch child.parent as parent
where child.id = ?


or

Code:
from com.Child child
inner join fetch child.parent as parent
where child.id = ?



I wondered how best to troubleshoot this further or if upgrading from 2.1 would help this behavior.

Thanks for your assistance.


Top
 Profile  
 
 Post subject: Number of selects.
PostPosted: Mon Aug 01, 2005 12:26 pm 
Expert
Expert

Joined: Fri Jul 22, 2005 2:42 pm
Posts: 670
Location: Seattle, WA
Query
Code:
from Child as c where c.id=:cid

should do the trick if in the mapping table fetch is set to "join".
like this

Code:
<class  table="p021" name="P021">
    <id name="id"  access="field">
      <generator class="assigned"/>
    </id>
   <property name="name"  access="field"/>
   <set name="childHolder" inverse="true" cascade="all-delete-orphan" access="field" fetch="join">
          <key column="u_id"/>
          <one-to-many class="C021"/>
   </set>
</class>

<class table="c021" name="C021">
  <id name="id" access="field">
    <generator class="assigned"/>
  </id>
  <property name="name" access="field"/>
  <many-to-one class="P021" access="field"
            name="parent"
            column="u_id"
            not-null="true"
            insert="false"
            update="false"      fetch="join"
            />
</class>




At least it is what h3-cvs does. Althought it does two selects - one to get the child and second to fetch all the childs of the child parent.

Postgres log looks like this:

[code]
LOG: statement: begin;
LOG: statement: select c021x0_.id as id1_, c021x0_.name as name1_, c021x0_.u_id as u3_1_ from c021 c021x0_ where c021x0_.id=1
LOG: statement: select p021x0_.id as id0_1_, p021x0_.name as name0_1_, childholde1_.u_id as u3_3_, childholde1_.id as id3_, childholde1_.id as id1_0_, childholde1_.name as name1_0_, childholde1_.u_id as u3_1_0_ from p021 p021x0_ left outer join c021 childholde1_ on p021x0_.id=childholde1_.u_id where p021x0_.id=1
LOG: statement: commit;begin;
[/code/
Seems better than many selects for every child anyway.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 

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:
cron
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.