-->
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.  [ 8 posts ] 
Author Message
 Post subject: What is the Best practice for optional child fetching?
PostPosted: Tue Feb 01, 2005 4:41 pm 
Newbie

Joined: Tue Feb 01, 2005 3:54 pm
Posts: 4
I have a typical parent-child setup except that the parent has 3 child tables.
The relationship is one parent-many children for each table.

Parent - 0..n Child1
- 0..n Child2
- 0..n Child3

For optimization, I wish to retrieve a list of the parent records initially
without retrieving the children.

A second method will retrieve a specific parent record with the children.

I've looked in the various FAQs but haven't come across an answer
although many before must have tackled the issue.

I tried setting the child retrieval to "lazy".

However, even if the retrieve with details method explictly retrieves the
child records with a left "join fetch parent.child1", I get a "lazy"
initialization error since I then call the getChild1s() method after the
session is closed.

My current approach is to create two classes, Parent and
ParentWithChildren.
The Parent would not have the child associations while the
ParentWithChildren would.
ParentWithChildren extends Parent. Both are mapped to the "Parent"
table.

When I perform a query using "from Parent parent", however, I get a
net.sf.hibernate.WrongClassException thrown.

So, what is the solution for this and if there are several approaches,
which is the best?


Thanks,
Andrew


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 01, 2005 5:45 pm 
Beginner
Beginner

Joined: Mon Nov 29, 2004 5:34 pm
Posts: 35
This is good question, I am also looking for similar reply. Please post your ideas/suggestions.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 01, 2005 6:20 pm 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
Quote:
I have a typical parent-child setup except that the parent has 3 child tables.
The relationship is one parent-many children for each table.

Parent - 0..n Child1
- 0..n Child2
- 0..n Child3

For optimization, I wish to retrieve a list of the parent records initially
without retrieving the children.

A second method will retrieve a specific parent record with the children.

I've looked in the various FAQs but haven't come across an answer
although many before must have tackled the issue.

I tried setting the child retrieval to "lazy".

However, even if the retrieve with details method explictly retrieves the
child records with a left "join fetch parent.child1", I get a "lazy"
initialization error since I then call the getChild1s() method after the
session is closed.


you're doing something wrong

check generated sql when calling .getChild1()

there are many ways to solve this problem.

next time, please give simplified mapping file, java code and filtered logs as said here http://www.hibernate.org/ForumMailingli ... AskForHelp

_________________
Anthony,
Get value thanks to your skills: http://www.redhat.com/certification


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 02, 2005 2:10 pm 
Newbie

Joined: Tue Feb 01, 2005 3:54 pm
Posts: 4
Thanks for the reply, Anthony

Here's what I did first.

1) Lazy approach

Domain has 0..n Assets

Domain.hbm.xml has:

<hibernate-mapping>
<class name="Domain" table="DOMAIN" lazy="true">
...
<set name="assets" table="ASSET" inverse="true"
cascade="all" lazy="true">
<key column="DOMAIN_ID" />
<one-to-many class="Asset" />
</set>
</class>

<query name="findDomainById"><![CDATA[
from Domain domain where domain.domainId = :domainId
]]></query>

</hibernate-mapping>


Asset.hbm.xml has:

<hibernate-mapping>
<class name="Asset" table="ASSET">
...
<many-to-one name="domain"
column="DOMAIN_ID"
class="Domain"
not-null="true"/>
</class>
</hibernate-mapping>


I have a retreival method called findDomainById which uses the named query "findDomainById" to retrieve
a Domain as follows:


try
{
sess = getSession();

Query query = sess.getNamedQuery("findDomainById");

query.setInteger("domainId", _domainId);

list = query.list();

if (list.size() != 0)
{
domain = (Domain) list.get(0);
}

status = OK;
}

The session is always closed on exit from the method.


I retrieved a Domain successfully. When I tried to retrieve the Assets using the getAssets() method in the Domain object, a Runtime Exception was thrown as expected as I tried to access an uninitialized proxy or exception.


As a test, I changed the named query in Domain.hbm.xml to

<query name="findDomainById"><![CDATA[
from Domain domain
left join fetch domain.assets
where domain.domainId = :domainId
]]></query>

I called this method and retrieved a Domain successfully.
When I tried to retrieve the Assets using the getAssets() method
in the Domain object, a Runtime Exception was still thrown even though I explicitly retrieved the Assets for the Domain.



2) Separate Domain object to contain the Assets

My second approach was to try to create separate Domain objects, one with the Details and one without.
The Domain object did not contain the Assets.
The DomainDetails object extends the Domaon and contains the getAssets(), addAsset(), and setAssets() methods.


DomainDetails.hbm.xml has:

<hibernate-mapping>
<class name="DomainDetails" table="DOMAIN">
...
<set name="assets" table="ASSET" inverse="true" cascade="all">
<key column="DOMAIN_ID" />
<one-to-many class="Asset" />
</set>
</class>

<query name="findDomainDetailsById"><![CDATA[
from DomainDetails domain
left join fetch domain.assets
where domain.domainId = :domainId
]]></query>

</hibernate-mapping>


Domain.hbm.xml has:

<hibernate-mapping>
<class name="Domain" table="DOMAIN">
...
</class>

<query name="findDomainById"><![CDATA[
from Domain domain where domain.domainId = :domainId
]]></query>

</hibernate-mapping>


Asset.hbm.xml has:

<hibernate-mapping>
<class name="Asset" table="ASSET">
...
<many-to-one name="domainDetails"
column="DOMAIN_ID"
class="DomainDetails"
not-null="true"/>
</class>
</hibernate-mapping>


I created a second method called findDomainDetailsById which returned a DomainDetails.

On calling the original findDomainById method (named query findDomainById above), however, I get an error that
I'm attempting to map to the Wrong object.



Finally,

Retrieving parent objects with and without children is a common requirement and so I'm sure that I made an error somewhere and will continue to debug.

I realize that there are sevaeral ways to solve this as you stated. I tried two of them. Is there a best way (even if it's only your opinion) of doing this to reduce database load?


Thanks,
Andrew


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 02, 2005 9:30 pm 
Beginner
Beginner

Joined: Sat Jan 22, 2005 9:11 am
Posts: 35
Location: London
Hi porchlights

The selection of a loading strategy should not affect your model!

I recommend you leave the one-to-many mappings as lazy and use Hibernate.initialize(). Also take a look at batch fetching.

As the documentation says, if you want to read data after closing the session you must obviously explicitly initialize or manually traverse the required object graph first.

HTH

Ben


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 03, 2005 9:15 am 
Newbie

Joined: Tue Feb 01, 2005 3:54 pm
Posts: 4
I was thinking of using initialize() but what I was not sure of was whether this call actually retrieved the child records.

It if did, then this defeats the attempt to selectively retrieve the child records only as needed.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 03, 2005 9:20 am 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
are you sure the lazy exception is not due to this:
Quote:
<many-to-one name="domainDetails"
column="DOMAIN_ID"
class="DomainDetails"
not-null="true"/>
???

_________________
Anthony,
Get value thanks to your skills: http://www.redhat.com/certification


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 03, 2005 12:29 pm 
Newbie

Joined: Tue Feb 01, 2005 3:54 pm
Posts: 4
No, the DomainDetails approach was taken after I got the lazy Exception. Trying the DomainDetails approach, I got rid of the lazy attributes altogether.

I'm busy with related stuff but will go back to testing/debugging this today.


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