-->
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.  [ 21 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Detach lazy object/collection does not work
PostPosted: Fri Oct 15, 2004 3:06 am 
Newbie

Joined: Mon Oct 11, 2004 4:08 am
Posts: 15
I tried to detach lazy object/collection after closed session on J2EE and standalone program and display the object infomation by "toString()" function.

Hibernate always tries to get lazy instances again and throw the following exception. However, refer to the reference document shows that "As soon as the session is closed, they will be detached.....", it seems that it is not correct.

Unlike Kodo JDO it allows user to issue "detach" function that totally detach object and it's associated objects/collections.

Please advise.

Hibernate version:2.1.6

Mapping documents:
<class name="User" table="PB_USER" dynamic-update="true" dynamic-insert="true">
<id name="userID" column="userID">
<generator class="assigned"/>
</id>
<property name="userType" column="USER_TYPE"/>
<property name="userStatus" column="STATUS" />
<many-to-one name="userAcct" column="USER_ACCOUNT_ID" unique="true" />
<joined-subclass name="Staff" table="PB_USER_STAFF" dynamic-insert="true" dynamic-update="true">
<key column="userID"/>
<property name="staffID" column="STAFF_ID" />
</joined-subclass>
<joined-subclass name="AccountExecutive" table="PB_USER_AE" dynamic-insert="true" dynamic-update="true">
<key column="userID"/>
<property name="aeCode" column="AE_CODE" />
<property name="branch" column="BRANCH" />
</joined-subclass>
<joined-subclass name="Account" table="PB_USER_ACCOUNT" dynamic-insert="true" dynamic-update="true">
<key column="userID"/>
<many-to-one name="execAE" class="AccountExecutive" column="EXEC_AE_USER_ID" unique="true" />
<property name="tradingLimit" column="TRADING_LIMIT" />
<set name="stockBal" cascade="all" inverse="true" lazy="true">
<key>
<column name="userID" not-null="true"/>
</key>
<one-to-many class="StockBalance" />
</set>
<set name="cashBal" cascade="all" inverse="true" lazy="true">
<key>
<column name="userID" not-null="true"/>
</key>
<one-to-many class="CashBalance" />
</set>
</joined-subclass>
</class>
Code between sessionFactory.openSession() and session.close():

Full stack trace of any exception that occurs:

Name and version of the database you are using:

The generated SQL (show_sql=true):

Debug level Hibernate log excerpt:
2004-10-15 14:44:21,784 [main] ERROR - Failed to lazily initialize a collection
- no session or session was closed
net.sf.hibernate.LazyInitializationException: Failed to lazily initialize a coll
ection - no session or session was closed
at net.sf.hibernate.collection.PersistentCollection.initialize(Persisten
tCollection.java:209)
at net.sf.hibernate.collection.PersistentCollection.read(PersistentColle
ction.java:71)
at net.sf.hibernate.collection.Set.iterator(Set.java:130)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 15, 2004 5:48 am 
Expert
Expert

Joined: Thu Jan 29, 2004 2:31 am
Posts: 362
Location: Switzerland, Bern
RTM chapter 6.5 of the reference documentation.

HTH
Ernst


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 15, 2004 6:50 am 
Newbie

Joined: Mon Oct 11, 2004 4:08 am
Posts: 15
I also tried the 6.5 methods in all lazy objects but Hibernate issues additional SQLs to get those lazy objects. That is not my purpose. To me, I just want to get the object without getting the lazy objects as I do not need them for some cases and also performance issue. Thus, how to actually detach the lazy objects and Hibernate does not issue any additional SQLs to get them even access those lazy objects after session close/commit.

Exception
======
net.sf.hibernate.LazyInitializationException: Failed to lazily initialize a coll
ection - no session or session was closed

Please advise.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 15, 2004 8:21 am 
Expert
Expert

Joined: Thu Jan 29, 2004 2:31 am
Posts: 362
Location: Switzerland, Bern
AFIAK tha'ts not possible out of the box.

You may have noticed, that Hibernate provides it's own implementation of the Collection interface. That's how the lazy initialization is done.

Maybe this helps:

After closeing the session go and get the values all Properties which return a Collection. Then try to get an element of every collection, if this fails with a LazyInitializationException replace it with an appropriate empty one of the JDK.

You coud automate this with reflection or use the mapping information of Configure.

HTH
Ernst


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 15, 2004 10:46 am 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
you can create a DTO and use projection "select new DTO () ...."

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


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 15, 2004 11:05 pm 
Newbie

Joined: Mon Oct 11, 2004 4:08 am
Posts: 15
Thanks for your reply. But I suggest that Hibernate should provide detach/attach functions just like JDO 2.0 for performance and data requisition concerns.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 16, 2004 3:45 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
You are aware that the (so far non-existant in real systems) JDO 2.0 detach/reattach functionality is a clone of Hibernates 2 year old detach/reattach functionality?

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 16, 2004 3:53 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
francong wrote:
Exception
======
net.sf.hibernate.LazyInitializationException: Failed to lazily initialize a coll
ection - no session or session was closed

Please advise.


Why do you call this "non-detached" ? For me it looks very much detached - it can't get to the session!?

Would you rather have it return a empty collection (or even worse null?) when you hit a collection that you have not yet loaded ?

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 16, 2004 4:03 am 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
Quote:
Would you rather have it return a empty collection (or even worse null?) when you hit a collection that you have not yet loaded ?


i'm afraid that's what he wanted, i may be wrong

have a nice week end guys

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


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 08, 2004 2:56 pm 
Newbie

Joined: Mon Nov 08, 2004 2:36 pm
Posts: 2
anthony wrote:
Quote:
Would you rather have it return a empty collection (or even worse null?) when you hit a collection that you have not yet loaded ?


i'm afraid that's what he wanted, i may be wrong


Well, if he doesn't, I do :-)

The issue for me is with an N-tier system. Following the idea of no DTOs, we pass back our Hibernate mapped POJO. Since the web tier has no concept of hibernate (and in our design, it shouldn't), it just treats the object like a normal POJO and starts poking at it to see if it satisfies certain criteria.

Since we don't want to pass back full graphs, the object is partially initialized--and the collections throw exceptions. The only real solution I have found is to "scrub" the object and remove any uninitialized hibernate collections and replace them with empty java.util objects. While it works, it could get a bit expensive with some of our objects (which can nest 4 to 5 levels deep).

Is there anyway to get a collection to detach so that when it doesn't have a valid session it just acts like a normal object? That is, instead of all the read() and write() calls in the List implementation methods tossing exceptions, it just quietly calls the internal list object. Then when it is passed back to the server tier, it either reconnects to a valid session and does its thing or it acts like a plain object would.

Does this make sense? Basically, as an N-tier designer, I see your current implementation as working against any attempt to separate the app out into discreet tiers. While you could argue for or against N-tier designs, it still begs the question why you always throw exceptions.

What harm is there in the collection trying to initialize when it has a session and quietly using the internal object when it doesn't?

Thanks in advance,
Matt

P.S. There is another post about how to patch initialization that basically is saying the same thing:
http://forum.hibernate.org/viewtopic.php?t=935907


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 08, 2004 6:35 pm 
Beginner
Beginner

Joined: Sun Oct 03, 2004 8:50 am
Posts: 32
Location: McLean, VA
max wrote:
Would you rather have it return a empty collection (or even worse null?) when you hit a collection that you have not yet loaded ?


Yes, I would. A populated collection vs. empty collection vs. null, each case gives me information to work with.

If the collection was populated it tells me that there was stuff out there and I can add and remove things.

If the collection was empty it says that Hibernate looked for the data and that there wasn't any, BUT that I could add stuff without it blowing up. This is especially important on the web tier when I may not have a session.

A null reference tells me Hibernate hasn't checked for this data, and should tell most developers to be careful. In this case I would want Hibernate to throw some sort of exception, UnintializedCollectionException, IllegalStateException, something else?

It's about giving developers information to make decisions without making thier code so brittle that if they try to figure out what to do it throws exceptions.

_________________
- Chad


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 08, 2004 7:32 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
and when you start adding stuff to a collection, how many of the existing elements should be kept ?

the easy answer: All of them....

but then what should e.g. iterator() or even a .get(something) return ?

There is no easy as we would not be able to anything remotely interesting with this collection since it does not have access to a session

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 08, 2004 7:34 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
To make a collection behave like a plain vanilla object ?

either call Hibernate.initialize() on it (the safe solution)
put in another collection (the unsafe solution, since now hibernate cannot know which elements have been added/deleted/etc. and thus would have to rebuild the data...not very safe)

...

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 08, 2004 7:39 pm 
Beginner
Beginner

Joined: Sun Oct 03, 2004 8:50 am
Posts: 32
Location: McLean, VA
max wrote:
and when you start adding stuff to a collection, how many of the existing elements should be kept ?

the easy answer: All of them....

but then what should e.g. iterator() or even a .get(something) return ?


How do you handle this now if I but a where clause on a collection such that I don't get the full result set back? You keep all the existing ones and add to them right? I'd continue that trend.

_________________
- Chad


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 08, 2004 7:45 pm 
Newbie

Joined: Mon Nov 08, 2004 2:36 pm
Posts: 2
max wrote:
To make a collection behave like a plain vanilla object ?

either call Hibernate.initialize() on it (the safe solution)...


But that just forces a load, doesn't? At least that is what I see.

What if I have an object that has 1000 objects in a collection. I want to work on that object on the web tier, perhaps generate a new collection object.

In a non-hibernate situation, this would be something like:

1) pass back object, with empty collection
2) add to collection
3) pass it back to server tier
4) server tier sees object in collection that does not have a PK--clearly a new object
5) save new collection object

This is exactly the problem we have, and the current hibernate behavior breaks this:

1) pass back object, with empty/uninitialized collection
2) add to collection --- EXCEPTION

We are unable to do anything with the collection instance because it is unintialized and not connected to the session. It just fails.

Perhaps you guys see this as a good idea? That's ok--different strokes for different folks. But the reality is that it keeps people from discarding DTOs then. If the collection is always expecting to be either a) initialized or b) have a valid session to initialize itself, we are going to have to replace it before we send it out to the web tier.

Which really breaks how I would think Hibernate would like us to use it.

Am I just totally misunderstanding something? Do you guys intend it to work this way (either load the whole 1000 objects or never touch it)? Or is this just a use case that never came up initially? Granted, this will only happen in an N-tier situation ... but that is a design you will run into on 50-75% of the time on any large project.

Thanks again for your help!
Matt


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 21 posts ]  Go to page 1, 2  Next

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.