Hibernate session issue - java

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

Related

Proper Hibernate Layer Design

Im developing a java web application using hibernate and I came across a basic problem:
Given user A triggers some Hibernate transaction. Start transaction, load, commit transaction.
At the same time, user B triggers a similar transaction. Then, the will get an exception: nested transactions not supported.
It seems that no more than one transaction can be active at one time.
I researched for a solution and found a lot of overview explainations like transaction-per-session pattern, but nothing tangible.
So my question is: What is a proper and simple way to handle hibernate transactions for multiple concurrent users?
the transaction management is quite standard, just remember any exceptions thrown by Hibernate are fatal , you have to roll back the transaction and close the current session immediately.
You have to close the each and every transaction.
Session session = null;
Transaction t = null;
try{
session = HibernateUtil.getSessionFactory().openSession();
t = session.beginTransaction();
//do what ever you want(session);
t.commit();
}catch(RuntimeException e){
System.out.println(e.getMessage());
}

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.

Session Management with Java Hibernate

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

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