Hibernate的執行流程——SessionFactory的創建
阿新 • • 發佈:2018-08-18
裏的 new factor exceptio hiberna pack 事務 close add
Hibernate的執行流程:
1、創建Configuration類實例,用來讀取並解析配置文件(如Hibernate.cfg.xml),一個Configuration實例代表hibernate所有Pojo類到SQL數據庫映射的集合;
2、創建SessionFactory對象,用來讀取並解析映射信息,同時將上一步Configuration對象中的所有配置信息copy到SessionFactory緩存中;
3、通過上一步創建的SessionFactory對象,打開Session;
4、開始事務,事務指Session提供的接口對數據庫進行CRUD操作。
只有了解Hibernate的執行流程,才能夠更好的理解SessionFactory的創建過程。
先放代碼:
package com; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; public class HibernateSessionFactory { private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";private static final ThreadLocal<Session> sessionThreadLocal = new ThreadLocal<Session>();//創建一個ThreadLocal<Session>對象用來存放當前Session對象 private static Configuration configuration = new Configuration(); private static SessionFactory sessionFactory; private static String configFile = CONFIG_FILE_LOCATION;static { try{ configuration.configure();//讀取並解析hibernate.cfg.xml文件
//在Hibernate4.x會使用註冊機來解析映射信息,所以會先創建ServiceRegistry對象 ServiceRegistry serviceRgistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
//ServiceRegister對象作為參數,使用configuration對象創建sessionFactory對象,即將configuration對象裏的信息copy到sessionFactory緩存中 sessionFactory = configuration.buildSessionFactory(serviceRgistry); }catch(Exception e){ e.printStackTrace(); } }
//聲明一個私有無參構造函數 private HibernateSessionFactory(){} public static SessionFactory getSessionFactory(){ return sessionFactory; } public static void rebuildSessionFactory(){ synchronized(sessionFactory){ try{ configuration.configure(configFile); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); }catch(Exception e){ e.printStackTrace(); } } }
//打開session public static Session getSession(){
//獲取當前線程的session對象 Session session = sessionThreadLocal.get(); try{ if(session == null || !session.isOpen()){ if(sessionFactory == null){//如果sessionFactory為null,創建一個 rebuildSessionFactory(); }
//如果session沒有打開,就用sessionFactory打開 session = (sessionFactory!=null)?sessionFactory.openSession():null;
//將session對象放到ThreadLocal對象裏,以便使用 sessionThreadLocal.set(session); } }catch(Exception e){ e.printStackTrace(); } return session; } public static void closeSession(){ Session session = sessionThreadLocal.get(); sessionThreadLocal.set(null); try{ if(session != null && session.isOpen()){ session.close(); } }catch(Exception e){ e.printStackTrace(); } } public static void setConfigFile(String configFile){ HibernateSessionFactory.configFile = configFile; sessionFactory = null; } public static Configuration getConfiguration(){ return configuration; } }
代碼裏已經有部分註釋,相信足夠理解代碼了。這裏特別註意的一點就是,這個SessionFactory創建代碼使用的jar包是Hibernate4.x,如果使用5.x以上版本,需要對創建SessionFactory過程做出以下改變:
//添加add(User.class),這個User類是一個POJO類,對應數據庫的一個user表,hibernate.cfg.xml裏面有配置的,如果沒有這一條語句,將會報錯:Unknow Entity xxx
configuration。add(User.class); configuration.configure();//讀取並解析hibernate.cfg.xml文件 //在Hibernate5.x會使用註冊機來解析映射信息,所以會先創建ServiceRegistry對象,使用StandardServiceRegistryBuilder() ServiceRegistry serviceRgistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build(); //ServiceRegister對象作為參數,使用configuration對象創建sessionFactory對象,即將configuration對象裏的信息copy到sessionFactory緩存中 sessionFactory = configuration.buildSessionFactory(serviceRgistry);
細心的讀者可以看出,創建出來的SessionFactory是線程安全的,因此SessionFactory可以同時被多個線程共享,但是正常情況下,session並不是線程安全,每個線程都會使用這個session實例,如果多個線程同時操作數據庫時,某個線程將session關閉了,正在操作數據庫的線程就會出現異常,為了解決這個問題,代碼中使用ThreadLocal對象來保證session的線程安全,這樣的話,每個線程只會操作當前session實例的副本,不影響其他線程。
Hibernate的執行流程——SessionFactory的創建