Session Management with Java Hibernate - java

I have a Hibernate-based platform, built from stateless servlets (one is used to register a user and the rest to query the db).
I'm using Hibernate's sessions as follows:
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
if ((null == session) || (session.isOpen() == false)) {
session = HibernateUtil.getSessionFactory().openSession();
}
Currently I do not close the session at the end of the servlet in order to avoid openSession() call (trying to use opened sessions if possible).
What's the best practice ? when am I supposed to close these sessions ?
Can you please give an example ?
Thanks in advance !

The best practice is in most cases session-per-request. That is, open a session in the beginning of handling a request, and close it in the end. You can do that in a Servlet Filter, for example.
Having one session for the entire application is bad, because it will accumulate a lot of entities in its 1st level cache, which is a memory leak. It may also produce undeterministic results when multiple clients use it at the same time.
Your code, however, is not using one session for the entire application - it is using the "current session" concept, which opens a session and stores it in a context (a ThreadLocal for example). But if you don't close it, it will stay there forever. Plus, it will cause the same problems as described above, because threads are reused in a web application, and a new request will get an old, unclosed session at some point.

Its always better to open a new session for every request, and close the session once the request is processed. Like
Session session = HibernateUtil.getSessionFactory().openSession();
instead of
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
If we use the getCurrentSession() method , tansaction.commit() / rollback() closes the connection.

The best is to manage a hibernate session is to open a new session for every request.
It all depends on how you obtain the session.
if you use sessionFactory.getCurrentSession(), you'll obtain a
"current session" which is bound to the lifecycle of the transaction
and will be automatically flushed and closed when the transaction
ends (commit or rollback)
if you decide to use sessionFactory.openSession(), you'll have to
manage the session yourself and to flush and close it "manually".
if (!session.isOpen()) {
session = session.getSessionFactory().openSession();
session.beginTransaction();
}

I better recommend you to use spring framework. Cause in spring you can use #Transactional at method level and session will be automatically created and closed by transaction manager (unless you are using any open session in view interceptor) using AOP which is internally handled by framework.
#Autowired
EntityManager em;
#Transactinal
void save(User user){
em.persist(user);
}
thats all.spring is fun :D

Related

Is it a good practice to use the same Hibernate Session over and over

I'm developing a JavaFX Hibernate desktop application. I configured my application so that I use the same session from the application runs till it close.
This is how I did it:
public static Session getCurrentSession() {
if (sessionFactory != null) {
Session session = sessionFactory.getCurrentSession();
if (session != null) {
return sessionFactory.getCurrentSession();
} else {
session = sessionFactory.openSession();
session.beginTransaction();
return session;
}
}
return null;
}
And when the User close the App, I run a second method that closes the session and the SessionFactory.
public static void closeConnections() {
if (sessionFactory != null) {
if (sessionFactory.getCurrentSession().isOpen()) {
sessionFactory.getCurrentSession().close();
}
sessionFactory.close();
}
}
I'm newB on Hibernate so be kind with me PEACE
Hibernate session should be thought of as a "single-unit-of-work". One or more transactions can live in a session. The best practice is in most cases session-per-request.Open a session in the beginning of handling a request, and close it in the end.
Hibernate's 1st level cache is mantained in the "Session" so that if you keep it around in the user session it will be hitting "cached" objects.
Hibernate has 2nd level cache that you have to configure (if you want) to take advantage of. The 2nd level basically supports the following: queries, objects with load and get, and collections/associations and provides cached objects across Sessions, SessionFactories, and Clusters.
You are not using one session per application, you are using the "current session" concept, which opens a session and stores it in a context.If you don't close your session it will stay there.
OK, for your basic question:
Is it a good practice to use the same Hibernate Session over and over?
Answer is no,the session objects should not be kept open for a long time because they are not usually thread safe and they should be created and destroyed them as needed.
What it is usually done in hibernate is:
You open a session (which is basically a database connection), do transactions, and then close your connection (close your session). In other words, you can check some other post's analogy :
What is the difference between a session and a transaction in JPA 2.0?
Hope it helps

Can you only have one hibernate session per thread in java?

So I'm working on an application without multi threading. We have a main business logic method that opens a Hibernate session like this:
session = HibernateSessionFactory.getSession();
tx = session.beginTransaction();
and then performs some light DB operations (a few selects). A method that I've overridden in a subclass is then called that needs to perform another select. I can't pass the session as a parameter without having to update 20ish subclasses.
I tried opening a new session and transaction and closing them when I was done, but when my method kicked back to the business method, I got an error that the session was closed. I tried not closing the session and committing the transaction, but that wasn't working either.
Right now I'm just using this and everything seems to be working properly locally:
session = HibernateSessionFactory.getSession();
tx = session.getTransaction();
and I'm only closing the session and rolling back incase of errors. I'm just uncertain if getSession will always return the session thats already open. Am I right to assume that only one session can be open at a time per thread?
Here's the implementation of getSession:
Session session = (Session) threadLocal.get();
if (session == null || !session.isOpen())
{
if (sessionFactory == null)
{
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession() : null;
threadLocal.set(session);
}
return session;
Thanks!
From my understanding, getSession will return a new hibernate session. There are two methods of using sessions in Hibernate that is described transactional patterns in the document: https://docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html/ch02.html
The actual "session" to the database depends on your connection to the database. Most people utilize a connection pool, like C3P0 that can be used to ensure session reuse and speed up your code.
The best structure I use is to create a SessionFactory once in application launch, as this sets up the connection pool to the database. Then, utilizing maybe a singleton pattern to keep a single SessionFactory, request new sessions for each transaction you perform from the single SessionFactory. Hibernate will utilize the underlying connection pool to handle session reuse for speed and optimization.

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