-->
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.  [ 10 posts ] 
Author Message
 Post subject: Lazy=true not working
PostPosted: Fri Mar 03, 2006 5:32 am 
Regular
Regular

Joined: Wed Jul 27, 2005 2:33 am
Posts: 118
Hi,
We are using Hibernate2.1.3 as a MBean in JBoss-3.2.3. We are running into issues related to lazy loading. We have set lazy=true on the collections of a parent objects. But, even then, when the parent object is loaded, the collection is also getting populated with the child objects. Following is a sample hbm mapping:

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
   
<hibernate-mapping>
<!--
    Created by the Middlegen Hibernate plugin 2.1

    http://boss.bekk.no/boss/middlegen/
    http://www.hibernate.org/
-->

<class
    name="com.dbdata.core.hibernateobject.Channel"
    table="CM_TABLE"
>
   <cache usage="transactional"/>
    <composite-id name="id" class="com.dbdata.core.hibernateobject.ChannelId">
        <key-property
            name="id"
            column="ID"
            type="int"
            length="22"
        >
        </key-property>
        <key-property
            name="versionId"
            column="VERSION_ID"
            type="int"
            length="22"
        >
        </key-property>
    </composite-id>   
     
   <timestamp
        name="revisionDate"
        column="REVISION_DTTM"
    />
   
   
    <property
        name="name"
        type="java.lang.String"
        column="NAME"
        not-null="true"
        length="40"
    >
    </property>
    <property
        name="description"
        type="java.lang.String"
        column="DESCRIPTION"
        length="1000"
    >
    </property>
   
    <!-- Associations -->
   
   
    <set
        name="channelInstances"
        [b]lazy="true"[/b]
        inverse="true"
      cascade="all-delete-orphan"
      order-by="NAME asc"
    >
      <cache usage="transactional"/>
        <key>
            <column name="CLASS_ID" />
            <column name="CLASS_VERSION_ID" />
        </key>
        <one-to-many
            class="com.dbdata.core.hibernateobject.ChannelInstance"
        />
    </set>
   

</class>
</hibernate-mapping>


When we are loading the com.dbdata.core.hibernateobject.Channel (Parent) object, even the collection "channelInstances" is getting populated with instances of com.dbdata.core.hibernateobject.ChannelInstance.

We did a bit of investigation into this and tried to obtain a Thread dump from one of the setters of the child object, to find out the flow from where this setter of the child is getting called. Following is the output from the Thread.dumpStack() invoked from one of the setters of the child object:

Code:
2006-03-02 15:39:35,393 ERROR [STDERR]    at [b]com.dbdata.core.hibernateobject.Channel.setChannelInstances[/b](Channel.java:301)
2006-03-02 15:39:35,393 ERROR [STDERR]    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2006-03-02 15:39:35,393 ERROR [STDERR]    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
2006-03-02 15:39:35,393 ERROR [STDERR]    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
2006-03-02 15:39:35,393 ERROR [STDERR]    at java.lang.reflect.Method.invoke(Method.java:324)
2006-03-02 15:39:35,393 ERROR [STDERR]    at net.sf.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:38)
2006-03-02 15:39:35,393 ERROR [STDERR]    at net.sf.hibernate.persister.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:221)
2006-03-02 15:39:35,393 ERROR [STDERR]    at net.sf.hibernate.impl.SessionImpl.initializeEntity(SessionImpl.java:2199)
2006-03-02 15:39:35,393 ERROR [STDERR]    at net.sf.hibernate.loader.Loader.doQuery(Loader.java:293)
2006-03-02 15:39:35,393 ERROR [STDERR]    at net.sf.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:186)
2006-03-02 15:39:35,393 ERROR [STDERR]    at net.sf.hibernate.loader.Loader.loadEntity(Loader.java:889)
2006-03-02 15:39:35,393 ERROR [STDERR]    at net.sf.hibernate.loader.Loader.loadEntity(Loader.java:909)
2006-03-02 15:39:35,409 ERROR [STDERR]    at net.sf.hibernate.loader.EntityLoader.load(EntityLoader.java:59)
2006-03-02 15:39:35,409 ERROR [STDERR]    at net.sf.hibernate.loader.EntityLoader.load(EntityLoader.java:51)
2006-03-02 15:39:35,409 ERROR [STDERR]    at net.sf.hibernate.persister.EntityPersister.load(EntityPersister.java:419)
2006-03-02 15:39:35,409 ERROR [STDERR]    at net.sf.hibernate.impl.SessionImpl.doLoad(SessionImpl.java:2106)
2006-03-02 15:39:35,409 ERROR [STDERR]    at net.sf.hibernate.impl.SessionImpl.doLoadByClass(SessionImpl.java:1980)
2006-03-02 15:39:35,409 ERROR [STDERR]    at net.sf.hibernate.impl.SessionImpl.get(SessionImpl.java:1916)


It appears that while loading the parent(through Loader.loadEntity) Hibernate invokes the doQueryAndInitializeNonLazyCollections. We had a look at this code and it looks like it intializes the collection irrespective of whether it is lazy=true or lazy=false. Also, the javadoc of this method does not say anything about the lazy attribute:

Quote:
/**
* Execute an SQL query and attempt to instantiate instances of the class mapped by the given
* persister from each row of the <tt>ResultSet</tt>. If an object is supplied, will attempt to
* initialize that object. If a collection is supplied, attempt to initialize that collection.
*/


Are we missing something here? The lazy=true is a very fundamental feature and it appears that we are surely missing something in our configuration. Any help is appreciated.

Thank you.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 03, 2006 5:57 am 
Beginner
Beginner

Joined: Wed Aug 04, 2004 4:33 am
Posts: 45
Location: Switzerland
I had the same problem once. Lazy didn't work and I couldn't solve it. Will watch this topic.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 03, 2006 11:21 am 
Expert
Expert

Joined: Fri Aug 19, 2005 2:11 pm
Posts: 628
Location: Cincinnati
I can't tell anything from that error trace, not enough.

did you check in the logs if the database was actually queried and the data was retrieved? that doInitializeNonLazy class could just be checking and not actually loading.

_________________
Chris

If you were at work doing this voluntarily, imagine what you'd want to see to answer a question.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 03, 2006 11:58 am 
Regular
Regular

Joined: Wed Jul 27, 2005 2:33 am
Posts: 118
Quote:
I can't tell anything from that error trace


let me clarify, i am *not* getting any exceptions. That was the output from Thread.dumpStack(), which i invoked in one of the setter methods of my child object, to identify the flow through which the setter is being called.

Quote:
did you check in the logs if the database was actually queried and the data was retrieved


Yes, i did that. I even turned on show-sql=true and found that queries were fired on the child object table and data fetched.

Quote:
that doInitializeNonLazy class could just be checking and not actually loading.


Well, i was debugging the application through Eclipse to make sure about this, and i found that the child object is indeed loaded as part of load process of the parent object, even with lazy=true on the collection.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 03, 2006 12:00 pm 
Regular
Regular

Joined: Wed Jul 27, 2005 2:33 am
Posts: 118
Let me know if any addition information is needed


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 03, 2006 12:15 pm 
Expert
Expert

Joined: Fri Aug 19, 2005 2:11 pm
Posts: 628
Location: Cincinnati
I'll say this. I have many simple classes exactly like yours where the lazy="true" thing works soooooo.... I'd have to say either that cache="transactional" statement is counteracting it, or the inverse="true" is.

but I'd say probably to the caching


also, I don't know how you're calling it in your code, but there are a number of ways to override lazy="true" when you're trying to load a class:

Criteria has fetch options
Hibernate.Initialize
Fetch=join
setFetchMode

_________________
Chris

If you were at work doing this voluntarily, imagine what you'd want to see to answer a question.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 03, 2006 12:25 pm 
Regular
Regular

Joined: Wed Jul 27, 2005 2:33 am
Posts: 118
Quote:
I don't know how you're calling it in your code


I am invoking the session.get() method and passing it the id of the parent. Something like:

Code:
parentObject = session.get(parentClass, parentId);


Quote:
either that cache="transactional" statement is counteracting it, or the inverse="true"


I will try doing some investigations on this.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 03, 2006 12:39 pm 
Expert
Expert

Joined: Fri Aug 19, 2005 2:11 pm
Posts: 628
Location: Cincinnati
jaikiran wrote:
Code:
parentObject = session.get(parentClass, parentId);




I hardly have a use for session.get so I'm not sure how it reacts to collections, but it says session.get never returns a proxy for the object it's trying to load... so I don't know if that filters down through collections

_________________
Chris

If you were at work doing this voluntarily, imagine what you'd want to see to answer a question.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 13, 2006 5:43 am 
Newbie

Joined: Tue Jun 13, 2006 4:26 am
Posts: 3
Location: Bristol
Jaikiran,

Are you using property change support in your beans? I've come across this problem just once before and firing a property change event on the collection was the cause. When the event fires, the size() method is called on the collection which causes initialization to occur. Setting the lazy mode to "extra" will stop the collection being initialized but still causes some SQL to be executed.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 13, 2006 7:39 am 
Regular
Regular

Joined: Tue May 16, 2006 3:32 am
Posts: 117
In addition to what is said above, in any of the setCollection methods don't iterate over the children, etc. Doing something like this would load the children also. The code could always be rewritten to avoid this.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 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.