執行個體A引用執行個體B,B如果是代理的話(比如多對一關聯中):如果遍曆A的查詢結果集(假設有10條記錄),在遍曆A的時候,訪問B變數,將會導致n次查詢語句的發出。這個時候,如果在B一端的class上配置batch-size,hibernate將會減少SQL語句的數量。
Hibernate可以充分有效使用批量抓取,也就是說,如果僅一個訪問代理(或集合),那麼hibernate將不載入其他未執行個體化代理。批量抓取是延遲查詢抓取的最佳化方案,你可以在兩種批量抓取方案之間進行選擇:在類層級和集合層級。
類/實體層級的批量抓取很容易理解,假設你在運行時將需要面對下面的問題:你在一個Session中載入了25個Cat執行個體,每個Cat執行個體都擁有一個引用成員owner,其指向Persion,而Persion類是代理,同時lazy=true,如果你必須遍曆整修cats集合,對每個元素調用getOwner()方法,hibernate將會預設的執行25次SELECT查詢,得到其ower的代理對象。這時你可以通過在對應檔的Person屬性,顯式聲明batch-size,改變其行為:
<class name=”Person” batch-size=”10”>...</class>隨之,hibernate將只需要執行三次查詢,分別是10,10,5.
抓取策略(fetching strategy) 是指:當應用程式需要在(Hibernate實體物件圖的)關聯關係間進行導航的時候, Hibernate如何擷取關聯對象的策略。抓取策略可以在O/R映射的中繼資料中聲明,也可以在特定的HQL 或條件查詢(Criteria Query)中重載聲明。
Hibernate3 定義了如下幾種抓取策略: 串連抓取(Join fetching) - Hibernate通過 在SELECT語句使用OUTER JOIN(外串連)來 獲得對象的關聯執行個體或者關聯集合。 查詢抓取(Select fetching) -另外發送一條 SELECT 語句抓取當前對象的關聯實體或集合。除非你顯式的指定lazy="false"禁止 延遲抓取(lazy fetching),否則只有當你真正訪問關聯關係的時候,才會執行第二條select語句。 子查詢抓取(Subselect fetching) - 另外發送一條SELECT 語句抓取在前面查詢到(或者抓取到)的所有實體物件的關聯集合。除非你顯式的指定lazy="false" 禁止延遲抓取(lazy fetching),否則只有當你真正訪問關聯關係的時候,才會執行第二條select語句。 批量抓取(Batch fetching) - 對查詢抓取的最佳化方案, 通過指定一個主鍵或外鍵列表,Hibernate使用單條SELECT語句擷取一批對象執行個體或集合。
Hibernate會區分下列各種情況: Immediate fetching,立即抓取 - 當宿主被載入時,關聯、集合或屬性被立即抓取。 Lazy collection fetching,延遲集合抓取- 直到應用程式對集合進行了一次操作時,集合才被抓取。(對集合而言這是預設行為。) "Extra-lazy" collection fetching,"Extra-lazy"集合抓取 -對集合類中的每個元素而言,都是直到需要時才去訪問資料庫。除非絕對必要,Hibernate不會試圖去把整個集合都抓取到記憶體裡來(適用於非常大的集合)。 Proxy fetching,代理抓取 - 對返回單值的關聯而言,當其某個方法被調用,而非對其關鍵字進行get操作時才抓取。 "No-proxy" fetching,非代理抓取 - 對返回單值的關聯而言,當執行個體變數被訪問的時候進行抓取。與上面的代理抓取相比,這種方法沒有那麼“延遲”得厲害(就算只訪問標識符,也會導致關聯抓取)但是更加透明,因為對應用程式來說,不再看到proxy。這種方法需要在編譯期間進行位元組碼增強操作,因此很少需要用到。 Lazy attribute fetching,屬性消極式載入 - 對屬性或返回單值的關聯而言,當其執行個體變數被訪問的時候進行抓取。需要編譯期位元組碼強化,因此這一方法很少是必要的。
這裡有兩個正交的概念:關聯何時被抓取,以及被如何抓取(會採用什麼樣的SQL語句)。不要混淆它們。我們使用抓取來改善效能。我們使用延遲來定義一些契約,對某特定類的某個脫管的執行個體,知道有哪些資料是可以使用的。
java代碼: 查看 複製到剪貼簿 列印 hibernate抓取策略(單端代理的批量抓取) 保持預設,同fetch="select",如: <many-to-one name="classes" column="classesid" fetch="select"/> fetch="select",另外發送一條select語句抓取當前對象關聯實體或集合 設定fetch="join",如: <many-to-one name="classes" column="classesid" fetch="join"/> fetch="join",hibernate會通過select語句使用外串連來載入其關聯實體或集合 此時lazy會失效 hibernate抓取策略(集合代理的批量抓取) 保持預設,同fetch="select",如: <set name="students" inverse="true" cascade="all" fetch="select"> fetch="select",另外發送一條select語句抓取當前對象關聯實體或集合 hibernate抓取策略(集合代理的批量抓取) 設定fetch="join",如: <set name="students" inverse="true" cascade="all" fetch="join"> fetch="join",hibernate會通過select語句使用外串連來載入其關聯實體或集合