Hibernate(開放原始碼的對象關係映射框架)

Hibernate(開放原始碼的對象關係映射框架)

本詞條是多義詞,共2個義項
更多義項 ▼ 收起列表 ▲

Hibernate是一個開放原始碼的對象關係映射框架,它對JDBC進行了非常輕量級的對象封裝,它將POJO與資料庫表建立映射關係,是一個全自動的orm框架,hibernate可以自動生成SQL語句,自動執行,使得Java程式設計師可以隨心所欲的使用對象編程思維來操縱資料庫。 Hibernate可以套用在任何使用JDBC的場合,既可以在Java的客戶端程式使用,也可以在Servlet/JSP的Web套用中使用,最具革命意義的是,Hibernate可以在套用EJB的JaveEE架構中取代CMP,完成數據持久化的重任。

基本介紹

  • 中文名:對象關係映射框架
  • 外文名:Hibernate
  • 套用:EJB的J2EE架構中取代CMP
  • 屬性:開放原始碼的對象關係映射框架
發展歷程,編程開發,編程環境,編程工具,語言特點,核心API,版本,主鍵介紹,包的作用,快取管理,一級快取,二級快取,延遲載入,性能最佳化,資料庫設計,HQL最佳化,主配置,快取,延遲載入,方法選用,集合的選用,事務控制,批量操作,

發展歷程

2001年,澳大利亞墨爾本一位名為Gavin King的27歲的程式設計師,上街買了一本SQL編程的書,他厭倦了實體bean,認為自己可以開發出一個符合對象關係映射理論,並且真正好用的Java持久化層框架,因此他需要先學習一下SQL。這一年的11月,Hibernate的第一個版本發布了。
2002年,已經有人開始關注和使用Hibernate了。
2003年9月,Hibernate開發團隊進入JBoss公司,開始全職開發Hibernate,從這個時候開始Hibernate得到了突飛猛進的普及和發展。
2004年,整個Java社區開始從實體bean向Hibernate轉移,特別是在Rod Johnson的著作《Expert One-on-One J2EE Development without EJB》出版後,由於這本書以紮實的理論、充分的論據和詳實的論述否定了EJB,提出了輕量級敏捷開發理念之後,以Hibernate和Spring為代表的輕量級開源框架開始成為Java世界的主流和事實標準。在2004年Sun領導的J2EE5.0標準制定當中的持久化框架標準正式以Hibernate為藍本。
2006年,J2EE5.0標準正式發布以後,持久化框架標準Java Persistent API(簡稱JPA)基本上是參考Hibernate實現的,而Hibernate在3.2版本開始,已經完全兼容JPA標準。

編程開發

編程環境

Hibernate是一個以LGPL(Lesser GNU Public License)許可證形式發布的開源項目。在Hibernate官網上有下載Hibernate包的說明。Hibernate包以原始碼或者二進制的形式提供。

編程工具

Eclipse:一個開放原始碼的、基於Java的可擴展開發平台。
Hibernate
NetBeans:開放源碼的Java集成開發環境,適用於各種客戶機和Web套用。
IntelliJ IDEA:在代碼自動提示、代碼分析等方面的具有很好的功能。
MyEclipse:由Genuitec公司開發的一款商業化軟體,是套用比較廣泛的Java應用程式集成開發環境。
EditPlus:如果正確配置Java的編譯器Javac”以及解釋器“Java”後,可直接使用EditPlus編譯執行Java程式。

語言特點

  • 將對資料庫的操作轉換為對Java對象的操作,從而簡化開發。通過修改一個“持久化”對象的屬性從而修改資料庫表中對應的記錄數據。
  • 提供執行緒和進程兩個級別的快取提升應用程式性能。
  • 有豐富的映射方式將Java對象之間的關係轉換為資料庫表之間的關係。
  • 禁止不同資料庫實現之間的差異。在Hibernate中只需要通過“方言”的形式指定當前使用的資料庫,就可以根據底層資料庫的實際情況生成適合的SQL語句。
  • 非侵入式:Hibernate不要求持久化類實現任何接口或繼承任何類,POJO即可。

核心API

Hibernate的API一共有6個,分別為:SessionSessionFactoryTransactionQueryCriteria和Configuration。通過這些接口,可以對持久化對象進行存取、事務控制。
Session
Session接口負責執行被持久化對象的CRUD操作(CRUD的任務是完成與資料庫的交流,包含了很多常見的SQL語句)。但需要注意的是Session對象是非執行緒安全的。同時,Hibernate的session不同於JSP套用中的HttpSession。這裡當使用session這個術語時,其實指的是Hibernate中的session,而以後會將HttpSession對象稱為用戶session。
SessionFactory
SessionFactory接口負責初始化Hibernate。它充當數據存儲源的代理,並負責創建Session對象。這裡用到了工廠模式。需要注意的是SessionFactory並不是輕量級的,因為一般情況下,一個項目通常只需要一個SessionFactory就夠,當需要操作多個資料庫時,可以為每個資料庫指定一個SessionFactory。
Transaction
Transaction 接口是一個可選的API,可以選擇不使用這個接口,取而代之的是Hibernate 的設計者自己寫的底層事務處理代碼。 Transaction 接口是對實際事務實現的一個抽象,這些實現包括JDBC的事務、JTA 中的UserTransaction、甚至可以是CORBA 事務。之所以這樣設計是能讓開發者能夠使用一個統一事務的操作界面,使得自己的項目可以在不同的環境和容器之間方便地移植。
Query
Query接口讓你方便地對資料庫及持久對象進行查詢,它可以有兩種表達方式:HQL語言或本地資料庫的SQL語句。Query經常被用來綁定查詢參數、限制查詢記錄數量,並最終執行查詢操作。
Criteria
Criteria接口與Query接口非常類似,允許創建並執行面向對象的標準化查詢。值得注意的是Criteria接口也是輕量級的,它不能在Session之外使用。
Configuration
Configuration 類的作用是對Hibernate 進行配置,以及對它進行啟動。在Hibernate 的啟動過程中,Configuration 類的實例首先定位映射文檔的位置,讀取這些配置,然後創建一個SessionFactory對象。雖然Configuration 類在整個Hibernate 項目中只扮演著一個很小的角色,但它是啟動hibernate 時所遇到的第一個對象。

版本

Hibernate版本
Hibernate版本更新速度很快,目前為止有多個階段性的版本:Hibernate3,Hibernate4和Hibernate5,這一點程式設計師從其Jar檔案名稱便可以看出來。目前(2018-01-10)最新發布的版本是Hibernate ORM 5.2.12.Final Released。
Hibernate2系列的最高版本是Hibernate2.1.8,Hibernate3系列的最高版本是hibernate-distribution-3.6.10.Final-dist版,但使用較多且較穩定的版本是Hibernate 3.1.3或Hibernate 3.1.2。
另外,自Hibernate3發布以來,其產品線愈加成熟,相繼出現了Hibernate注釋、Hibernate實體管理器、Hibernate外掛程式工具等一系列產品套件。在方便程式設計師使用Hibernate進行應用程式的開發的同時,也逐漸增強了Hibernate產品線的實力。
目前Hibernate已經出現了4.0以及5.0的版本

主鍵介紹

Assigned
Assigned方式由用戶生成主鍵值,並且要在save()之前指定否則會拋出異常
特點:主鍵的生成值完全由用戶決定,與底層資料庫無關。用戶需要維護主鍵值,在調用session.save()之前要指定主鍵值。
Hilo
Hilo使用高低位算法生成主鍵,高低位算法使用一個高位值和一個低位值,然後把算法得到的兩個值拼接起來作為資料庫中的唯一主鍵。Hilo方式需要額外的資料庫表和欄位提供高位值來源。默認情況下使用的表是
Hibernate相關書籍Hibernate相關書籍
hibernate_unique_key,默認欄位叫作next_hi。next_hi必須有一條記錄否則會出現錯誤。
特點:需要額外的資料庫表的支持,能保證同一個資料庫中主鍵的唯一性,但不能保證多個資料庫之間主鍵的唯一性。Hilo主鍵生成方式由Hibernate 維護,所以Hilo方式與底層資料庫無關,但不應該手動修改hi/lo算法使用的表的值,否則會引起主鍵重複的異常。
Increment
Increment方式對主鍵值採取自動增長的方式生成新的主鍵值,但要求底層資料庫的主鍵類型為long,int等數值型。主鍵按數值順序遞增,增量為1。
/*特點:由Hibernate本身維護,適用於所有的資料庫,不適合多進程並發更新資料庫,適合單一進程訪問資料庫。不能用於群集環境。*/
Identity
Identity方式根據底層資料庫,來支持自動增長,不同的資料庫用不同的主鍵增長方式。
Hibernate相關書籍Hibernate相關書籍
特點:與底層資料庫有關,要求資料庫支持Identity,如MySQl中是auto_increment, SQL Server 中是Identity,支持的資料庫有MySql、SQL Server、DB2、Sybase和HypersonicSQL。 Identity無需Hibernate和用戶的干涉,使用較為方便,但不便於在不同的資料庫之間移植程式。
Sequence
Sequence需要底層資料庫支持Sequence方式,例如Oracle資料庫
特點:需要底層資料庫的支持序列,支持序列的資料庫有DB2、PostgreSql、Oracle、SAPDb等在不同資料庫之間移植程式,特別從支持序列的資料庫移植到不支持序列的資料庫需要修改配置檔案
Native
Native主鍵生成方式會根據不同的底層資料庫自動選擇Identity、Sequence、Hilo主鍵生成方式
特點:根據不同的底層資料庫採用不同的主鍵生成方式。由於Hibernate會根據底層資料庫採用不同的映射方式,因此便於程式移植,項目中如果用到多個資料庫時,可以使用這種方式。
UUID
UUID使用128位UUID算法生成主鍵,能夠保證網路環境下的主鍵唯一性,也就能夠保證在不同資料庫及不同伺服器下主鍵的唯一性。
特點:能夠保證資料庫中的主鍵唯一性,生成的主鍵占用比較多的存貯空間
Foreign GUID
Foreign用於一對一關係中。GUID主鍵生成方式使用了一種特殊算法,保證生成主鍵的唯一性,支持SQL Server和MySQL

包的作用

net.sf.hibernate.*
該包的類基本上都是接口類和異常類
net.sf.hibernate.cache.*
JCS的實現類
net.sf.hibernate.cfg.*
配置檔案讀取類
net.sf.hibernate.collection.*
Hibernate集合接口實現類,例如List,Set,Bag等等,Hibernate之所以要自行編寫集合接口實現類是為了支持lazy loading
net.sf.hibernate.connection.*
幾個資料庫連線池的Provider
net.sf.hibernate.dialect.*
支持多種資料庫特性,每個Dialect實現類代表一種資料庫,描述了該資料庫支持的數據類型和其它特點,例如是否有AutoIncrement,是否有Sequence,是否有分頁sql等等
net.sf.hibernate. eg.*
Hibernate文檔中用到的例子
net.sf.hibernate.engine.*
這個包的類作用比較散
net.sf.hibernate.expression.*
HQL支持的表達式
net.sf.hibernate.hq.*
HQL實現
net.sf.hibernate. id.*
ID生成器
net.sf.hibernate.impl.*
最核心的包,一些重要接口的實現類,如Session,SessionFactory,Query等
net.sf.hibernate.jca.*
JCA支持,把Session包裝為支持JCA的接口實現類
net.sf.hibernate.jmx.*
JMX是用來編寫App Server的管理程式的,大概是JMX部分接口的實現,使得App Server可以通過JMX接口管理Hibernate
net.sf.hibernate.loader.*
也是很核心的包,主要是生成sql語句
net.sf.hibernate.lob.*
Blob和Clob支持
net.sf.hibernate.mapping.*
hbm檔案的屬性實現
net.sf.hibernate.metadata.*
PO的Meta實現
net.sf.hibernate.odmg.*
ODMG是一個ORM標準,這個包是ODMG標準的實現類
net.sf.hibernate.persister.*
核心包,實現持久對象和表之間的映射
net.sf.hibernate.proxy.*
Proxy和Lazy Loading支持
net.sf.hibernate. ps.*
該包是PreparedStatment Cache
net.sf.hibernate.sql.*
生成JDBC sql語句的包
net.sf.hibernate.test.*
測試類,你可以用junit來測試Hibernate
net.sf.hibernate.tool.hbm2ddl.*
用hbm配置檔案生成DDL
net.sf.hibernate.transaction.*
Hibernate Transaction實現類
net.sf.hibernate.type.*
Hibernate中定義的持久對象的屬性的數據類型
net.sf.hibernate.util.*
一些工具類,作用比較散
net.sf.hibernate.xml.*
XML數據綁定

快取管理

Hibernate 中提供了兩級Cache(高速緩衝存儲器),第一級別的快取是Session級別的快取,它是屬於事務範圍的快取。這一級別的快取由hibernate管理的,一般情況下無需進行干預;第二級別的快取是SessionFactory級別的快取,它是屬於進程範圍或集群範圍的快取。這一級別的快取可以進行配置和更改,並且可以動態載入和卸載。 Hibernate還為查詢結果提供了一個查詢快取,它依賴於第二級快取。
第一級快取 第二級快取 存放數據的形式 相互關聯的持久化對象的散裝數據 快取的範圍
事務範圍,每個事務都有單獨的第一級快取進程範圍或集群範圍,快取被同一個進程或集群範圍內的所有事務共享 並發訪問策略由於每個事務都擁有單獨的第一級快取,不會出現並發問題,無需提供並發訪問策略由於多個事務會同時訪問第二級快取中相同數據,因此必須提供適當的並發訪問策略,來保證特定的事務隔離級別數據過期策略沒有提供數據過期策略。處於一級快取中的對象永遠不會過期,除非應用程式顯式清空快取或者清除特定的對象必須提供數據過期策略,如基於記憶體的快取中的對象的最大數目,允許對象處於快取中的最長時間,以及允許對象處於快取中的最長空閒時間。
物理存儲介質記憶體和硬碟 對象的散裝數據首先存放在基於記憶體的快取中,當記憶體中對象的數目達到數據過期策略中指定上限時,就會把其餘的對象寫入基於硬碟的快取中。
快取的軟體實現 在Hibernate的Session的實現中包含了快取的實現由第三方提供,Hibernate僅提供了快取適配器(CacheProvider)。用於把特定的快取外掛程式集成到Hibernate中。啟用快取的方式只要應用程式通過Session接口來執行保存、更新、刪除、載入和查詢資料庫數據的操作,Hibernate就會啟用第一級快取,把資料庫中的數據以對象的形式拷貝到快取中,對於批量更新和批量刪除操作,如果不希望啟用第一級快取,可以繞過Hibernate API,直接通過JDBC API來執行指操作。用戶可以在單個類或類的單個集合的粒度上配置第二級快取。如果類的實例被經常讀但很少被修改,就可以考慮使用第二級快取。只有為某個類或集合配置了第二級快取,Hibernate在運行時才會把它的實例加入到第二級快取中。 用戶管理快取的方式第一級快取的物理介質為記憶體,由於記憶體容量有限,必須通過恰當的檢索策略和檢索方式來限制載入對象的數目。Session的evict()方法可以顯式清空快取中特定對象,但這種方法不值得推薦。 第二級快取的物理介質可以是記憶體和硬碟,因此第二級快取可以存放大量的數據,數據過期策略的maxElementsInMemory屬性值可以控制記憶體中的對象數目。管理第二級快取主要包括兩個方面:選擇需要使用第二級快取的持久類,設定合適的並發訪問策略:選擇快取適配器,設定合適的數據過期策略。

一級快取

當應用程式調用Session的save()、update()、saveOrUpdate()、get()或load(),以及調用查詢接口的 list()、iterate()或filter()方法時,如果在Session快取中還不存在相應的對象,Hibernate就會把該對象加入到第一級快取中。當清理快取時,Hibernate會根據快取中對象的狀態變化來同步更新資料庫。 Session為應用程式提供了兩個管理快取的方法: evict(Object obj):從快取中清除參數指定的持久化對象。 clear():清空快取中所有持久化對象。

二級快取

3.1. Hibernate的二級快取策略的一般過程如下:
1) 條件查詢的時候,總是發出一條select * from table_name where …. (選擇所有欄位)這樣的SQL語句查詢資料庫,一次獲得所有的數據對象
2) 把獲得的所有數據對象根據ID放入到第二級快取中。
3) 當Hibernate根據ID訪問數據對象的時候,首先從Session一級快取中查;查不到,如果配置了二級快取,那么從二級快取中查;查不到,再查詢資料庫,把結果按照ID放入到快取。
4) 刪除、更新、增加數據的時候,同時更新快取。
Hibernate的二級快取策略,是針對於ID查詢的快取策略,對於條件查詢則毫無作用。為此,Hibernate提供了針對條件查詢的Query Cache。
3.2. 什麼樣的數據適合存放到第二級快取中? 1 很少被修改的數據 2 不是很重要的數據,允許出現偶爾並發的數據 3 不會被並發訪問的數據 4 參考數據,指的是供套用參考的常量數據,它的實例數目有限,它的實例會被許多其他類的實例引用,實例極少或者從來不會被修改。
3.3. 不適合存放到第二級快取的數據? 1 經常被修改的數據 2 財務數據,絕對不允許出現並發 3 與其他套用共享的數據。
3.4. 常用的快取外掛程式 Hibernater 的二級快取是一個外掛程式,下面是幾種常用的快取外掛程式:
l EhCache:可作為進程範圍的快取,存放數據的物理介質可以是記憶體或硬碟,對Hibernate的查詢快取提供了支持。
l OSCache:可作為進程範圍的快取,存放數據的物理介質可以是記憶體或硬碟,提供了豐富的快取數據過期策略,對Hibernate的查詢快取提供了支持。
l SwarmCache:可作為群集範圍內的快取,但不支持Hibernate的查詢快取。
l JBossCache:可作為群集範圍內的快取,支持事務型並發訪問策略,對Hibernate的查詢快取提供了支持。
上述4種快取外掛程式的對比情況列於表9-3中。
表9-3 4種快取外掛程式的對比情況
緩 存 插 件
支 持 只 讀
支持非嚴格讀寫
支 持 讀 寫
支 持 事 務
EhCache
OSCache
SwarmCache
JBossCache
它們的提供器列於表9-4中。
表9-4 快取策略的提供器
緩 存 插 件
提供器(Cache Providers)
Hashtable(只能測試時使用)
org.hibernate.cache.HashtableCacheProvider
EhCache
org.hibernate.cache.EhCacheProvider
OSCache
org.hibernate.cache.OSCacheProvider
在默認情況下,Hibernate使用EhCache進行JVM級別的快取。用戶可以通過設定Hibernate配置檔案中的hibernate.cache.provider_class的屬性,指定其他的快取策略,該快取策略必須實現org.hibernate.cache.CacheProvider接口。
3.5. 配置二級快取的主要步驟:
1) 選擇需要使用二級快取的持久化類,設定它的命名快取的並發訪問策略。這是最值得認真考慮的步驟。
2) 選擇合適的快取外掛程式,然後編輯該外掛程式的配置檔案。

延遲載入

延遲載入
Hibernate對象關係映射提供延遲的與非延遲的對象初始化。非延遲載入在讀取一個對象的時候會將與這個對象所有相關的其他對象一起讀取出來。這有時會導致成百的(如果不是成千的話)select語句在讀取對象的時候執行。這個問題有時出現在使用雙向關係的時候,經常會導致整個資料庫都在初始化的階段被讀出來了。當然,你可以不厭其煩地檢查每一個對象與其他對象的關係,並把那些最昂貴的刪除,但是到最後,我們可能會因此失去了本想在ORM工具中獲得的便利。
一個明顯的解決方法是使用Hibernate提供的延遲載入機制。這種初始化策略只在一個對象調用它的一對多或多對多關係時才將關係對象讀取出來。這個過程對開發者來說是透明的,而且只進行了很少的資料庫操作請求,因此會得到比較明顯的性能提升。這項技術的一個缺陷是延遲載入技術要求一個Hibernate會話要在對象使用的時候一直開著。這會成為通過使用DAO模式將持久層抽象出來時的一個主要問題。為了將持久化機制完全地抽象出來,所有的資料庫邏輯,包括打開或關閉會話,都不能在套用層出現。最常見的是,一些實現了簡單接口的DAO實現類將資料庫邏輯完全封裝起來了。一種快速但是笨拙的解決方法是放棄DAO模式,將資料庫連線邏輯加到套用層中來。這可能對一些小的應用程式有效,但是在大的系統中,這是一個嚴重的設計缺陷,妨礙了系統的可擴展性。
Web層延遲載入
幸運的是,Spring框架為Hibernate延遲載入與DAO模式的整合提供了一種方便的解決方法。以一個Web套用為例,Spring提供了OpenSessionInViewFilter和OpenSessionInViewInterceptor。我們可以隨意選擇一個類來實現相同的功能。兩種方法唯一的不同就在於interceptor在Spring容器中運行並被配置在web套用的上下文中,而Filter在Spring之前運行並被配置在web.xml中。不管用哪個,他們都在請求將當前會話與當前(資料庫)執行緒綁定時打開Hibernate會話。一旦已綁定到執行緒,這個打開了的Hibernate會話可以在DAO實現類中透明地使用。這個會話會為延遲載入資料庫中值對象的視圖保持打開狀態。一旦這個邏輯視圖完成了,Hibernate會話會在Filter的doFilter方法或者Interceptor的postHandle方法中被關閉。
實現方法在web.xml中加入
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>

性能最佳化

初用HIBERNATE的人也許都遇到過性能問題,實現同一功能,用HIBERNATE與用JDBC性能相差十幾倍很正常,如果不及早調整,很可能影響整個項目的進度。 大體上,對於HIBERNATE性能調優的主要考慮點如下:
.資料庫設計調整
.HQL最佳化
.API的正確使用(如根據不同的業務類型選用不同的集合及查詢API)
.主配置參數(日誌,查詢快取,fetch_size, batch_size等)
.映射檔案最佳化(ID生成策略,二級快取,延遲載入,關聯最佳化)
.一級快取的管理
.針對二級快取,還有許多特有的策略
.事務控制策略。

資料庫設計

a) 降低關聯的複雜性
b) 儘量不使用聯合主鍵
c) ID的生成機制,不同的資料庫所提供的機制並不完全一樣
d) 適當的冗餘數據,不過分追求高範式

HQL最佳化

HQL如果拋開它同HIBERNATE本身一些快取機制的關聯,HQL的最佳化技巧同普通的SQL最佳化技巧一樣,可以很容易在網上找到一些經驗之談。

主配置

a) 查詢快取,同下面講的快取不太一樣,它是針對HQL語句的快取,即完全一樣的語句再次執行時可以利用快取數據。但是,查詢快取在一個交易系統(數據變更頻繁,查詢條件相同的機率並不大)中可能會起反作用:它會白白耗費大量的系統資源但卻難以派上用場。
b) fetch_size,同JDBC的相關參數作用類似,參數並不是越大越好,而應根據業務特徵去設定
c) batch_size同上。
d) 生產系統中,切記要關掉SQL語句列印。

快取

a) 資料庫級快取:這級快取是最高效和安全的,但不同的資料庫可管理的層次並不一樣,比如,在Oracle中,可以在建表時指定將整個表置於快取當中。
b) SESSION快取:在一個HibernateSESSION有效,這級快取的可干預性不強,大多於HIBERNATE自動管理,但它提供清除快取的方法,這在大批量增加/更新操作是有效的。比如,同時增加十萬條記錄,按常規方式進行,很可能會發現OutofMemeroy的異常,這時可能需要手動清除這一級快取:Session.evict以及 Session.clear
c) 套用快取:在一個SESSIONFACTORY中有效,因此也是最佳化的重中之重,因此,各類策略也考慮的較多,在將數據放入這一級快取之前,需要考慮一些前提條件:
i. 數據不會被第三方修改(比如,是否有另一個套用也在修改這些數據?)
ii. 數據不會太大
iii. 數據不會頻繁更新(否則使用CACHE可能適得其反)
iv. 數據會被頻繁查詢
v. 數據不是關鍵數據(如涉及錢,安全等方面的問題)。
快取有幾種形式,可以在映射檔案中配置:read-only(唯讀,適用於很少變更的靜態數據/歷史數據),nonstrict-read- write,read-write(比較普遍的形式,效率一般),transactional(JTA中,且支持的快取產品較少)
d) 分散式快取:同c)的配置一樣,只是快取產品的選用不同,oscache, jboss cache,的大多數項目,對它們的用於集群的使用(特別是關鍵交易系統)都持保守態度。在集群環境中,只利用資料庫級的快取是最安全的。

延遲載入

a) 實體延遲載入:通過使用動態代理實現
b) 集合延遲載入:通過實現自有的SET/LIST,HIBERNATE提供了這方面的支持
c) 屬性延遲載入:

方法選用

a) 完成同樣一件事,Hibernate提供了可供選擇的一些方式,使用不同的編碼方式對性能有不同的影響。比如:一次返回十萬條記錄,如果用 (List/Set/Bag/Map等)進行處理,很可能導致記憶體不夠的問題,而如果用基於游標(ScrollableResults)或 Iterator的結果集,則不存在這樣的問題。
b) Session的load/get方法,前者會使用二級快取,而後者則不使用。
c) Query和list/iterator,如果去仔細研究一下它們,你可能會發現很多有意思的情況,二者主要區別(如果使用了Spring,在HibernateTemplate中對應find,iterator方法):
i. list只能利用查詢快取(但在交易系統中查詢快取作用不大),無法利用二級快取中的單個實體,但list查出的對象會寫入二級快取,但它一般只生成較少的執行SQL語句,很多情況就是一條(無關聯)。
ii. iterator則可以利用二級快取,對於一條查詢語句,它會先從資料庫中找出所有符合條件的記錄的ID,再通過ID去快取找,對於快取中沒有的記錄,再構造語句從資料庫中查出,因此很容易知道,如果快取中沒有任何符合條件的記錄,使用iterator會產生N+1條SQL語句(N為符合條件的記錄數)
iii. 通過iterator,配合快取管理API,在海量數據查詢中可以很好的解決記憶體問題,如:
while(it.hasNext()){
YouObject object = (YouObject)it.next();
session.evict(youObject);
sessionFactory.evice(YouObject.class, youObject.getId());
}
如果用list方法,很可能就出OutofMemory錯誤了。

集合的選用

在Hibernate3.1文檔的“19.5. Understanding Collection performance”中有詳細的說明。

事務控制

事務方面對性能有影響的主要包括:事務方式的選用,事務隔離級別以及鎖的選用
a) 事務方式選用:如果不涉及多個事務管理器事務的話,不需要使用JTA,只有
JDBC的事務控制就可以。
b) 事務隔離級別:參見標準的SQL事務隔離級別
c) 鎖的選用:悲觀鎖(一般由具體的事務管理器實現),對於長事務效率低,但安全。樂觀鎖(一般在套用級別實現),如在HIBERNATE中可以定義 VERSION欄位,顯然,如果有多個套用運算元據,且這些套用不是用同一種樂觀鎖機制,則樂觀鎖會失效。因此,針對不同的數據應有不同的策略,同前面許多情況一樣,很多時候我們是在效率與安全/準確性上找一個平衡點,無論如何,最佳化都不是一個純技術的問題,你應該對你的套用和業務特徵有足夠的了解。

批量操作

即使是使用JDBC,在進行大批數據更新時,BATCH與不使用BATCH有效率上也有很大的差別。可以通過設定batch_size來讓其支持批量操作。
舉個例子,要批量刪除某表中的對象,如“delete Account”,打出來的語句,HIBERNATE找出了所有ACCOUNT的ID,再進行刪除,這主要是為了維護二級快取,這樣效率肯定高不了,在後續的版本中增加了bulk delete/update,但這也無法解決快取的維護問題。也就是說,由於有了二級快取的維護問題,HIBERNATE的批量操作效率並不盡如人意。
hibernate工作原理:
1、通過Configuration().configure();讀取並解析hibernate.cfg.xml配置檔案
2、由hibernate.cfg.xml中的<mappingresource="com/xx/User.hbm.xml"/>讀取解析映射信息。
3、通過config.buildSessionFactory();//得到sessionFactory。
4、sessionFactory.openSession();//得到session。
5、session.beginTransaction();//開啟事務。
6、persistent operate;
7、session.getTransaction().commit();//提交事務
8、關閉session;
9、關閉sessionFactory;
hibernate優點:
1、封裝了jdbc,簡化了很多重複性代碼。
2、簡化了DAO層編碼工作,使開發更對象化了。
3、移植性好,支持各種資料庫,如果換個資料庫只要在配置檔案中變換配置就可以了,不用改變hibernate代碼。
4、支持透明持久化,因為hibernate操作的是純粹的(pojo)java類,沒有實現任何接口,沒有侵入性。所以說它是一個輕量級框架。
hibernate延遲載入
get不支持延遲載入,load支持延遲載入。
1、hibernate2對 實體對象和集合 實現了延遲載入
2、hibernate3對 提供了屬性的延遲載入功能
hibernate延遲載入就是當使用session.load(User.class,1)或者session.createQuery()查詢對象或者屬性的時候
這個對象或者屬性並沒有在記憶體中,只有當程式運算元據的時候,才會存在記憶體中,這樣就實現延遲載入,節省了記憶體的開銷,從而提高了伺服器的性能。
Hibernate的快取機制
一級快取:session級的快取也叫事務級的快取,只快取實體,生命周期和session一致。不能對其進行管理。
不用顯式的調用。
二級快取:sessionFactory快取,也叫進程級的快取,使用第3方外掛程式實現的,也只快取實體,生命周期和sessionFactory一致,可以進行管理。
首先配置第3方外掛程式,我們用的是EHCache,在hibernate.cfg.xml檔案中加入
<propertyname="hibernate.cache.user_second_level_cache">true</property>
在映射中也要顯式的調用,<cacheusage="read-only"/>
二級快取之查詢快取:對普通屬性進行快取。如果關聯的表發生了修改,那么查詢快取的生命周期也結束了。
在程式中必須手動啟用查詢快取:query.setCacheable(true);
最佳化Hibernate
1、使用一對多的雙向關聯,儘量從多的一端維護。
2、不要使用一對一,儘量使用多對一。
3、配置對象快取,不要使用集合快取。
4、表欄位要少,表關聯不要怕多,有二級快取撐腰。
hibernate 類與類之間關係
關聯關係
聚集關係
繼承關係
Hibernate繼承關係映射策略分為三種:一張表對應一整棵類繼承樹、一個類對應一張表、每一個具體類對應一張表。

相關詞條

熱門詞條

聯絡我們