2012-01-12 109 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