PeakGen
PeakGen

Reputation: 23025

Hibernate issue with `SessionFactory`

I am having a JSP, Servlet (Pure JSP, Servlet) application where it uses Hibernate. Below is a Hibernate implementation class for a one table.

DesignationImpl.java

package dao;

import model.sub.DesigAllBean;
import java.util.List;
import model.main.Designation;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;

/**
 *
 * @author Yohan
 */
public class DesignationImpl implements DesignationInterface
{


    @Override
    public Session openCurrentSession() {
            Session currentSession = getSessionFactory().openSession();
            return currentSession;
    }

    @Override
    public Transaction openTransaction(Session session) {
        Transaction beginTransaction = session.beginTransaction();
        return beginTransaction;
    }

    private static SessionFactory getSessionFactory() {

        Configuration configuration = new Configuration().configure();
        StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder()
                        .applySettings(configuration.getProperties());
        SessionFactory sessionFactory = configuration.buildSessionFactory(builder.build());
        return sessionFactory;
    }

    @Override
    public void save(Designation d, Session session)
    {
        session.save(d);
    }

    @Override
    public void update(Designation d, Session session) 
    {
        session.update(d);
    }
}

Below is the service class which calls to the above class.

DesignationService .java

package service;

import dao.Common;
import model.sub.*;
import dao.DesignationImpl;
import dao.DesignationInterface;
import java.util.ArrayList;
import java.util.List;
import model.main.Designation;
import org.hibernate.Session;
import org.hibernate.Transaction;

/**
 *
 * @author Yohan
 */
public class DesignationService 
{
    private DesignationInterface designationInterface;

    public DesignationService()
    {
        designationInterface = new DesignationImpl();
    }

    public Session getSession()
    {
        Session session = designationInterface.openCurrentSession();
        return session;
    }

    public Transaction getTransaction(Session session)
    {
        return designationInterface.openTransaction(session);
    }

    public String save(Designation d)
    {
        Session session = designationInterface.openCurrentSession();
        Transaction transaction = null;
        String result="";

        try
        {
            transaction = designationInterface.openTransaction(session);
            designationInterface.save(d,session);
            transaction.commit();
            result = Common.SAVE_SUCCESS;
        }
        catch(Exception e)
        {
            e.printStackTrace();

            if(transaction!=null)
            {
                transaction.rollback();
            }
            result = Common.SAVE_ROLLBACK;
        }
        finally
        {
            session.close();
        }

        return result;
    }

    public String update(Designation d)
    {
        Session session = designationInterface.openCurrentSession();
        Transaction transaction = null;
        String result="";

        try
        {
            transaction = designationInterface.openTransaction(session);
            designationInterface.update(d,session);
            transaction.commit();
            result = Common.SAVE_SUCCESS;
        }
        catch(Exception e)
        {
            e.printStackTrace();

            if(transaction!=null)
            {
                transaction.rollback();
            }
            result = Common.SAVE_ROLLBACK;
        }
        finally
        {
            session.close();
        }

        return result;
    }
}

And the servlets call them like below.

DesignationService desigSrvc=new DesignationService();

        Designation designation=desigSrvc.findByForiegnKey(idEmployee);

        Employee empl=new Employee();
        empl.setIdEmployee(idEmployee);

        if(designation.getDateCreated()==null)
        {
            designation.setDateCreated(Common.getCurrentDateSQL());
        }   

        designation.setEmployee(empl);
        designation.setDesignation(txtDesignation);
        designation.setLocation(location);
        designation.setSalary(salary);
        designation.setDatePromoted(datePromoted);
        designation.setLastUpdated(Common.getCurrentDateSQL());       

        desigSrvc.save(designation);

As you can see, there is a bad thing happening there, that is, the servlets are creating new SessionFactory instances every time it executes.I am having Driver#Connect issues and I guess this might be the reason for it.

I read stackoverflow posts and some seems to be suggesting the use of only one SessionFactory for the entire application. If it is suitable, then how can I do it? Maybe make a singleton class like below and use it in my implementation classes?

public class SessionFactoryBuilder
{
    private static SessionFactoryBuilder instance;
    private static SessionFactory sessionFactory;

    private SessionFactoryBuilder()
    {
    }

    private static void buildConfig()
    {
        Configuration configuration = new Configuration().configure();
            StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder()
                            .applySettings(configuration.getProperties());
            sessionFactory = configuration.buildSessionFactory(builder.build());
    }

    public static SessionFactoryBuilder getInstance()
    {
         if(instance == null) 
         {
            instance = new SessionFactoryBuilder();
            buildConfig();
         }
      return instance;
    }

    public SessionFactory getSessionFactory()
    {
        return sessionFactory;
    }
}

But then what about threads? Servlets are multi threaded isn't it?

Upvotes: 0

Views: 1021

Answers (2)

Tamás Sajti
Tamás Sajti

Reputation: 80

I corrected Viraj Nalawade's code which had a few errors:

class HibernateUtil {
    private static SessionFactory INSTANCE = null;

    public static SessionFactory getSessionFactory() {
        if (INSTANCE == null) {
            createSessionFactory();
        }
        return INSTANCE;
    }

    private synchronized static void createSessionFactory() {
        if (INSTANCE != null) {
            return;
        }
        Configuration configuration = new Configuration();
        configuration.configure();
        ServiceRegistry serviceRegistry = configuration.getStandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
        INSTANCE = configuration.buildSessionFactory(serviceRegistry);
    }
}

Upvotes: 0

Viraj Nalawade
Viraj Nalawade

Reputation: 3227

As I commented I have the HibernateUtil.java class as Singleton. This class can provide you sessionfactory using HibernateUtil.getSessionFactory() and you should remove the related code from your DesignationImpl class

public class HibernateUtil {

private static StandardServiceRegistry serviceRegistry; 
private static SessionFactory INSTANCE = null;
public static SessionFactory getSessionFactory() {
     if(INSTANCE=null){
          createSessionFactory():
      }
      return sessionFactory;
}
private synchronized static void createSessionFactory(){
    if(INSTANCE!=null){return;}
    Configuration configuration = new Configuration();
    configuration.configure();
    SeviceRegistry=newStandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
    sessionFactory = configuration.buildSessionFactory(serviceRegistry);
    }
  }
}

Find the above code, and please suggest / comment to confirm the correctness of code.I think threading will be taken care of using this..I adding a dual check to avoid multiple sessionfactory creation ad its a heavy resource.

Upvotes: 2

Related Questions