亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

Hibernate 會話工廠(SessionFactory)

1. 前言

Hibernate 的核心價值觀是:開發者們!做你們應該做的。臟的、累的、沒技術含義的由本尊來做。

本節課和大家一起好好的聊聊 Hibernate 的核心組件之一:會話工廠(SessionFactory)。

通過本節課,你將學習到:

  • 會話工廠的設計要求;
  • 會話工廠的核心功能。

2. 會話工廠的作用

原生 Jdbc 開發如同自己炒菜做飯,需經手買菜、洗菜、做菜…… 一系列過程。

基于 Hibernate 框架開發類似找一家餐館就餐,只需要坐在那里,訂一份菜單,稍等便會有色相味俱全的菜品出現在面前。

餐館并沒有省略買菜、洗菜、做菜一系操作,對于顧客而言,這些由餐館內部工作人員完成。

Hibernate 框架與此類似,原生 JDBC 開發的過程中一系列的標準流程一樣也不能少,只是由內部組件替代完成。

可把餐館當成一個出品菜肴的工廠,為就餐者承擔起一系列臟活、累活……

Hibernate 提供了一個 SessionFactory(會話工廠)對象,任勞任怨地為開發者承擔起 Jdbc 開發流程中底層的繁瑣事務操作。

2.1 概括會話工廠(SessionFactory)的功能

  • 為開發者屏蔽創建會話對象(session)時的一系列繁瑣事宜,讓開發者簡單、直接獲取 Session 對象,快速迭代自己的代碼功能;
  • 可根據開發者在主配置文件中的配置需求,提供高級輔助功能(如數據庫連接池……);
  • 會話工廠可緩存生成的 SQL 語句和 Hibernate 在運行時使用的映射元數據。

SessionFactory 類的設計顧名思議使用到工廠設計模式。經常會在一些框架程序中看到工廠設計模式,工廠設計模式的知名度如此之高,是由它自身的優勢決定的:

  • 工廠對象替開發者完成創建對象的細枝末節,讓開發者只需專注于如何運用對象;
  • 工廠對象內部可提供創建對象的優化方案,避免因開發者隨意創建對象所帶來的內存消耗。

古人打獵,需要用一周時間打磨工具,用一天時間捕捉獵物。現代人打獵前,可以去商店買一把獵槍,然后盡情享受打獵過程(保護野生動物,禁止打獵!)。

工廠設計模式對開發者說:享受開發吧!少年……

SessionFactory 從功能來講似乎簡單明了,創建 Session(其實這把獵槍不簡單)。

2.2 會話工廠的使用細節

使用細節需要開發者了解:

  • SessionFactory 可看成對某一個具體數據庫系統的抽象映射;
  • 項目不涉及多數據源時,整個應用程序只需要一個會話工廠,可在應用初始化時創建;
  • 多線程環境下,因 SessionFactory 需要在線程間共享,設計時考慮到了線程安全性問題,內部屬性多使用 final 關鍵字修飾;
  • 如果使用 Hibernate 訪問多個數據庫,則需要對每一個數據庫使用一個 SessionFactory。

綜上所述:

  • 實用生產級別項目中,建議使用單例設計模式封裝 SessionFactory 的創建,保證其應用程序作用域中的唯一性;
  • 盡量不要在封裝類中使用全局實例變量存儲數據,避開線程安全性問題。

3. 單例設計模式封裝會話工廠的創建

測試環境是一個演示、求證過程,測試一次創建一個 SessionFactory 對象并沒有什么不妥。

生產環境則不同,代碼結構上設計如果有缺陷,或者不遵循對象本身的特性需求。產品上線后,可能會因為產品的設計缺陷給客戶造成某種程度上的損失。

報酬拿不到事小,丟失市場信任事大。

使用 HibernateSessionFactory 對象封裝 SessionFactory 的創建:

public class  HibernateSessionFactory {
    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;  
    //加載類時創建會話工廠對象
    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.printStackTrace(); 
        } 
    }    
    private  HibernateSessionFactory() {
    } 
    public static Session  getSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
       if (session == null || !session.isOpen()) {   
            session = (sessionFactory != null) ? sessionFactory.openSession():null;                   
            threadLocal.set(session);
        }  
        return session; 
    }       
    public static void  closeSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
        threadLocal.set(null);
        if (session != null) {
            session.close();
        } 
    }      
    public static  org.hibernate.SessionFactory getSessionFactory() {
        return sessionFactory;
    } 
}  

HibernateSessionFactory 類內有很多代碼值得細細品味,本節課你只需要關注單例設計模式實現要素:

  • 構造方法私有化,創建對象的能力由內部決定,阻止外部非法任意創建;
  private HibernateSessionFactory() {
  }
  • SessionFactory 在類的靜態代碼塊內創建;
  private static  org.hibernate.SessionFactory sessionFactory;  
  //創建會話工廠,只會執行一次,也就只有一個對象
  static {
      //省略……
  }
  • 提供公開方法允許外部調用;
  public static org.hibernate.SessionFactory getSessionFactory() {
      //直接返回內部創建的會話工廠對象
      return sessionFactory;
  }

無論外部調用 getSessionFactory()方法多少次,最后創建的都只會有一個 SessionFactory 對象。

HibernateSessionFactory 類其它精華代碼留到下一節課程。

4. 小結

工廠、工廠又見工廠!

工廠設計模式是一種屏蔽底層細節,為開發者創建高質量對象的優秀設計方案。怎么表揚這種設計模式都不為過。

到了本節課程說再見時刻,建議開發者,通過本節課程的學習,不僅要理解、掌握 Hibernate 中會話工廠的使用,更能把工廠模式很好地運用到自己的真實項目中。

既要學會使用 Hibernate,也要掌握其內在核心思想。