Hibernate开启/关闭会话,DAO的正确方法

我已经编写了这个Hibernate对象DAO,但是使用这种方法,它使用的是每次更新的方法(我不认为这是正确的)。

之所以我认为它是正确的,是因为我遇到了我的User类的问题,其中包含了延迟提取的集合。 从DAO检索每个用户时,会话将关闭。 因此我无法获得我的collections品。

有时,它也会对表进行大量不必要的更新,因为该对象已分离。

那么有没有办法修复我的DAO,比如使用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); } } } 

好的方法是为您的DAO(AbstractDao)添加close方法,并将其称为“工作单元”的结尾。

而且,请不要对会话进行静态引用,会话不是线程安全的


以下是样本的精彩解释: 链接

您可以在HibernateUtil中保存静态Session成员。 懒惰初始化。 随时关闭会话,但在关闭之前,您将继续使用它。