Tuesday, July 3, 2012

Session Management in Hibernate

Hibernate Session Management is an art. You must know where and how the session needs to be opened or closed. Each session once opened has to be closed, otherwise there will be whole bunch of opened sessions that it would give a permgen exception later.
I have gone through many examples on the Internet, where most of the example suggest opening a session using
HibernateUtil.getSessionFactory().openSession();. Opening a session is fine, but then you need to externally close the session. Moreover, each time you open a session, a new instance of session is created.
So, what should be the possible solution?

The R&D which i have done suggest me to have a single session per request. i.e. as a request comes, I open a session, and when all the work is over, I close the session. Then what shall be the difference in this statement and the above.

I'll  give you the difference. In the previous way of getting sessions, there might be possible that updates are done in two different session, where the state of the database is different in both session. There may be possiblity of loss of data, or maybe additional data which is not required may creep in.

To avoid,
in the hibernate.cfg.xml file, add the following two lines

 <property name="hibernate.current_session_context_class">thread</property>
  <property name="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

This ensures that the session is a thread safe session, which will be create once and shared everywhere.
In the doGet() or doPost() open a session using
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
and begin a transaction in servlet itself.
Transaction tx = session.beginTransaction();

Call the utility methods that you want to call from the servlets.

In each of the method, get the current session and begin a tranasaction.(even for a method), but this time, you are not creating a new session, but are using the already created session.

so suppose you have a method where in you are persisting the request data
In the method, open the session with

    session = HibernateUtil.getSessionFactory().getCurrentSession();
    tx = session.beginTransaction();

Remember where to commit the transaction because commiting the transaction automatically closes the session, with auto flushing the contents into the database.


So, if the call is suppose you are calling the method from the servlet, to save the inputs.
At the last statement of the method, you are commiting the transaction. then this would mean that session also is closed.
and then for any other purpose, you need to open the session again.

So, I suggest, you first understand where all you need to persist and use the data. I personally believe that commiting the transaction for this should be done exculsively in the servlet,s destroy method or finally block . because that's the only place where we can ensure that all the work would be over for that session and whatever data that has been processed in the data needs to be dumped into the database.

Bhavin.


No comments:

Post a Comment