Hibernate工作原理
現在我們知道了一個概念Hibernate Session,只有處於Session管理下的POJO才具有持久化操作能力。當應用程式對於處於Session管理下的POJO例項執行操作時,Hibernate將這種面向物件的操作轉換成了持久化操作能力。
HIbernate簡要的體系結構如下圖所示:
通過上圖能夠發現HIbernate需要一個hibernate.properties檔案,該檔案用於配置Hibernate和資料庫連線的資訊。還需要一個XML檔案,該對映檔案確定了持久化類和資料表、資料列之間的想對應關係。
除了使用hibernate.properties檔案,還可以採用另一種形式的配置檔案: *.cfg.xml
Hibernate的持久化解決方案將使用者從赤裸裸的JDBC訪問中釋放出來,使用者無需關注底層的JDBC操作,而是以面向物件的方式進行持久層操作。底層資料連線的獲得、資料訪問的實現、事務控制都無需使用者關心。這是一種“全面解決”的體系結構方案,將應用層從底層的JDBC/JTA API中抽象出來。通過配置檔案來管理底層的JDBC連線,讓Hibernate解決持久化訪問的實現。這種“全面解決”方案的體系結構圖如圖所示:
針對以上的Hibernate全面解決方案架構圖:
(1)SessionFactory
(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 。對比兩種格式的檔案,可以發現雖然格式不同但其實質完全一樣。