Sri
Sri

Reputation: 85

Where to open and where to close SessionFactory in my Application

I am developing jsf application and using hibernate as back end. I want create session factory and close it once through out application. I am creating Session factory with util class.

import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

public class HibernateUtil
{
private static SessionFactory sessionFactory;
private static ServiceRegistry serviceRegistry;

static
{
    try
    {
        Configuration configuration = new Configuration().configure();

        serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
    }
    catch (HibernateException he)
    {
        System.err.println("Error creating Session: " + he);
        throw new ExceptionInInitializerError(he);
    }
}

public static SessionFactory getSessionFactory()
{
    return sessionFactory;
} 
}

 public static void closeFactory() {
    if (sessionFactory != null) {
        try {
            sessionFactory.close();
        } catch (HibernateException ignored) {
            log.error("Couldn't close SessionFactory", ignored);
        }
    }
}

In my every method of DAO classes I am opening session factory and closing it. So where i can open/close the session factory only once for application. Thanks in advance.

Upvotes: 4

Views: 25845

Answers (6)

subhakar patnala
subhakar patnala

Reputation: 319

Where to open and where to close SessionFactory in my Application

You are using singleton session factory object. So you can call the getSessionFactory() method with class name. So that you do need to create object for session factory every time.

Your DAO class methods should like this

Method in DAO class

public boolean createUser(NewUserDTO newUserDTO) {
    try {
        sessionFactory = DBUtils.getSessionFactory();
        session = sessionFactory.openSession();
        transaction = session.beginTransaction();
        session.save(newUserDTO);
        session.getTransaction().commit();
    } catch (RuntimeException runtimeException) {
        LOGGER.error(runtimeException);
        transaction.rollback();
        return false;
    } finally {
        if (session != null) {
            session.close();
        }
    }
    return true;
}

And session must be closed for every method. So that you are not creating session factory for every class.

Upvotes: -2

its not enough to close the session. You must additonally close the factory.

session.close();
session.getSessionFactory().close();

Upvotes: 0

AnirbanDebnath
AnirbanDebnath

Reputation: 1043

The best way is by using 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().

Upvotes: 2

Serge Ballesta
Serge Ballesta

Reputation: 149125

The rule is that you should have one and only one SessionFactory throughout your application.

Where to open and close it depends on what the application is :

  • for a classic application, it would be opened and closed in main.
  • for a web application it would be opened and closed in a ServletContextListener (respectively in contextInitialized and contextDestroyed events)

You can also use a singleton and create it in static method as you do and close it at the end like above.

But please do not close the session factory at the end of a DAO method.

For Sessions, you get one at the beginning of a unit of work through openSession, and close it after commit or rollback (in case of exception you must rollback and immediately close the session). But Hibernate manual states : The scope of a Hibernate org.hibernate.Session is flexible but you should never design your application to use a new Hibernate org.hibernate.Session for every database operation. Even though it is used in the following examples, consider session-per-operation an anti-pattern.

Normally, you will use one single session per what needs a transaction. For example in a Web application, session per request is a common design.

But you could also use a higher level framework like Spring, that will do all SessionFactory and Session management for you.

Upvotes: 11

OO7
OO7

Reputation: 2807

SessionFactory: The job of SessionFactory is to handle all the sessions in the application. Generally, there is only one sessionFactory in the application which allows to create as many as sessions required to perform CRUD operations.

SessionFactory is immutable & threadsafe. Therefore multiple threads can access the same sessionFactory object.

static {
    try {
        Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
        serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
                configuration.getProperties()).build();
        sessionFactory = auditConfiguration.buildSessionFactory(serviceRegistry);
    } catch (Throwable ex) {
        System.err.println("Initial SessionFactory creation failed." + ex);
        throw new ExceptionInInitializerError(ex);
    }
}

Session: Session is a light weight and a non-threadsafe object. Hence, session cannot be shared between multiple threads. It should be created for every transaction on DB either Create, Read, Update or Delete & must be closed when transaction is done.

try {
    Session session = sessionFactory.openSession();
    // do some CRUD operation
} catch(Exception ex) {
    // On error, revert all changes done
    if (transaction != null) {
        transaction.rollback();
    }
} finally {
    if (session != null) {
        session.close();
    }
}

So I suggest u to open/close session instead of sessionFactory.

Upvotes: 5

techPackets
techPackets

Reputation: 4516

So where i can open/close the session factory only once for application.

A session factory is instantiated only once per application & gets destroyed when the app shuts down. A session factory is a factory of session so it's setup only once.

Regarding sessions, you should open & close a session in every method. You should not have too many open sessions.

So its a must that you close the session after the transaction.

When you don't close your Hibernate sessions and therefore do not release JDBC connections after every transaction, you have what is typically called Connection leak. So, after a number of requests (depending on the size of your connection pool) the server will not be able to acquire a connection to respond your request. Actually, server will be waiting for connections to be released and be available on pool again and it will seem to be hanging.

Upvotes: 0

Related Questions