-->
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.  [ 18 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: how does Hibernate manages data changed by other apps ?
PostPosted: Tue Oct 07, 2003 6:00 am 
Newbie

Joined: Wed Aug 27, 2003 2:43 am
Posts: 19
Location: Paris
Hello,

How does Hibernate cope with other applications changing data already loaded in a Session ?

What are the best practices to keep object up to date in an environment where several applicaiton simulatneously change the database ? (I think this is called dirty-checking...)

Thanks,
Adrian.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 07, 2003 6:03 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
A Session is a transaction-scoped cache. Of course, you don't want to violate transaction isolation, so a Session doesn't care about other changes. You can of course disable (or not enable) the process-level JCS cache and only have the first level Session cache.

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


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 07, 2003 6:20 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
...and keep the Session's shortlived! The shorter, the more uptodate your queries will be.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 07, 2003 6:25 am 
Newbie

Joined: Wed Aug 27, 2003 2:43 am
Posts: 19
Location: Paris
Ok, so I obviously use Hibernate in a wrong way because I keep a Session open in my middle layer for a very long time.

Why do I do that: because lazy loading is extremely important in my app. And my understanding was that if I close a Session and than access lazy associations, the access will fail.

So I thought: why not let the Session open for the lifetime of an HTTP Session (it is a web application). This way, I benefit from Hibernate's caching etc. etc.

Could you advise me on how should this be done ?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 07, 2003 6:34 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Well, I have a similar requirement. I'm using a Session the following way:

1. My DAO/persistence layer implementation calls a static SessionHelper.getSessoin() method. This method returns the Hibernate Session for the current running Thread, stored in SessionHelper in a ThreadLocal.

2. It is set as a ThreadLocal by a ServletFilter. This filter runs on each request and looks if there is a disconnected Hibernate Session stored in the HttpSession. It then will either reconnect this Session or create a new Session. Either way, I have a ThreadLocal Session.

3. At the end of each request, the filter will run again and disconnect the Hibernate Session. It is stored in the HttpSession.

4. I model my user interface as a state machine with nested states. That is, a state called "Product Detail View" has nested states, i.e. a user can click on some buttons in this view to show different kinds of information, but will always stay in the same parent state.

5. I use one Hibernate Session per "parent state". This means, I know when transittions from a "List View Search Result" to a "Product Edit Details View" occours and during this transition, reset (close and reopen) the Hibernate Session to get fresh data.

This is only one possible solution, and there are many more. Another one is to always initialize all required data before it is send to the UI tier.

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


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 07, 2003 6:36 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
That is not wrong usage - it all depends on your context.

Lazy loading only possible with a Session opened....you might look into to using disconnect/reconnect on a session - then you can have a session that crosses transaction boundaries........

...but remember - what are you exactly trying to do ? How do YOU ensure that your object graph is uptodate ? Do you just keep the objects hanging arouond for the whole entire HTTP session ? How do you get that object grpah updated ? Do you reupdate the whole graph on each request ? If yes - why not just open/close the session for each request instead ?....this stuff is something one should look into before embarking on keeping state across a HTTP session.....nothing unique for Hibernate ;)

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 07, 2003 7:33 am 
Newbie

Joined: Wed Aug 27, 2003 2:43 am
Posts: 19
Location: Paris
christian wrote:
Well, I have a similar requirement. I'm using a Session the following way:
1. My DAO/persistence layer implementation calls a static SessionHelper.getSessoin() method. This method returns the Hibernate Session for the current running Thread, stored in SessionHelper in a ThreadLocal.


Why does one Session have to be Thread local ? If a Session's life is long, it seems a pity to duplicate all the caching a Session does for all threads... Is it because Session is not thread-safe, perhaps ? If so, how can that manifest itself ? (I am not very familiar with thread-safeness)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 07, 2003 7:47 am 
Newbie

Joined: Wed Aug 27, 2003 2:43 am
Posts: 19
Location: Paris
max wrote:
Lazy loading only possible with a Session opened....you might look into to using disconnect/reconnect on a session - then you can have a session that crosses transaction boundaries........


Yes, in fact that is one thing I didn't do: disconnect/reconnect during the Session's lifetime. On double checking, I see it is recommended in sect 14.3.1. "Long session with automatic versioning".

max wrote:
How do YOU ensure that your object graph is uptodate ? Do you just keep the objects hanging arouond for the whole entire HTTP session ? How do you get that object grpah updated ? Do you reupdate the whole graph on each request ? If yes - why not just open/close the session for each request instead ?....this stuff is something one should look into before embarking on keeping state across a HTTP session.....nothing unique for Hibernate ;)


Well... I was kind of hoping that Hibernate would somehow realize which data is old by itself :) Don't throw objects at me, I'm just a lazy user who wants lazy loading...

So what I understand is that in order to be sure that the data one has in a Session is not stale (old), one must close and reopen that Session. That means that all cache will be invalidated, a flood of SELECTs will be reexecuted, and I was trying to avoid that...

Or not ?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 07, 2003 7:48 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
A Session is, by nature, not threadsafe. In one thread, you have to open a new Session from a SessionFactory (which is usually available from a Singleton/Registry/JNDI) and close it after you have finished your work. The only solution to keep a Session for longer than the execution of one thread is to disconnect it and reconnect it for a subsequent thread. Concurrent access is not allowed.

Usually, you have some methods in a DAO/persistence layer that are called in a single unit of work. An example would be: Find customer, check his account for validity, place the order. Each persistence/DAO method requires a Session, so what are your options here to deal with the Session?

The first strategiy is to pass a Session object around as an argument and to every method that requires a Session. This is obviously not a good idea.

The second option would be a Singleton Session, which is not allowed, because a Session can not be threadsafe.

The most elegant solution is a ThreadLocal variable. Look at this code:

Code:
public class HibernateSession {
   
   private static SessionFactory sessionFactory;
   public static final ThreadLocal session = new ThreadLocal();
   
    public static Session currentSession()
        throws HibernateException {

      Session s = (Session) session.get();
      if (s == null) {

        // Don't get from JNDI, use a static SessionFactory
        if (sessionFactory == null) {

            // Use default hibernate.cfg.xml
            sessionFactory = new Configuration().configure().buildSessionFactory();

        }

         s = sessionFactory.openSession();
         session.set(s);
      }
      return s;
    }

    public static void closeSession()
        throws HibernateException {
       
       Session s = (Session) session.get();
       session.set(null);
       if (s != null) s.close();
    }
   
}


This is from http://www.hibernate.org/Documentation/ ... catAndJNDI and is a good start if you want to implement your own HibernateSession helper class. Just call currentSession() in your DAO/persistence layer and call closeSession() at the end of your unit of work, in my case, when i leave a "parent state".

Juergen has also written some things about this in his Hibernate and Spring documentation. If you need a framework that deals with all this Session and Transaction demarcation, have a look at

http://www.hibernate.org/Documentation/ ... gFramework

HTH

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


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 07, 2003 7:51 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
dimulescu wrote:
So what I understand is that in order to be sure that the data one has in a Session is not stale (old), one must close and reopen that Session. That means that all cache will be invalidated, a flood of SELECTs will be reexecuted, and I was trying to avoid that...

Or not ?


Well, you can of course evict() and refresh() your objects. But there is simply no other way, we are not doing any magic here :) In my experience, problems with the stale data and unclear transactions semantics are usually a sign of an ad-hoc design. You are no longer dealing with cache-less, primitive access to some records with JDBC, but try to build a transactional caching system. Get an overview of all the problems first and then look for existing solutions, like our Design Patterns or the Spring framework.

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


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 07, 2003 8:42 am 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
It is not good a idea to store cache in http session, memory usage depends on session count and it limits app availability.
I prefer to store nothing more than authentication info in http session and use soft global cache (session id can be one of keys if you need it).


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 07, 2003 8:56 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Yes, I forgot to add that. My first strategy(I only implemented it once...) is not as scalable as others.

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


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 07, 2003 9:38 am 
Newbie

Joined: Wed Aug 27, 2003 2:43 am
Posts: 19
Location: Paris
First, thank you all very much for your help, it is really useful. Unfortunately, it not over :)

Ok, so I: 1) thread-safed my application and 2) I now disconnect the Session after every method of my DAO interface.

But I get an unexpected problem:

christian wrote:
Usually, you have some methods in a DAO/persistence layer that are called in a single unit of work. An example would be: Find customer, check his account for validity, place the order. Each persistence/DAO method requires a Session, so what are your options here to deal with the Session?


Exactly, that's also my case. I have a DAO class called LazyHibernateSerializer which uses Hibernate to do stuff like, for instance,

Code:
Site getSite(long id)
.

After LazyHibernateSerializer.getSite(long) finished, the Session (inside LazyHibernateSerializer) is now disconnect()-ed. And here's the interesting part:

In my case, Site has a 1-n lazy association with Service. If I do
Code:
site.addService(Service serv)
-- which actually uses the PersistentCollection's add() method -- , I will get an exception "Session was disconnected"). And that's true because, guess what, I do disconnect the session after each access (method call) to the persistence layer.

And that seems to mean, exactly what I feared, I cannot use my lazy associations... And then, in order not to have this behaviour, I must not only keep my Session open but also connect()-ed ! (which is what I used to do and what I see now as not very intelligent thing to do...)

Can you see a better way of doing it? Can the Session somehow autoconnect() ? Do you not use the lazy collections in your object in the time between calling the DAO layer's methods ?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 07, 2003 9:49 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Thats easy. Don't disconnect the Session. Just get it from a ThreadLocal with a static helper method call.

Disconnecting the Session and storing it in a Session are not mutually exclusive concepts: You can use both or just one. In your case, use propably only a ThreadLocal and a HibernateSessionHelper that implements this. Your Session would be open as long as your thread runs and therefore "automagically" resolve lazy associations. You just have to find a way to close it at the end of the thread/request, usually with a Servlet filter. There is even a pattern for this in the Wiki, called "Open Session in view".

If you add the disconnect/reconnect concept on top of this, you simply don't close the Session, but disconnect and store it. This is a more complex and certainly a more resource intensive approach, because objects are cached in the HttpSession. In your case, ThreadLocal should be fine, without disconnect/reconnect.

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


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 07, 2003 9:52 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
And, because this is propably your next question: With a ThreadLocal, you have also various ways to implement Transaction handling. You can either start and commit a Transaction in each DAO method or start it before calling the DAO methods and commit it after the last: All calls would be in the scope of one database transaction. If you don't want to add methods like "beginTransaction()" and "endTransaction()" somewhere in your code and figure out how to start and commit a ThreadLocal Session in the implementation of these, check out either a declarative transaction framework like EJB or a lightweight approach with Spring.

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


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