2012-01-12 69 views
3

我已经编写了这个Hibernate对象DAO,但是使用这种方法,它使用的是每次更新的会话方式(我认为这不对)。休眠打开/关闭会话,DAO的正确方法

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

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

那么有没有办法修复我的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); 
     } 
    } 
} 

回答

0

可以HibernateUtil中持有的静态会话成员。延迟初始化。 随时关闭会话,但在未关闭之前,您将继续使用它。

+0

但这种方式,我将只使用1个会话。这是期望的吗? – HeavenAgain 2012-01-13 17:03:08

+0

当您使用startOperation()获取新会话时,可以使用closeOperation()关闭会话,并在您喜欢时使用它。 – AAaa 2012-01-14 11:33:51

+1

如果使会话保持静态,则此交互模式不是线程安全的。 – 2014-01-06 20:17:39

1

好方法是给你的DAO(AbstractDao)添加一个关闭方法,并把它称为你的“工作单元”的结尾。

而且,请于会议没有静态引用,会话不是线程安全的


这是一个辉煌的说明与示例:Link