類級別的檢索策略
類級別可選的檢索策略包括立即檢索和延遲檢索,默認爲延遲檢索
- 立即檢索:立即加載檢索方法指定的對象
- 延遲檢索:延遲加載檢索方法指定的對象,在使用具體的屬性時,再進行加載
類級別的檢索策略可以通過<class>
元素的lazy
屬性進行設置
-
lazy
爲true
時,就是延遲檢索。 -
lazy
爲false
時,就是立即檢索。
如果程序加載一個對象的目的是爲了訪問它的屬性,可以採取立即檢索。如果程序加載一個持久化對象的目的是僅僅爲了獲得它的引用,可以採取延遲檢索,在使用延遲檢索時,要防止懶加載異常。
無論<class>
的元素的lazy
屬性是true
還是false
,Session的get()
及Query的list()
在類級別總是使用立即檢索策略。
若<class>
元素的lazy
屬性爲true
或取默認值,Session的load()
不會執行查詢數據表的SELECT語句,僅返回代理類對象的實例,該代理類實例有如下特徵:
- 由Hibernate在運行時採用CGLIB工具動態生成
- Hibernate創建代理類實例時,僅初始化其OID屬性
- 在應用程序第一次訪問代理類實例的非OID屬性時,Hibernate會初始化代理類實例。
延遲檢索和增強延遲檢索
在延遲檢索(lazy
屬性爲true
)集合屬性時,Hibernate在以下情況下初始化集合代理類實例
- 應用程序第一次訪問集合屬性:
iterator()
,size()
,isEmpty()
,contains()
等方法 - 通過
Hibernate.initialize()
靜態方法顯示初始化
增強延遲檢索(lazy
屬性爲extra
)時,與延遲檢索類似,主要區別是增強延遲檢索策略能進一步延遲實體類對象的集合代理實例的初始化時機。
- 當程序第一次訪問集合屬性的
iterator()
時,會導致集合代理類實例的初始化 - 當程序第一次訪問集合屬性的
size()
,contains()
,isEmpty()
時,Hibernate不會初始化集合類的實例,僅通過特定的SELECT語句查詢必要的信息,不會檢索所有的集合對象。
一對多和多對多的檢索策略
在映射文件中,用<set>
元素來配置一對多關聯及多對多關聯關係,<set>
元素有lazy
和fetch
屬性。
lazy
:主要決定實體類中關聯的集合被初始化的時機。即到底是在加載實體類對象的時候就被初始化呢,還是在程序訪問集合時被初始化。
默認爲true
,即訪問集合時被初始化,可以設置爲false
,即加載實體類對象的時候就初始化。lazy
還可以設置爲extra
,是一個增強版的延遲檢索,會儘可能地延遲集合初始化的時機。<set>
元素的batch-size
屬性
用來爲延遲檢索策略或立即檢索策略設定批量檢索的數量。批量檢索能減少SELECT語句的數目,提高延遲檢索或立即檢索的運行性能。
配置示例:
<!-- 一次性檢索5個集合-->
<set name="orders" table="orders" inverse="true" cascade="delete" batch-size="5">
<key column="customer_id"></key>
<one-to-many class="Order"/>
</set>
-
fetch
:決定初始化集合的方式。
取值爲select
或subselect
時,決定初始化集合的查詢語句的方式,subselect
是子查詢,此時batch-size
屬性將被忽略;若取值爲join
,則決定集合被初始化的時機。在加載一端的實體類對象時,使用迫切左外連接(使用左外連接進行查詢,且把集合屬性進行初始化)的方式檢索n端的集合屬性若把fetch
設置爲join
的話,lazy
屬性將被忽略。若使用HQL查詢,則忽略fetch=join
。
多對一和一對一關聯的檢索策略
和set
一樣,<many-to-one>
元素也有一個lazy
屬性和fetch
屬性
lazy屬性(默認值爲proxy) | fetch屬性(默認值爲select) | 檢索實體對象時對關聯的實體對象使用的檢索策略 |
---|---|---|
proxy | 未顯式設置(默認值爲select) | 採取延遲檢索 |
no-proxy | 未顯式設置(默認值爲select) | 無代理延遲檢索 |
false | 未顯式設置(默認值爲select) | 立即檢索 |
未顯式設置(默認值爲proxy) | join | 迫切左外連接策略 |
若
fetch
屬性設爲join
,那麼lazy
屬性被忽略,並且使用迫切左外連接來初始化n端關聯的1端的屬性迫切左外連接檢索策略的優點在於比立即檢索策略使用的SELECT更少
無代理延遲檢索需要增強持久化類的字節碼才能實現
Query
的list()
會忽略映射文件配置的迫切左外連接檢索策略,而採用延遲檢索策略batch-size
:一次性初始化1端的代理對象的個數。該屬性需要設置在1端的class元素中
示例:<class name="Customer" table="customers" batch-size="5">