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.  [ 12 posts ] 
Author Message
 Post subject: Query fetching too much, hql, fetch, lazy, proxy
PostPosted: Fri Nov 21, 2003 9:26 am 
Beginner
Beginner

Joined: Fri Oct 10, 2003 10:30 am
Posts: 35
Location: Stockholm
Hi hib gurus
I have a class called message.
Message has an id, a parent (an other message) and a smallcontent.
Given an id and i small content, I want to retrieve a (unique) grand child which has those properties.
This is my query:

query.append("select image from com.nmt.msp.resource.SimpleMessageResource as image");
query.append(" join image.parent as parent");
query.append(" join parent.parent as grandparent");
query.append(" where ");
query.append(" grandparent.id = :rootMessageId");
query.append(" and image.smallContent = :theImageName");

which I run in this way:
--------------------------------------------------------------------------
net.sf.hibernate.Query q=theMspSession.createQuery(query.toString());
q.setString("theImageName", theImageName);
q.setLong("rootMessageId", rootMessageId);
--------------------------------------------------------------------------

This is the produced sql:
--------------------------------------------------------------------------
19577 Query select simpleme0_.id as x0_0_ from message simpleme0_ inner join message simpleme1_ on simpleme0_.parentid=simpleme1_.id inner join message simpleme2_ on simpleme1_.parentid=simpleme2_.id where (simpleme2_.id=237 )and(simpleme0_.smallcontent='e.gif' )
--------------------------------------------------------------------------
(a table with the message id= 242, the right one) and then 2 messages are fetched:
--------------------------------------------------------------------------
19577 Query select simpleme1_.id as id0_, simpleme1_.parentid as parentid0_, simpleme1_.internal as internal0_, simpleme1_.smallcontent as smallcon4_0_, simpleme0_.id as id1_, simpleme0_.parentid as parentid1_, simpleme0_.internal as internal1_, simpleme0_.smallcontent as smallcon4_1_ from message simpleme0_ left outer join message simpleme1_ on simpleme0_.parentid=simpleme1_.id where simpleme0_.id=242
19577 Query select simpleme1_.id as id0_, simpleme1_.parentid as parentid0_, simpleme1_.internal as internal0_, simpleme1_.smallcontent as smallcon4_0_, simpleme0_.id as id1_, simpleme0_.parentid as parentid1_, simpleme0_.internal as internal1_, simpleme0_.smallcontent as smallcon4_1_ from message simpleme0_ left outer join message simpleme1_ on simpleme0_.parentid=simpleme1_.id where simpleme0_.id=237
--------------------------------------------------------------------------

though I want only the message with id 242 to be fetched....
Why the other is fetched?
This is my message.xml
--------------------------------------------------------------------------
<hibernate-mapping>
<class name="resource.SimpleMessageResource" table="message"
proxy ="service.Message">
<id name="id" column="id" type="long" unsaved-value="-1">
<generator class="native"/>
</id>

<many-to-one name="parent" column="parentid" class="resource.SimpleMessageResource" cascade="none" outer-join = "true"/>
<property name="internal" type="boolean">
<column name="internal" unique-key="name-system-internal" index="namesystem_idx" not-null="true"/>
</property>

<property name="smallContent" column="smallcontent" not-null="false" />
</class>
</hibernate-mapping>
--------------------------------------------------------------------------
and this is my hib.conf

--------------------------------------------------------------------------
hibernate.dialect net.sf.hibernate.dialect.MySQLDialect
hibernate.connection.datasource java:comp/env/jdbc/msp
hibernate.show_sql false
hibernate.use_outer_join true
hibernate.jdbc.batch_size 0
hibernate.jdbc.use_streams_for_binary true
--------------------------------------------------------------------------

Note: without hibernate.use_outer_join true three messages are fetched, parent, child and grandchild.
Thanks for any help

--
Roberto Cosenza


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 21, 2003 7:14 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Since the many-to-one object is always outer joined, Hibernate will load parent, gandparent etc... the whole family.

Try
Code:
<many-to-one name="parent" column="parentid" class="resource.SimpleMessageResource" cascade="none" outer-join = "auto" lazy="true"/>


From the doc
Quote:
he outer-join attribute accepts three different values:
* auto (default) Fetch the association using an outerjoin if the associated class has no proxy
* true Always fetch the association using an outerjoin
* false Never fetch the association using an outerjoin

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 21, 2003 7:20 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
No, theres no lazy attribute on a <many-to-one>. Instead you need to map the associated class with a proxy. That will suppress eager fetching.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 21, 2003 8:06 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Hum I sent my older answer (the one I wrote before thinking of it ;-) )
As you can see the end of the post is good and refer to proxy

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2003 8:45 am 
Beginner
Beginner

Joined: Fri Oct 10, 2003 10:30 am
Posts: 35
Location: Stockholm
I found out that the parent & grandparent fetching is performed not during the query but when I access one of the property of the object (not mapped properties of course, a string is enough).

Is this the correct beaviour? I guess not. And the association is mapped with a proxy (it maps to the object itself, which as you can see, uses a proxy).

Testing with outher-join = false/true/auto did not help.

Confused....
/rob


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2003 8:53 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
The outer-join setting does not affect HQL queries. If you wish to do outer-join fetching in HQL, you must use LEFT JOIN FETCH.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2003 8:57 am 
Beginner
Beginner

Joined: Fri Oct 10, 2003 10:30 am
Posts: 35
Location: Stockholm
good.
I'm trying to avoid the fetch join though!
A has a child B which has a child C.

When I access a.getName(), C is fetched....
/roberto


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2003 8:58 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
No, you are mistaken.

An proxied object is only fetched when it is first accessed. Are you sure you have mapped it with a proxy?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2003 9:01 am 
Beginner
Beginner

Joined: Fri Oct 10, 2003 10:30 am
Posts: 35
Location: Stockholm
quite sure gavin, look at the xml file I posted earlier. Can I see in the hibernate log if the "proxy" mapping is seen correctly in some way?

Thanx,
Roberto


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2003 9:07 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Well, the only many-to-one association in the mapping you posted earlier has outer-join="true", so of course the parent will be fetched by outer join when any SimpleMessageResource is first loaded (unless it is loaded by a HQL query).


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2003 9:14 am 
Beginner
Beginner

Joined: Fri Oct 10, 2003 10:30 am
Posts: 35
Location: Stockholm
I use this

query.append("select image from com.nmt.msp.resource.SimpleMessageResource as image");
query.append(" join image.parent as parent");
query.append(" join parent.parent as grandparent");
query.append(" where ");
query.append(" grandparent.id = :rootMessageId");
query.append(" and image.smallContent = :theImageName");


hql query.

This is my current mapping.

<hibernate-mapping>
<class name="com.nmt.msp.resource.SimpleMessageResource" table="message"
proxy ="com.nmt.msp.service.Message">

<id name="id" column="id" type="long" unsaved-value="-1">
<generator class="native"/>
</id>

<many-to-one name="parent" column="parentid" class="com.nmt.msp.resource.SimpleMessageResource" cascade="none" outer-join = "false"/>

<property name="content" column="content" not-null="false" type="binary" length="100000"/>
</class>

</hibernate-mapping>


I do not run load on the message id, I use the object in the session used for the hql query. As soon as I run message.getContent(), the whole hyerarchy is fetched.

I know that is wierd and that there must be some mistake but I cannot find it. Please point me to the right direction.
/roberto


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2003 9:20 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
I recommend that you get out your debugger and start stepping through code.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 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:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.