72

I am new in hibernate,after read the hibernate api and tutorial,it seems that the session should closed when not used.

Like this:

Session sess=getSession();
Transcration tx=sess.beginTranscration();
//do something using teh session
sess.save(obj);
tx.commit();
sess.close;

I have no question when using it in a standlone application. However I am not sure when using in the web app.

For example, I have a servlet: TestServlet to receive the parameters from the client, then I call a Manager to query something according to the parameters, just like this:

class TestServlet{
  doGet(HttpServletRequset,httpServletResponse){
    String para1=request.getParam...();
    String para2=.....
    new Manager().query(para1,para2);
  }
}

class Manager{
  public String query(String pa1,String pa2){
    Session=....// get the session
    //do query using para1 and 1
    session.close() //Here, I wonder if I should close it.
  }
}

Should I close the session in the query method?

Since someone told me that session in hibernate is just like the connection in jdbc. So opening and closing it so frequently is the correct way?

BTW, does the tx.commit() is required each time?

Also what's the thread problem about using session in servlet, since I saw the session is not thread safe in api.

coding_idiot
  • 13,526
  • 10
  • 65
  • 116
hguser
  • 35,079
  • 54
  • 159
  • 293

4 Answers4

127

I am new in hibernate,after read the hibernate api and tutorial,it seems that the session should cloesd when not used.

It should be closed when you're done with (but this can be done automatically for you as we'll see).

I have no question when using it in a standalone application. However I am not sure when using in the web app.

Well, as explained in the section 11.1.1. Unit of work of the documentation, the most common pattern in a multi-user client/server application is session-per-request.

For example, I have a servlet:TestServlet to recieve the parameters from the client,then I call a Manager to query something according to the parameters: just like this (...) Should I close the session in the query method?

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".

To implement a session-per-request pattern, prefer the first approach (much easier and less verbose). Use the second approach to implement long conversations.

The wiki page Sessions and transactions is a good complement to the documentation on this topic.

BTW, does the tx.commit() is required each time?

You might want to read Non-transactional data access and the auto-commit mode to clarify a few things but, to put it simply, your Hibernate code has to be executed within a transaction and I'd suggest to use explicit transaction boundaries (i.e. explicit beginTransaction and commit).

Also what's the thread problem about using session in servlet, since I saw the session is not thread safe in api.

Just don't make it an instance variable of the Servlet and you won't have any problem.

References

SpringLearner
  • 13,738
  • 20
  • 78
  • 116
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • Thanks for your reply. Now I decide create a static class HibernateUtil which can return session by getCurrentSession(),then I call the HibernateUtil to get a session in other place. Is this right? – hguser Oct 29 '10 at 08:24
  • Also,**each session per requset**, I wonder if this will cause low perfromance, since when I did not use hibernate, I will use a ConnectionPool. – hguser Oct 29 '10 at 08:28
  • 6
    @hguser: If you're not using EJB or Spring, then yes, go for a HibernateUtils class. And no, obtaining a Session is not an expensive operation and is not a performance concern, it's not worse than obtaining a connection from the pool. – Pascal Thivent Oct 29 '10 at 10:41
  • Thanks :) A related question: how should I know about jdbc,and sql to use and learn hibernate better? – hguser Oct 29 '10 at 11:27
  • so,getCurrentSession() will auto closed by the "session context" implementation. – lovespring Apr 03 '14 at 03:47
  • @lovespring that's how I understand it as well. @PascalThivent, the two bullet-points under `It all depends on how you obtain the session.` are key -- consider moving it closer to the top of your answer. When Iwas hurriedly searching a few days ago, I couldn't find the direct info I was looking for in your answer; I missed it. – Don Cheadle Jan 28 '15 at 21:49
  • hi, `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 the getCurrentSession is not in transaction, will it auto-close? – Sam YC Aug 22 '16 at 03:08
2

If you are getting session through sessionFactory.openSession() then you have to close it externally. Opened session for unintended period can cause the data leaks. Plus it can give invitation to Web App security threat.

KernelPanic
  • 2,328
  • 7
  • 47
  • 90
1

We can make use of ThreadLocal.

public class MyUtil {
private static SessionFactory sessionFactory;
private static ServiceRegistry serviceRegistry;
private static final ThreadLocal<Session> threadLocal;

static {
try {
    Configuration configuration = new Configuration();
    configuration.configure();
    serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
    sessionFactory = configuration.buildSessionFactory(serviceRegistry);
    threadLocal = new ThreadLocal<Session>();

    } catch(Throwable t){
      t.printStackTrace();
      throw new ExceptionInInitializerError(t);
    }
}
public static Session getSession() {
    Session session = threadLocal.get();
    if(session == null){
        session = sessionFactory.openSession();
        threadLocal.set(session);
    }
    return session;
}

public static void closeSession() {
    Session session = threadLocal.get();
    if(session != null){
    session.close();
    threadLocal.set(null);
    }
}

public static void closeSessionFactory() {
    sessionFactory.close();
    StandardServiceRegistryBuilder.destroy(serviceRegistry);
   }
}

Here, the SessionFactory is initialized only once using the static block. Hence, whenever the main class makes a call to getSession(), the presence of Session object is first checked in the threadLocal object. Therefore, this program provides thread-safety. After each operation, closeSession() will close the session and set the threadLocal object to null. Finally call the closeSessionFactory().

AnirbanDebnath
  • 990
  • 16
  • 26
1

A session is opened whenever getCurrentSession() is called for the first time and closed when the transaction ends.

This creates a brand new session if one does not exist or uses an existing one if one already exists. It automatically configured with both auto-flush and auto-close attributes as true means Session will be automatically flushed and closed.

Ff you are using getCurrentSession() then no need to close the connection if you are going to tried this then you will face an exception.

Rastalamm
  • 1,712
  • 3
  • 23
  • 32