Hibernate4.0之HibernateSessionFactory原始碼詳解

餘二五發表於2017-11-14
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
@SuppressWarnings(“deprecation”)
public class HibernateSessionFactory {
    /** 
     * Location of hibernate.cfg.xml file.
     * Location should be on the classpath as Hibernate uses  
     * #resourceAsStream style lookup for its configuration file. 
     * The default classpath location of the hibernate config file is 
     * in the default package. Use #setConfigFile() to update 
     * the location of the configuration file for the current session.   
     */
    
    private static String CONFIG_FIEL_LOACTION = “/hibernate.cfg.xml”;
    private static String configFile = CONFIG_FIEL_LOACTION;
    private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
    private static org.hibernate.SessionFactory sessionFactory;
    private static Configuration configuration = new Configuration();
    private static ServiceRegistry serviceRegistry; 
/**
   在回話工廠類HibernateSessionFactory中, 首先通過一次靜態程式碼塊來啟動Hibernate,該程式碼塊只在HibernateSessionFactory類被載入時執行一次,用於建立sessionFactory。即SessionFactory是執行緒安全的,只能被例項化一次。
在靜態程式碼塊中通過建立Configuration物件並呼叫其configure()方法讀取Hibernate配置檔案hibernate.cfg.xml資訊,從而進行配置資訊的管理。然後
建立SessionFactory例項,在Hibernate4.0版本之前,該例項建立工作由Configuration物件的buildSessionFactory()方法來完成。而Hibernater4.0版本之後,建立SessionFactory例項的方法有所改變,Hibernate 增加了一個註冊ServiceRegistryBuilder類。要生成一個序號產生器物件,然後所有的生成
SessionFactory的物件向序號產生器註冊一下再使用。生成方法還config.buildSessionFactory()方法,只不過加了一個序號產生器的引數。
*/
    static {
        try {
            configuration.configure();
            serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
            sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        } catch (Exception e) {
            System.err.println(“%%%% Error Creating SessionFactory %%%%” + e);
            e.printStackTrace();
        }
    }
    
    private HibernateSessionFactory() {
    }
    
    /**
     * Returns the ThreadLocal Session instance.  Lazy initialize
     * the <code>SessionFactory</code> if needed.
     *    
     * 由於sessionFactory是執行緒安全的,因而同一個SessionFactory例項可以被多個執行緒共享,即多個併發執行緒可以同時訪問一個SesisonFactory並
     * 獲得Session的例項。但由於Session不是執行緒安全的,如果多個併發執行緒同時操作同一個Session物件,就可能出現一個執行緒在進行資料庫操作,而另一個
     * 執行緒將Session物件關閉的情況,從而出現異常。如何才能保證執行緒安全呢?這就要求SessionFactory能夠針對不同的執行緒建立不同的Session物件,即
     * 需要對Session進行有效的管理,Hibernate中使用ThreadLocal物件來維護和管理Session例項。
     * 
     * ThreadLocal是執行緒區域性變數,執行緒區域性變數高效的為每一個使用它的執行緒提供單獨的執行緒區域性變數的副本。為了實現為每個執行緒維護一個變數的副本,ThreadLocal
     * 類提供了一個Map結構,是key值用來儲存執行緒的ID, value用來儲存一個Session例項的副本。這樣多執行緒併發操作時,實在與自己繫結的Session例項副本上進行
     * 的,從而避免多個執行緒橫在同一個Session例項上操作是可能導致的資料異常。
     *    
     * 在HibernaterSessionFctory類的getSession()方法中,首先呼叫ThreadLocal類的get()方法獲得當前執行緒的Session物件,然後判斷當前執行緒是否已存在
     * Session物件或者物件未開啟,在判斷SessionFactory物件是否為空,如果SeesionFctory物件不存在,先呼叫rebuildSessionFactory()方法建立SesionFactory,
     * 如果SessionFactory物件已經存在,則呼叫SessionFactory物件的openSession()方法建立Session物件。建立完Session物件後,還需要呼叫ThreadLocal的set()
     * 方法為該執行緒儲存Session物件。
     * 
     *  @return Session
     *  @throws HibernateException
     */
    public static Session getSession() {
        Session session = (Session) threadLocal.get();
        try{
            if (session == null || !session.isOpen()) {
                if (sessionFactory == null) {
                    rebuildSessionFactory();
                }
                session = (sessionFactory != null) ? sessionFactory.openSession()
                        : null;
                threadLocal.set(session);
            }
        } catch (HibernateException e){
            System.err.println(“%%%% Error Creating getSession %%%%” + e);
            e.printStackTrace();
        }
        return session;
    }
    /**
     *  Rebuild hibernate session factory
     *
     */
    public static void rebuildSessionFactory() {
        synchronized(sessionFactory){
            try {
                configuration.configure(configFile);
                serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
                sessionFactory = configuration.buildSessionFactory(serviceRegistry);
            } catch (Exception e) {
                System.err.println(“%%%% Error rebuildSessionFactory %%%%” + e);
                e.printStackTrace();
            }
        }
    }
    /**
     *  Close the single hibernate session instance.
     *
     *  @throws HibernateException
     */
    public static void closeSession(){
        Session session = (Session) threadLocal.get();
        threadLocal.set(null);
        try{
            if (session != null && session.isOpen()) {
                session.close();
            }
        } catch(HibernateException e){
            System.err.println(“%%%% Error closeSession %%%%” + e);
            e.printStackTrace();
        }
    }
    /**
     *  return session factory
     *
     */
    public static org.hibernate.SessionFactory getSessionFactory() {
        return sessionFactory;
    }
    /**
     *  return hibernate configuration
     *
     */
    public static Configuration getConfiguration() {
        return configuration;
    }
    
    public static void setConfigFile(String configFile){
        HibernateSessionFactory.configFile = configFile;
    }
}
本文轉自 小眼兒 部落格園部落格,原文連結:http://www.cnblogs.com/hujunzheng/p/4619460.html,如需轉載請自行聯絡原作者


相關文章