1. 程式人生 > >Hibernate工作原理

Hibernate工作原理

      現在我們知道了一個概念Hibernate Session,只有處於Session管理下的POJO才具有持久化操作能力。當應用程式對於處於Session管理下的POJO例項執行操作時,Hibernate將這種面向物件的操作轉換成了持久化操作能力。

HIbernate簡要的體系結構如下圖所示:

        通過上圖能夠發現HIbernate需要一個hibernate.properties檔案,該檔案用於配置Hibernate和資料庫連線的資訊。還需要一個XML檔案,該對映檔案確定了持久化類和資料表、資料列之間的想對應關係。

除了使用hibernate.properties檔案,還可以採用另一種形式的配置檔案: *.cfg.xml

檔案。在實際應用中,採用XML配置檔案的方式更加廣泛,兩種配置檔案的實質是一樣的。

        Hibernate的持久化解決方案將使用者從赤裸裸的JDBC訪問中釋放出來,使用者無需關注底層的JDBC操作,而是以面向物件的方式進行持久層操作。底層資料連線的獲得、資料訪問的實現、事務控制都無需使用者關心。這是一種“全面解決”的體系結構方案,將應用層從底層的JDBC/JTA API中抽象出來。通過配置檔案來管理底層的JDBC連線,讓Hibernate解決持久化訪問的實現。這種“全面解決”方案的體系結構圖如圖所示:

        針對以上的Hibernate全面解決方案架構圖:

      (1)SessionFactory

這是Hibernate的關鍵物件,它是單個數據庫對映關係經過編譯後的記憶體映象,它也是執行緒安全的它是生成Session的工廠,本身要應用到ConnectionProvider,該物件可以在程序和叢集的級別上,為那些事務之間可以重用的資料提供可選的二級快取。

      (2)Session:它是應用程式和持久儲存層之間互動操作的一個單執行緒物件。它也是Hibernate持久化操作的關鍵物件,所有的持久化物件必須在Session的管理下才能夠進行持久化操作。此物件的生存週期很短,其隱藏了JDBC連線,也是Transaction 的工廠。Session物件有一個一級快取,現實執行Flush之前,所有的持久化操作的資料都在快取中Session物件處。

      (3)持久化物件:系統建立的POJO例項一旦與特定Session關聯,並對應資料表的指定記錄,那該物件就處於持久化狀態,這一系列的物件都被稱為持久化物件。程式中對持久化物件的修改,都將自動轉換為持久層的修改。持久化物件完全可以是普通的Java Beans/POJO,唯一的特殊性是它們正與Session關聯著。

      (4)瞬態物件和脫管物件:系統進行new關鍵字進行建立的Java 例項,沒有Session 相關聯,此時處於瞬態。瞬態例項可能是在被應用程式例項化後,尚未進行持久化的物件。如果一個曾今持久化過的例項,但因為Session的關閉而轉換為脫管狀態。

      (5)事務(Transaction):代表一次原子操作,它具有資料庫事務的概念。但它通過抽象,將應用程式從底層的具體的JDBC、JTA和CORBA事務中隔離開。在某些情況下,一個Session 之內可能包含多個Transaction物件。雖然事務操作是可選的,但是所有的持久化操作都應該在事務管理下進行,即使是隻讀操作。

      (6)連線提供者(ConnectionProvider):它是生成JDBC的連線的工廠,同時具備連線池的作用。他通過抽象將底層的DataSource和DriverManager隔離開。這個物件無需應用程式直接訪問,僅在應用程式需要擴充套件時使用。

      (7)事務工廠(TransactionFactory):他是生成Transaction物件例項的工廠。該物件也無需應用程式的直接訪問。

  Hibernate進行持久化操作離不開SessionFactory物件,這個物件是整個資料庫對映關係經過編譯後的記憶體映象,該物件的openSession()方法可開啟Session物件。SessionFactory對想是由Configuration物件產生。

每個Hibernate配置檔案對應一個configuration物件。在極端情況下,不使用任何配置檔案,也可以建立Configuration物件。

一. 建立Configuration物件

        org.hibernate.cfg.Configuration例項代表一個應用程式到SQL資料庫的對映配置,Configuration提供了一個buildSessionFactory()方法,該方法可以產生一個不可變的SessionFactory物件。

        你可以直接例項化Configuration來獲取一個例項,併為它指定一個Hibernate對映檔案,如果對映檔案在類載入路徑中,則可以使用addResource()方法來新增對映定義檔案。那麼現在的問題就是如何建立Configuration物件呢?

隨著Hibernate 所使用的配置檔案的不同,建立Configuration物件的方式也不相同。通常有幾種配置Hibernate的方式:

第一種是使用hibernate.properties檔案作為配置檔案。

第二種是使用hibernate.cfg.xml檔案作為配置檔案。

第三種是不使用任何的配置檔案,以編碼方式來建立Configuration物件。

請注意:Configuration物件的唯一作用就是建立SessionFactory例項,所以它才被設計成為啟動期間物件,而一旦SessionFactory物件建立完成,它就被丟棄了。

1. 使用hibernateproperties作為配置檔案

        對於hibernate.properties作為配置檔案的方式,比較適合於初學者。因為初學者往往很難記住該配置檔案的格式,以及需要配置哪些屬性。在Hibernate釋出包的etc路徑下,提供了一個hibernate.properties檔案,該檔案列出了Hibernate 的所有屬性。每個配置段都給出了大致的註釋,使用者只要取消所需配置段的註釋,就可以快速配置Hibernate和資料庫的連結此處給出使用hibernate.properties檔案建立Configuration物件的方法。

//例項化configuration物件
Configuration cfg = new Configuration()
//多次呼叫addResource()方法,新增對映檔案
.addResource("Item.hbm.xml")
.addResource("Bid.hbm.xml");

        檢視hibernate.properties檔案發現,該檔案沒有提供Hibernate對映檔案的方式。因此使用hibernate.properties檔案來作為配置檔案時,必須使用Configuration的.addResource()方法,使用該方法來新增對映檔案。

注意:正如上面的程式碼所示,使用hibernate.properties檔案配置Hibernate的屬性固然簡單,但是因為要手動新增對映檔案,當對映檔案極其多時,這是一件非常催人淚下的事情。這也就是在實際開發中,不常使用hibernate.properties檔案作為配置檔案的原因。

        當然還有另一種新增配置檔案的策略,因為對映檔案和持久化類是一一對應的,可以通過Configuration物件來新增持久化類,讓Hibernate自己來搜尋對映檔案。

//例項化configuration物件
Configuration cfg = new Configuration)
//多次呼叫addClass()方法,直接新增持久化類
.addClass(ppp.Item.class)
.addClass(ppp.BId.class);

2. 使用hibernate.cfg.xml作為配置檔案

         前面已經看到使用hibernate.properties作為配置檔案的情形。因為hibernate.cfg.xml中已經添加了hibernate的對映檔案,採用這種配置檔案建立configuration物件例項由以下程式碼實現:

//例項化configuration物件
Configuration cfg = new Configuration()
//configure()方法將會負責載入hibernate.cfg.xml檔案
.configure()

        需要注意的是:在通過new關鍵字建立Configuration物件之後,不要忘記呼叫configure()方法。

二. hibernate.properties和hiberntae.cfg.xml檔案

        如果使用etc路徑下的hibernate.properties檔案作為配置檔案的模板,修改此模板檔案作為Hibernate配置檔案,這種方式的確是快速進入Hibernate開發的方法。但是對於實際開發,通常會使用hibernate.cfg.xml檔案作為配置檔案。

深入對比hibernate.properties和hibernate.cfg.xml檔案後看如下的hibernate.properties的一個配置屬性:

//指定資料庫的方言
hibernate.dialect org.hibernate.dialect.MySQLDialect

上面的一行程式碼是典型的Properties檔案的的格式,前面的key為hibernate.dialect , 後面的value是為org.hibernate.dialect.MySQLDialect。

接下來我們再來檢視hibernate.cfg.xml檔案中的相對應的配置程式碼:

<property name = "dialect">org.hibernate.dialect.MySQLDialect</property>

同樣指定了Hibernate的Dialect 屬性是org.hibernate.dialect.MySQLDialect 。對比兩種格式的檔案,可以發現雖然格式不同但其實質完全一樣。