一款侵、概述
檢索數(shù)據(jù)時(shí)的 2 個(gè)問題:
不浪費(fèi)內(nèi)存:當(dāng) Hibernate 從數(shù)據(jù)庫中加載 Customer 對象時(shí), 如果同時(shí)加載所有關(guān)聯(lián)的 Order 對象, 而程序?qū)嶋H上僅僅需要訪問 Customer 對象, 那么這些關(guān)聯(lián)的 Order 對象就白白浪費(fèi)了許多內(nèi)存.
更高的查詢效率:發(fā)送盡可能少的 SQL 語句
二、類級別的檢索策略
類級別可選的檢索策略包括立即檢索和延遲檢索舰涌,默認(rèn)為延遲檢索
①温技、立即檢索:立即加載檢索方法指定的對象
②茁彭、延遲檢索:延遲加載檢索方法指定的對象国瓮。在使用具體的屬性時(shí),再進(jìn)行加載
類級別的檢索策略可以通過 <class> 元素的 lazy 屬性進(jìn)行設(shè)置
如果程序加載一個(gè)對象的目的是為了訪問它的屬性, 可以采取立即檢索.
如果程序加載一個(gè)持久化對象的目的是僅僅為了獲得它的引用, 可以采用延遲檢索播瞳。注意出現(xiàn)懶加載異常掸刊!
無論<class>元素的 lazy 屬性是 true 還是 false, Session 的 get() 方法及 Query 的 list() 方法在類級別總是使用立即檢索策略
若 <class> 元素的 lazy 屬性為 true 或取默認(rèn)值, Session 的 load() 方法不會(huì)執(zhí)行查詢數(shù)據(jù)表的 SELECT 語句, 僅返回代理類對象的實(shí)例, 該代理類實(shí)例有如下特征:
①、由 Hibernate 在運(yùn)行時(shí)采用 CGLIB 工具動(dòng)態(tài)生成
②赢乓、Hibernate 創(chuàng)建代理類實(shí)例時(shí), 僅初始化其 OID 屬性
③忧侧、在應(yīng)用程序第一次訪問代理類實(shí)例的非 OID 屬性時(shí), Hibernate 會(huì)初始化代理類實(shí)例
三、案例
設(shè)置lazy等于false
把lazy改回true
四牌芋、一對多和多對多的檢索策略
在映射文件中蚓炬,用<set>元素來配置一對多關(guān)聯(lián)及多對多關(guān)聯(lián)關(guān)系。
①躺屁、lazy:主要決定 orders 集合被初始化的時(shí)機(jī)试吁,即到底是在加載 Customer 對象時(shí)就被初始化,還是在程序訪問 orders 集合時(shí)被初始化
②楼咳、fetch:取值為 “select” 或 “subselect” 時(shí)熄捍,決定初始化 orders 的查詢語句的形式, 若取值為”join”母怜,則決定 orders 集合被初始化的時(shí)機(jī)
若把 fetch 設(shè)置為 “join”余耽,lazy 屬性將被忽略
③、batch-size:用來為延遲檢索策略或立即檢索策略設(shè)定批量檢索的數(shù)量苹熏,批量檢索能減少 SELECT 語句的數(shù)目碟贾,提高延遲檢索或立即檢索的運(yùn)行性能。
五轨域、案例
1-n或n-n的集合屬性默認(rèn)使用懶加載檢索策略
可以通過設(shè)置set的lazy屬性來修改默認(rèn)的檢索袱耽,但不建議設(shè)置為false
lazy還可以設(shè)置為extra,增強(qiáng)延遲檢索干发,該取值會(huì)盡可能的延遲集合初始化的時(shí)機(jī)
重寫Orders的hashCode和equals方法
六朱巨、延遲檢索和增強(qiáng)延遲檢索
在延遲檢索(lazy 屬性值為 true) 集合屬性時(shí), Hibernate 在以下情況下初始化集合代理類實(shí)例
①、應(yīng)用程序第一次訪問集合屬性: iterator(), size(), isEmpty(), contains() 等方法
②枉长、通過 Hibernate.initialize() 靜態(tài)方法顯式初始化
增強(qiáng)延遲檢索(lazy 屬性為 extra): 與 lazy=“true” 類似. 主要區(qū)別是增強(qiáng)延遲檢索策略能進(jìn)一步延遲 Customer 對象的 orders 集合代理實(shí)例的初始化時(shí)機(jī):
①冀续、當(dāng)程序第一次訪問 orders 屬性的 iterator() 方法時(shí), 會(huì)導(dǎo)致 orders 集合代理類實(shí)例的初始化
②、當(dāng)程序第一次訪問 order 屬性的 size(), contains() 和 isEmpty() 方法時(shí), Hibernate 不會(huì)初始化 orders 集合類的實(shí)例, 僅通過特定的 select 語句查詢必要的信息, 不會(huì)檢索所有的 Order 對象
七必峰、?<set>元素的 batch-size 屬性
<set>元素有一個(gè) batch-size 屬性洪唐,用來為延遲檢索策略或立即檢索策略設(shè)定批量檢索的數(shù)量,批量檢索能減少 SELECT 語句的數(shù)目吼蚁,提高延遲檢索或立即檢索的運(yùn)行性能凭需。
八、 <set>元素的 fetch 屬性
set集合的fetch屬性:
(1)默認(rèn)值為select肝匆,通過正常的方式來初始化set元素
(2)可以取值為subselect粒蜈,通過子查詢的方式來初始化所有set集合,子查詢作為where子句的in的條件出現(xiàn)术唬,子查詢查詢所有1的一端的ID薪伏,此時(shí)lazy有效。但batch-size失效粗仓。
在加載1的一端的對象時(shí)嫁怀,使用迫切左外連接(使用左外連接,且把集合屬性進(jìn)行初始化)的方式檢索n的一端的集合屬性借浊,忽略lazy屬性
九塘淑、迫切左外連接檢索(fetch 屬性值設(shè)為 “join”)
<set>元素的 fetch 屬性: 取值為 “select” 或 “subselect” 時(shí), 決定初始化 orders 的查詢語句的形式; 若取值為”join”, 則決定 orders 集合被初始化的時(shí)機(jī).默認(rèn)值為 select
當(dāng) fetch 屬性為 “join” 時(shí):
①、檢索 Customer 對象時(shí), 會(huì)采用迫切左外連接(通過左外連接加載與檢索指定的對象關(guān)聯(lián)的對象)策略來檢索所有關(guān)聯(lián)的 Order 對象
②蚂斤、lazy 屬性將被忽略
③存捺、Query 的list() 方法會(huì)忽略映射文件中配置的迫切左外連接檢索策略, 而依舊采用延遲加載策略
十、多對一和一對一關(guān)聯(lián)的檢索策略
和<set>一樣, <many-to-one>元素也有一個(gè) lazy 屬性和 fetch 屬性。
(1)若 fetch 屬性設(shè)為 join, 那么 lazy 屬性被忽略
(2)迫切左外連接檢索策略的優(yōu)點(diǎn)在于比立即檢索策略使用的 SELECT 語句更少.
(3)無代理延遲檢索需要增強(qiáng)持久化類的字節(jié)碼才能實(shí)現(xiàn)
十一捌治、案例
把fetch改為subselect
把lazy取值為proxy和ffalse分別代表對應(yīng)的屬性采用延遲檢索和立即檢索
fetch取值為join岗钩,表示使用迫切左外連接的方式初始化n關(guān)聯(lián)1的一端的屬性
batch-size,該屬性需要設(shè)置在1那一端的class元素中