-->
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.  [ 3 posts ] 
Author Message
 Post subject: Programmatically overriding lazy for collections
PostPosted: Fri Aug 28, 2009 2:52 pm 
Newbie

Joined: Fri Aug 28, 2009 12:50 pm
Posts: 5
My team has run into an issue programmatically overriding the "lazy" attribute specified in our Hibernate mapping files for collections.

Some background info:
Our application originally used a Versant object database, and we have converted our application to use Hibernate 3.1.3 to persist our data into MySQL 5.1.30-community. We are currently using Java 1.4.2_17 and MySQL connector 3.1.13, but we are moving to the latest of both Java and the MySQL connector in this release cycle. We have gone through great lengths to have no references to Hibernate except in core code, so ALL of our business logic operates on detached objects. Also our application has a client-server architecture, so we frequently send our data objects via RMI to the clients to operate in a separate JVM from the Hibernate persistence context. For these reasons, we map our entities and collections with lazy="false" in most cases.

We have an Equipment class that contains a List collection of children. The children collection is made up of other Equipment objects. This parent-child object tree can be arbitrarily deep, although I believe that 6 or 7 is the deepest that we encounter at this time. Because this tree can be large and most use cases do not require the entire tree, we use lazy="true" for the children collection.

There is a feature in our application that exports Equipment to text. In this case, we always need the entire Equipment parent-child tree and hence we want to perform the retrieves as if children was configured lazy="false". We always query by criteria, so we did what appears to be the most popular answer: Use setFetchMode on the criteria to set it to FetchMode.JOIN. However, this only eagerly fetches the children for the Equipment object being queried. All of the Equipment in the children collection do NOT have their children eagerly fetched. It appears that this change in FetchMode is not applied recursively in order to retrieve the entire Equipment tree.

On the other hand, if we set lazy="false" for the children collection in the mapping file, we find that it does what we want: The entire Equipment tree is retrieved eagerly. This is certainly not the solution we want because as I stated earlier, most of our use cases do not require the entire tree. This creates an unacceptable performance in many areas of our application.

That being said, I see a difference between setting lazy="false" in the mapping file verses setting the FetchMode to EAGER or JOIN. I also find it interesting that you can set the "lazy" attribute and the "fetch" attribute separately in the mapping files. Based on this article as well as many other sources, these are perpendicular concepts. Lazy determines what is retrieved, and fetch determines how to retrieve it. It seems to reason there should be a way to programmatically override lazy="true" to be lazy="false". Furthermore, it appears to me that using FetchMode.JOIN is a workaround to make an association behave as if lazy="false", but only in certain situations.

Does anyone know of the solution to this problem? We really would like to avoid doing any work around, such as writing a method to recursively load the children, as that is not a general solution.

Thanks,
Joe


Top
 Profile  
 
 Post subject: Re: Programmatically overriding lazy for collections
PostPosted: Mon Aug 31, 2009 2:12 pm 
Regular
Regular

Joined: Mon Jan 05, 2009 6:42 pm
Posts: 99
Location: IL
Hi,
I don't have expertise in this. So this is not a solution to your question probably. I will be watching this thread to see what others have to offer.
We have been using the Fetch Mode to load the objects selectively the ones we wanted to load eagerly. It will be fun to know about recursively load all of the children.

So when you use your work around to use the Fetch Mode and use the deepest association so that hibernate would do initialize all the way through. And this would not help in your case?

For example:-
On a given Entity, you could tell hibernate to load associations one after another or all the way through in one shot.
.setFetchMode("roles", FetchMode.JOIN)
.setFetchMode("roles.roleUsers", FetchMode.JOIN)
.setFetchMode("roles.roleUsers.user",
FetchMode.JOIN).setFetchMode("roles.roleUsers.user.contact", FetchMode.JOIN)
.setFetchMode("roles.roleUsers.user.contact.company", FetchMode.JOIN).add(Restrictions.idEq(id))
.uniqueResult();

OR
.setFetchMode("roles", FetchMode.JOIN)
// .setFetchMode("roles.roleUsers", FetchMode.JOIN)
//.setFetchMode("roles.roleUsers.user",
// FetchMode.JOIN).setFetchMode("roles.roleUsers.user.contact", FetchMode.JOIN)
.setFetchMode("roles.roleUsers.user.contact.company", FetchMode.JOIN).add(Restrictions.idEq(id))
.uniqueResult();
In my case both of them run fine and initialize all of the children to the deep I have asked for.
the difference in the above is that the first ones loads and initializes all of the instances in ONE SQL query but in the later case it does load and initialize all of the children but in subsequent queries(depending on the requirement both of them have advantages or disadvantages).

I know this is not what you looking for.. So good luck! and post us back if you have found another way.
-Srilatha.


Top
 Profile  
 
 Post subject: Re: Programmatically overriding lazy for collections
PostPosted: Mon Aug 31, 2009 2:44 pm 
Newbie

Joined: Fri Aug 28, 2009 12:50 pm
Posts: 5
latha1119 wrote:
Hi,
I don't have expertise in this. So this is not a solution to your question probably.
(...)
I know this is not what you looking for.. So good luck! and post us back if you have found another way.
-Srilatha.


Thanks for your reply, Srilatha. I was not aware that you could set the FetchMode arbitrarily deep as you showed in your example. However, your suspicion is correct that this is not a good solution for my team. The primary concern with this solution is that we do not necessarily know how deep the parent-child tree is.

Since our motivation behind this topic is to prevent excessive RMI calls and repeatedly creating Sessions, our best workaround idea is to attach the pojos to a session and call a method that will recursively load all children in the tree. This is similar to the mechanism that we presently use to handle lazy instantiation, since this always occurs while detached. But it's just not an elegant solution, and requires special coding for all other cases we may experience in the future.

Thanks for the insight. Hopefully someone else will stumble across this post and explain how to truly set the FetchMode to EAGER.

Joe


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