How should i manage Sessions and Transactions in hibernate? - java

I have a function that has some nested if statements and a query in each of the if statements ,how should i manage transaction and session calls.I know that i should bind each call with seperate transaction .
Session session=null;
Transaction tx=null;
if(!list.isEmpty()){
session=factory.openSession();
tx=session.beginTransaction();
session.createQuery(" update Tbluser set loggedStatus='9'").executeUpdate();
tx.commit();
session.close();
if(list.get(1)=="N")
{
///some query
}
}
should i have not closed the session just yet or should i create a new Session object for the new query that i have? or what else should be the correct approach?

If all the operations in the if blocks are related and atomic, you should consider opening one session and transaction before the first if block and commit/close after the last if block.
If each operations is separate, then you can open one session before the first if and enclose each if in a new transaction.

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());
}

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

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.

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