-->
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.  [ 20 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Failed to lazily initialize a collection - no Session
PostPosted: Thu Nov 06, 2003 4:33 pm 
Newbie

Joined: Thu Nov 06, 2003 4:01 pm
Posts: 8
I'm integrating hibernate into a client swing accounting application. I first encountered the problem of the cache being out of sync with recent commits. Is there no way to sync cached with commits? Then I found that Session objects should be closed and reopened for each unit of work which seems very strange but OK. So, that indirectly solves the problem of the cache being out of date since all cache is lost when the Session is closed. But, then there is zero benefit for my app from cache. Now here's the problem; lazily loaded collections after the session is closed. I have not yet found a work around for this problem. This seems to be a big for me. Is it possible to avoid storing a reference to the Session in classes such as PersistentCollection and, instead, store a reference to SessionFactory or similar factory provided by me with which to get a Session. This would ensure that that a Session is always available for the collection when it is lazily loaded even if the original Session has been closed. If not, it seems that I will have to reload every persisent object in memory when a session is closed even though a new one is immediately reopened and available.

Thanks,

-Ken


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 06, 2003 5:57 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 7:19 pm
Posts: 2364
Location: Brisbane, Australia
Session object is very lite so yes you create and close them often. They are normally kept open for the unit of work then dumped. There are mulitple levels of caching, firstly at the session level then at the system level (with greater support for clustering on its way). Read about JCS tags and the new (2.1) caching APIs. Read http://hibernate.bluemars.net/61.html for an overview.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 07, 2003 11:20 am 
Newbie

Joined: Thu Nov 06, 2003 4:01 pm
Posts: 8
Thanks, I will read about JCS however, the real question was lower in my post.

...lazily loaded collections after the session is closed. I have not yet found a work around for this problem. This seems to be a big for me. Is it possible to avoid storing a reference to the Session in classes such as PersistentCollection and, instead, store a reference to SessionFactory or similar factory provided by me with which to get a Session. This would ensure that that a Session is always available for the collection when it is lazily loaded even if the original Session has been closed. If not, it seems that I will have to reload every persisent object in memory when a session is closed even though a new one is immediately reopened and available.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 07, 2003 11:49 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
You can use lock() or update() to reassociate an entity with a new session. This is a major (unique) feature of Hibernate.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 07, 2003 12:57 pm 
Newbie

Joined: Thu Nov 06, 2003 4:01 pm
Posts: 8
Again, what are your thoughts on Storing a SessionFactory, or similar, in classes so that they call getSession() instead attempting to store and reuse a Session reference which may be null. I do not know all the hibernate code or how the change may cause other issues so ask you. I would certainly be willing assist/contribute. I use this approach throughout my projects and it works well. It adds some very nice fault tolerance.

I attempted to lock the object but got this exception even thought the object is not transient.

net.sf.hibernate.TransientObjectException: attempted to lock a transient instance.

Update did work however, I only want to navigate lazy collections to populate the UI at this point; updating will cause errors if used for this purpose as the UI is not ready to persist the changes.

Further, using lock or update every time I want to simply display an object in the UI is very error prone and will probably never work.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 07, 2003 1:15 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Quote:
Again, what are your thoughts on Storing a SessionFactory, or similar, in classes so that they call getSession()


I have no idea what you are talking about.

Quote:
I attempted to lock the object but got this exception even thought the object is not transient.


Try Hibernate 2.1

Quote:
Further, using lock or update every time I want to simply display an object in the UI is very error prone and will probably never work.


Can't see why not .... but if it really won't work then your alternative is to use a long-lived session. Christian says this works very successfully in his real apps though I only ever had it as a theoretic possibility.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 07, 2003 2:52 pm 
Newbie

Joined: Thu Nov 06, 2003 4:01 pm
Posts: 8
Regarding 'Storing a SessionFactory' I will try to clarify. PersistentCollection stores a reference to a Session as session. If that session was closed, then the reference is null. When the collection tries to initialize, it tests session for null, isDisconnected, etc. If the session reference fails the test, an exception is thrown. Consider the following class. The purpose of the class would be similar to javax.sql.DataSouce in the way that it is not a connection but can get one for you. You may also think of it as a Proxy pattern.

public class SessionSource {
private Session session;
public Session getSession() {
if (session == null)
session = sessionFactory.openSession();
return session;
}
}


PersistentCollection could store a reference to SessionSource which would always be valid even if the Session was closed. If the collection called SessionSource.getSession() instead of simply trying to use the session reference, it would almost always be guaranteed a valid Session.

Long lived sessions sounds like a better fit for my purpose as long as I can clear the cache or otherwise be sure I'm not getting stale data.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 07, 2003 5:28 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
The trouble with this is that it would encourage a style of programming where the user opens lots of "little" sessions w/o being consciously aware of the fact. For transaction isolation and, especially, performance, we don't want this. For performance, it is really important that you keep the session open for as long as possible (but not too long, since you don't want to increase the risk of stale data and optimistic lock failures).


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 18, 2003 3:17 pm 
Newbie

Joined: Thu Nov 13, 2003 1:14 pm
Posts: 18
Location: Leinfelden-Echterdingen, Germany
The long-lived session/lazy-loading topic is something causing me trouble, too. I'm afraid I did not realy get the concept behind hibernate sessions.

On the one hand, I read repeatedly things like:
Quote:
Session object is very lite so yes you create and close them often.

On the other hand, obviously, this is only half of the truth:
Quote:
For performance, it is really important that you keep the session open for as long as possible.

So I'm somewhat confused and would be grateful for any additional information.

Until then, Ken, did you find a solution that works well for you? Are there any other users that are willing to share there experience on this topic?

Thanks,

Peter


Top
 Profile  
 
 Post subject: session lifetime issues
PostPosted: Tue Nov 18, 2003 4:21 pm 
Newbie

Joined: Thu Nov 06, 2003 4:01 pm
Posts: 8
I also did not give much regard to the statements about the Session being short lived until I ran into the technical issues.

I'm trying another OR mapping tool.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 18, 2003 7:20 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Quote:
On the one hand, I read repeatedly things like:
Session object is very lite so yes you create and close them often.

On the other hand, obviously, this is only half of the truth:
For performance, it is really important that you keep the session open for as long as possible.


The session usually has the same lifespan as a transaction. If you use sessions that last for longer than a transaction

(a) you will start to run out of memory
(b) you start to run into problems with transaction isolation

On the other hand, if you open many sessions per transaction/request

(a) you lose the benefits of the sessional cache

There is a section of the manual that discusses this stuff.

Really, "one session per transaction/request" is quite straightforward. :)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 18, 2003 7:24 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Notice that I am sometimes deliberately vague on the definition of "transaction". But, for beginners, and even for most advanced users, "transaction" can mean an ordinary database transaction.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 18, 2003 11:04 pm 
Newbie

Joined: Thu Nov 06, 2003 4:01 pm
Posts: 8
In hopes of adding something constructive to Hibernate, I'll explain the issues I encountered regarding session lifetime again.

Firstly, Hibernate is very impressive and worked much better than other toosl in many ways. No doubt more refined and mature than other open source tools and some commercial tools. HQL(awesome), java2hbm, hbm2java, schema generation, simple mapping syntax, lazy collection, and more, are all excellent features that worked well.

problems I encountered:

1.
References to persistent objects(PO's) held in my code would fail when I attempted to access a lazy collection of said PO reference. This was due to the fact that Session which loaded the PO was null since it had been closed, as suggested, after completion of a unit of work or transaction. There was no automatic way to reassociate all live references in the VM with the new Session.

2.
The docs say that a session must be discarded if it throws any exceptions. Exceptions are a normal and expected part of db transactions for my app and therefore this tells me that I must be prepared to close the Session after every transaction thereby causing problem 1 again.

3.
No simple way to refresh,discard entire cache or otherwise avoiding getting stale data. Again, I'd have to track all my PO references and remove each one from cache. This was not feasible for me. The only way was to, again, close and reopen the session thereby causing problem 1 again.

For my purposes, Hibernate needs:

1. stable session capable of long life
2. simple way to clear all cache or avoid stale data
3. lazy collections tolerant of nullified sessions. They should auto-reassociate with the new Session. javax.sql.DataSource insulates db apps from JDBC connection loss. Hibernate PersistentCollection needs to use a similar approach, don't store the session, store a way to always get one! AKA Factory pattern. :-)

-Ken


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 19, 2003 12:06 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
1. do:

session.lock(object, LockMode.NONE)

to reassociate a proxy or an entity with a collection.

Note that Hibernate is absolutely no different to JDO or other well-designed ORM solutions in this. This is a standard problem. At least Hibernate gives you _some_ solution for reattachment, unlike JDO.

2. Correct. You are supposed to discard the session after every transaction, whether an exception occurs or not. That is a basic design feature of Hibernate. How could this possibly count as a problem?

3. The way to discard the session-level cache and avoid stale data is by closing the session at the end of the transaction. Just like you are supposed to. To discard the second-level cache, you call sessionFactory.evictXXX().

You do understand the concept of a two-level cache, right? Just because we discard the session, doesn't mean that we lose the second-level cache.


Quote:
For my purposes, Hibernate needs:

1. stable session capable of long life
2. simple way to clear all cache or avoid stale data
3. lazy collections tolerant of nullified sessions. They should auto-reassociate with the new Session. javax.sql.DataSource insulates db apps from JDBC connection loss. Hibernate PersistentCollection needs to use a similar approach, don't store the session, store a way to always get one! AKA Factory pattern. :-)



1. Why????

2. Session.clear(), Session.close(), SessionFactory.evictXXX()

3. It is impossible to auto-associate a POJO with the current threadlocal session without resorting to AOP-style interception. This requires control of the build or classloader, which we don't want. Since we won't do it for POJOs, we must not corrupt our semantics by having auto-association for some objects (eg. collections, proxies) and not others. And you don't need it anyway: Session.lock() is not hard to do.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 19, 2003 12:33 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
OK, I think I've figured out what you might be talking about.


* In Hibernate, at the end of a (database) txn, if we keep the same session open, we keep the session cache
* In JDO, by default, at the end of the txn, if we keep the same PM, all instances transition to "hollow"

What this means is that if we re-use the same session for multiple database txns (ie. for a whole "application transaction"), Hibernate uses more aggressive caching, and relies upon optimistic locking to detect stale data problems (which is ok, but only for the duration of the application txn). So in Hibernate we should NEVER keep a Session open for an entire user login session, only for the duration of an application txn.

On the other hand, JDO uses much less aggressive caching in this same scenario - it reloads all accessed objects at the start of each new transaction. This is a more pessimistic approach to concurrency. In fact, in JDO, we could potentially use the same PM for the entire user session, I think.

So what we have is a classic tradeoff between optimistic (performance) and pessimistic (less risk of an optimistic lock failure).

To implement the JDO-style behaviour in Hibernate would be easy enough, but would require that the session *always* return proxies (which is ok, I suppose). And we would simply add a refresh() method to the session, which "uninitializes" the proxies. Mmmmm its doable. But is it actually good? I'm a really big fan of optimistic locking.....


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