1.持久化和ORM
持久化是指把數據(內存中的對象)保存到可持久保存的存儲設備中(如硬盤),主要應用於將內存中的數據存儲到關系型數據庫中,在三層結構中,持久層專注於實現系統的邏輯層面,將數據使用者與數據實體進行關聯。
ORM簡稱對象-關系型數據映射,在編寫程序時,處理數據采用面向對象的方式,保存數據卻以關系型數據庫的方式,因此需要一種能在兩者之間進行轉換的機制。這種機制稱為ORM。ORM保存了對象和關系型數據庫表的映射信息。Hibernate映射信息保存在XML格式的配置文件中。
2 Hibernate 核心接口框圖
2.1 Configuration類
在啟動Hibernate的過程中,Configuration實例首先確定映射文件hibernate.cfg.xml的位置,讀取相關的配置信息,最後創建一個唯一的SessionFactory實例,這個唯一的SessionFactory實例負責進行所有的持久化操作。Configuration類的實例只存在於系統的初始化階段。
2.2 SessionFactory接口
SessionFactory接口負責Hibernate的初始化。具體來說,在Hibernate中SessionFactory實際上起到了一個緩沖區的作用,Hibernate 自動生成的SQL語句,映射數據以及某些可重復利用的數據都可放在這個緩沖區中。同時它還保存了對數據庫配置的所有映射關系,維護當前的二級數據緩存和Statement Pool。
一般情況下,一個項目只需要一個SessionFactory,但當項目中要操作多個數據庫時,則必須為每個數據庫指定一個SessionFactory。
2.2.1 openSession方法和getCurrentSession方法的主要區別
在創建Session實例時,采用openSession,SessionFactory創建的是一個新的Session實例。而getCurrentSession方法創建的Session實例會被綁定到當前線程中。采用openSession方法,在使用完後需要顯示調用close方法進行手動關閉。而getCurrentSession方法創建的Session實例則會在提交(commit)或回滾(rollback)操作時自動關閉。
2.3 Session接口
Session對象的生命周期以Transaction對象的事物開始和結束為邊界。Session提供了一系列與持久化相關的操作,如讀取,創建和刪除相關實體對象的實例,這一系列的操作最終將被轉換為對數據庫中數據的增加,修改,查詢和刪除操作。所以,Session也被稱為持久化管理器。
2.3.1 實體對象的生命周期
對象在生命周期中所處的狀態有:瞬時態(Transient),持久態(Persistent)和游離態(Detached)。同一個實體對象進行不同的操作後其狀態會進行相互轉換。
(1)瞬時態
利用new操作符實例化後的對象所處的狀態即為瞬時態,這時還沒有存入任何數據庫表中。一旦他們不再被其他對象引用時,狀態立即丟失,且不能再被訪問,只能等待垃圾回收。
(2)持久態
持久態對象與Session實例是相關的,對持久態對象所做的任何操作都將被Hibernate持久化到數據庫中。持久態對象總和數據庫中的記錄相對應,Session對緩存做清理時,會依據持久態對象屬性的變化,來同步的更新數據庫。當session執行delete()方法時,不僅會從數據庫中刪除與之對應的記錄,還會把它從session的緩存中刪除。
(3)游離態
當處於持久態的對象不再與Session實例相關時,該對象就變成了游離態。此時對象中的屬性值發生變化,Hibernate不會再將變化同步到數據庫中。對於游離態的對象,Session執行delete()方法會從數據庫中刪除與之對應的記錄。游離態與瞬時態的不同在於游離態是有持久態轉換來的,因此在數據庫還保存有對應的記錄,而瞬時態在數據庫中是不存在任何記錄和它對應的。
2.3.2 使對象進入持久態的方法
update(),saveOrUpdate()和lock()方法可以將游離態對象轉換為持久態對象。與save()方法類似,在調用update()方法後,被保存的對象不是立刻就同步到數據庫,只有當事物結束的時候才會將實體對象當前的屬性值更新到數據庫中,不過當需要執行新的同表查詢時,為得到准確的查詢結果,就需要及時對數據庫進行更新。若一個持久態對象與一個瞬時態對象關聯,則在允許級聯保存的情況下,Session會在清理緩存時將瞬時態對象轉換為持久態對象。
saveOrupdate()方法根據實體對象的狀態由Hibernate來決定使用什麼方法,當傳入實體對象是瞬時態時,執行save()操作;當傳入是游離態時,執行update()方法;當傳入對象為持久態時直接返回,不進行任何操作。
load()方法或者get()方法都是通過標識符的到指定類的持久態對象(需要類型強轉),但要求持久化對象必須存在,否則會產生異常。兩者的區別在於:
(1)當所查找的記錄不存在時,get()方法會返回null,而load()方法則會拋出HibernateException 異常。
(2) get()方法直接返回實體類,load()方法則返回實體的代理類實例。當然,如果將*.hbm.xml中<class>元素的lazy屬性設置為false是,則load()方法 也是返回實體類,不返回代理類。而lazy屬性是有什麼用呢,他表示延遲加載,即當真正需要屬性時,才執行真正的數據加載操作,這樣做可以降低系統的性能開銷。 當lazy()設置為true時,load()返回持久化對象的代理類實例,該代理類實例是在運行時動態生成的,它包括了目標對象的所有屬性和方法。但是由於采用了延遲加載,此 代理實例的屬性中除了id屬性其他都為NULL,只有當代理類實例調用getXXX()方法時,Hibernate才真正到數據庫中獲得屬性值。
(3)load()和get()都是從Session內部緩存中開始查找指定對象,如果沒有找到,load()會去Hibernate二級緩存查詢,若還未找到,則會發送一條SQL 語句到數據庫中進行查詢,並根據查詢結果生成相應的實體對象。而get()會越過二級緩存,直接發出SQL語句到數據庫中完成數據讀取。
本文均為自己一字一句整理得到,如果你覺得還不錯,請關注我或點贊,至於Query,Criteria和Transaction接口會在接下來的Hql實例講解博客中再作介紹,謝謝觀看!
---------參考資料《Java Web整合開發實戰》《Struts2+Spring3+Hibernate框架技術精講與整合案例》