1. 程式人生 > >Hibernate的執行流程——SessionFactory的創建

Hibernate的執行流程——SessionFactory的創建

裏的 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的創建