Hibernate opening/closing session, the correct approach for DAO

14,681

Good approach is to add close method to your DAO(AbstractDao) and call it the end of your "unit of work".

And, please, no static references to session, session is not thread safe


Here is a brilliant explanation with sample: Link

Share:
14,681
HeavenAgain
Author by

HeavenAgain

Updated on June 04, 2022

Comments

  • HeavenAgain
    HeavenAgain almost 2 years

    I have written this Hibernate object DAO, however with this approach, it is using session per update approach (which I don't think it's right).

    The reason why I don't think its right because I am running into problems with my User class, which contains collections that are lazily fetched. Since when retrieving each User from the DAO, the session is closed. Therefore I cannot get my collections.

    From time to time, it is also doing a lot of unnecessary updates to the table because the object is detached.

    So are there any ways of fixing my DAO, like using getCurrentSession()?

    import java.util.List;
    
    import org.hibernate.HibernateException;
    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    
    import org.test.util.DataAccessLayerException;
    import org.test.util.HibernateUtil;
    
    public abstract class AbstractDao {
        protected Session session;
        protected Transaction tx;
        public AbstractDao() {
            HibernateUtil.buildIfNeeded();
        }
        protected void saveOrUpdate(Object obj) {
            try {
                startOperation();
                session.saveOrUpdate(obj);
                tx.commit();
            } catch (HibernateException e) {
                handleException(e);
            } finally {
                HibernateUtil.close(session);
            }
        }
        protected void delete(Object obj) {
            try {
                startOperation();
                session.delete(obj);
                tx.commit();
            } catch (HibernateException e) {
                handleException(e);
            } finally {
                HibernateUtil.close(session);
            }
        }
        protected Object find(Class clazz, Long id) {
            Object obj = null;
            try {
                startOperation();
                obj = session.load(clazz, id);
                tx.commit();
            } catch (HibernateException e) {
                handleException(e);
            } finally {
                HibernateUtil.close(session);
            }
            return obj;
        }
        protected List findAll(Class clazz) {
            List objects = null;
            try {
                startOperation();
                Query query = session.createQuery("from " + clazz.getName());
                objects = query.list();
                tx.commit();
            } catch (HibernateException e) {
                handleException(e);
            } finally {
                HibernateUtil.close(session);
            }
            return objects;
        }
        protected void handleException(HibernateException e) throws DataAccessLayerException {
            HibernateUtil.rollback(tx);
            throw new DataAccessLayerException(e);
        }
        protected void startOperation() throws HibernateException {
            session = HibernateUtil.openSession();
            tx = session.beginTransaction();
        }
    }
    

    HibernateUtil

    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    
    public class HibernateUtil {
    
        private static Log log = LogFactory.getLog(HibernateUtil.class);
        private static SessionFactory sessionFactory;
    
        private static SessionFactory configureSessionFactory()
                throws HibernateException {
            Configuration configuration = new Configuration();
            configuration.configure();
            sessionFactory = configuration.buildSessionFactory();
            return sessionFactory;
        }
    
        public static SessionFactory buildIfNeeded()
                throws DataAccessLayerException {
            if (sessionFactory != null) {
                return sessionFactory;
            }
            try {
                return configureSessionFactory();
            } catch (HibernateException e) {
                throw new DataAccessLayerException(e);
            }
        }
    
        public static SessionFactory buildSessionFactory()
                throws HibernateException {
            if (sessionFactory != null) {
                closeFactory();
            }
            return configureSessionFactory();
        }
    
        public static SessionFactory getSessionFactory() {
            return sessionFactory;
        }
    
        public static Session openSession() throws HibernateException {
            buildIfNeeded();
            return sessionFactory.openSession();
        }
    
        public static void closeFactory() {
            if (sessionFactory != null) {
                try {
                    sessionFactory.close();
                } catch (HibernateException ignored) {
                    log.error("Couldn't close SessionFactory", ignored);
                }
            }
        }
    
        public static void close(Session session) {
            if (session != null) {
                try {
                    session.close();
                } catch (HibernateException ignored) {
                    log.error("Couldn't close Session", ignored);
                }
            }
        }
    
        public static void rollback(Transaction tx) {
            try {
                if (tx != null) {
                    tx.rollback();
                }
            } catch (HibernateException ignored) {
                log.error("Couldn't rollback Transaction", ignored);
            }
        }
    }
    
  • HeavenAgain
    HeavenAgain over 12 years
    But that way I will only be using 1 session. Is that desired?
  • AAaa
    AAaa over 12 years
    As you use startOperation() to get a new session, you can use closeOperation() to close the session, and use it whenever you like..
  • Ian McLaird
    Ian McLaird over 10 years
    if you make the session static, this interaction pattern is not thread safe.