What sessionFactory.getCurrentSession() does - java

The hibernate documentation says:
A org.hibernate.Session begins when the first call to
getCurrentSession() is made for the current thread. It is then bound
by Hibernate to the current thread. When the transaction ends, either
through commit or rollback, Hibernate automatically unbinds the
org.hibernate.Session from the thread and closes it for you. If you
call getCurrentSession() again, you get a new org.hibernate.Session
and can start a new unit of work.
If the property current_session_context_class is set to thread then what exactly hibernate does? What does it mean when they say current thread?
This post says SessionFactory.getCurrentSession() returns a session bound to a context, what it means exactly, can someone please clarify?

Related

Difference between HibernateTransactionManager and OpenSessionInViewFilter

From the docs - http://docs.spring.io/spring-framework/docs/2.0.x/api/org/springframework/orm/hibernate/HibernateTransactionManager.html
HibernateTransactionManager - Binds a Hibernate Session from the specified factory to the thread, potentially allowing for one thread-bound Session per factory
OpenSessionInViewFilter - This filter makes Hibernate Sessions available via the current thread, which will be autodetected by transaction managers.
What is the difference between both of them and at what scenarios should they be used ?
OpenSessionInViewFilter
Now when you are using OpenSessionInViewFilter, by default the session's flush mode is set to NEVER. So when you try to save something in your action using hibenate and commit it, it wont be reflected in your database. To solve this you need to flush the session in your action class or extend OpenSessionInViewFilter and override closeSession(Session session, SessionFactory sessionFactory).
Now it is also possible that you are maintaining a single transaction for per request. In your action you edit the attributes of a object and update it using session.update(object). But it is not yet commited as some other processing is remaining. At the same time, some other request is invoking a action which tries to retrieve the object which you were updating. Since the object is not yet commited the other request will get the old object. To solve this you need to begin a transaction before you load object and commit the transaction after you update the object. So that as soon as the object is saved/updated it is commited. With this there can be many transaction in single user request but only one session.
The OpenSessionInView pattern only guarantees that the session is open during one single thread execution.
When the page has been rendered and has been returned to the browser, the session gets closed by the filter.
So subsequent requests (e.g. navigation request) require another new session which will be opened by the OpenSessionInViewFilter. But as the "old" person object is not connected to the "new" session, it is considered as disconnected object which's references cannot be loaded lazily.

Hibernate session issue

When you first attempt to use a session Hibernate will create one and
attach it to your local thread. When you commit the transaction in the
session Hibernate will automatically close the session meaning it
can’t be reused. - got this quote from this site
how ever this is what my code looks like ,and i can i do close my hibernateSession every time i commited transaction:
Session session = HibernateUtil.getSessionFactory().openSession();
session.setFlushMode(FlushMode.AUTO);
session.beginTransaction();
session.getTransaction().commit();
session.close();
All of my code works fine, but there is issue :
For example if i add row in to database,saving success,if i add another one after 1-10 seconds. Hibernate Exception occurs saying Session is closed. but this not happen if i add another one if i wait upto 1 minute. Is this somewhat wrong in my code or the server im connecting is slow(I do have this idea because updates on my java servlet code is sometimes delay)? Any idea?
You did a good thing by opening a session whenever you need to commit a transaction but:
In general hibernate manages all the session closing and opening for you, so if you need to take the responsibility on your shoulders you need to change the following in hibernate config file : hibernate.cfg.xml
Property Name: current_session_context_class
Property Value: managed
To create a session and start a transaction you need this code:
org.hibernate.classic.Session session = HibernateUtil.getSessionFactory().openSession();
session.setFlushMode(FlushMode.MANUAL);
ManagedSessionContext.bind(session);
session.beginTransaction();
And to commit a transaction do the following:
ManagedSessionContext.unbind(HibernateUtil.getSessionFactory());
session.flush();
session.getTransaction().commit();
session.close();
Where you can be 100% sure that whenever you commit you un-attach the session from your thread and the gc will take care of it.
So whenever you need to do another transaction you need to run the first part of the code again.
try using .getCurrentSession() instead of openSession()
Instead of using
Session session = HibernateUtil.getSessionFactory().openSession();
use
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
To automatically close session when transaction is committed set below property as true in you hibernate configuration
hibernate.transaction.auto_close_session=true

How to reopen hibernate session after session was closed?

Is there is any session/hibernate function to reconnect/reopen
LOG: SEVERE: No operations allowed after connection closed.
No. You should create/open a new Session.
Here is code example how to ensure the session is always valid. Line 2 must reassign back the session as openSession returns a new session. Just session.getSessionFactory().openSession() is not enough.
if (!session.isOpen()) {
session = session.getSessionFactory().openSession();
session.beginTransaction();
}
// operate your session
Criteria criteria = session.createCriteria(clazz);
Hibernate Docs about Seesion says
The lifecycle of a Session is bounded by the beginning and end of a logical transaction. (Long transactions might span several database transactions.)
Once your transaction committed,Session wont available. You have to create a new one.

Read only data via Spring + Hibernate

Noticed that if I want to read some data and if I do not have a transaction context I will not be able to do so because
org.hibernate.HibernateException: No Session found for current thread
For reading data , is not required a transaction normally.
So in order for Spring to manage the session it needs to have a transaction even for read only operations like selects... ?
Is that not an overhead ?
PS.I do not want to open and close session manually...
Thanks a lot.
#Transactional tells spring to open and close a session, in addition to instructing it to start and commit a transaction. This is not very straightforward, but that's how it works. So if you don't have #Transactional, no session gets opened. Here are your options:
use #Transactional(readOnly=true) - the purpose is to have a read-only transaction. I recommend that one
use JPA EntityManager injected with #PersistenceContext. It will open a new underlying session for each invocation. Not that good option. But you should consider using EntityManager with a readOnly=true transaction
Use an additional aspect/interceptor/filter to open and close session. That would be hard, and you may end up confused by the spring implementation of hibernate's current session concept.

Open and close Hibernate session

This is how I get a Hibernate Session and create query.
HSession.getSession().createQuery("query here").executeUpdate();
AND
Critaria cr=HSession.getSession().createCritaria(..).. ;
HSession is where my Session factory is located and getSession() method returns a new session
(getSessionFactory().openSession();)
I want to know whether
After calling cr.list(); Is the session is still alive?
If alive, getting this criteria or executing a query way is not good? and
Creating a Session as
Session s=HSession.getSession();
s.createCriteria...
Is the way to use the session and close it using s.close(); ?
Yes, the session will be alive until you close it. You can perform multiple operations against a session, but only close() will close it.
In your case, it looks like the sessions are controlled by whatever HSession is. You'll need to look at that to see if any transactions are performed, how the sessions are managed, etc.
I read about this today ... it said "A Session is opened when getCurrentSession() is called for the first time and closed when the transaction ends."
So according to this: If you have a transaction wrapped around it (and you should have i guess) and call transaction.commit() ... the session is closed.
In your case it should still be open.
Please correct me if I'm wrong with this ... ! :)

Categories