hibernate載入策略

2021-08-26 04:00:04 字數 3673 閱讀 5851

抓取策略(fetching strategies)

抓取策略(fetching strategy)是指:當應用程式使用關聯物件的時候,hibernate如何獲取關聯物件的策略。

抓取策略可以在o/r對映的元資料中宣告,也可以在特定的hql或條件查詢(criteria query)中過載宣告。

在對映文件中定義的抓取策略將會對以下列表條目產生影響:

通過get()或load()方法取得資料。

只有在關聯之間進行導航時,才會隱式的取得資料。

注意:對hql 無效

hibernate3 定義了如下幾種抓取策略:

連線抓取(fetch="join") - hibernate通過 在select語句使用outer join(外連線)來獲得物件的關聯例項或者關聯集合。

查詢抓取(fetch="select") - 另外傳送一條 select 語句抓取當前物件的關聯實體或集合。

除非你顯式的指定lazy="false"禁止延遲抓取(lazy fetching),否則只有當你真正訪問關聯關係的時候,才會執行第二條select語句。

子查詢抓取(fetch="subselect") - 另外傳送一條select 語句抓取在前面查詢到(或者抓取到)的所有實體物件的關聯集合。

除非你顯式的指定lazy="false" 禁止延遲抓取(lazy fetching),否則只有當你真正訪問關聯關係的時候,才會執行第二條select語句。

批量抓取(batch fetching) - 對查詢抓取的優化方案, 通過指定乙個主鍵或外來鍵列表,hibernate使用單條select語句獲取一批物件例項或集合。 default_batch_fetch_size">10

hibernate抓取策略(單端**的批量抓取)

(一)保持預設,同fetch="select",如:

fetch="select",另外傳送一條select語句抓取當前物件關聯實體或集合

(二)設定fetch="join",如:

fetch="join",hibernate會通過select語句使用外連線來載入其關聯實體或集合,此時lazy會失效

hibernate抓取策略(集合**的批量抓取)

query query = session.createquery("from classes where id in(1,2,3)");

listlist = query.list();

for(classes c : list)

}(一)保持預設,同fetch="select",如:

fetch="select",另外傳送一條select語句抓取當前物件關聯實體或集合

(二)設定fetch="join",如:

fetch="join",hibernate會通過select語句使用外連線來載入其關聯實體或集合

此時lazy會失效

(三)設定fetch="subselect",如:

fetch="subselect",另外傳送一條select語句抓取在前面查詢到的所有實體物件的關聯集合

批量抓取

批量抓取是延遲查詢抓取的優化方案,你可以在兩種批量抓取方案之間進行選擇:在類級別和集合級別。

batch-szie可以在類級別的批量載入實體

name="classes" table="t_classes" batch-size="3"> 類上的批量抓取 from student s where id in(1,11,21)

batch-szie可以在集合級別的批量載入實體

name="students" inverse="true" cascade="all" batch-size="5"> 集合上的批量抓取 from classes c where id in(1,2,3)

類/實體級別的批量抓取很容易理解。假設你在執行時將需要面對下面的問題:你在乙個session中載入了25個cat例項,每個cat例項都擁有乙個引用成員owner,其指向person,而person類是**,同時lazy="true"。 如果你必須遍歷整個cats集合,對每個元素呼叫getowner()方法,hibernate將會預設的執行25次select查詢, 得到其owner的**物件。這時,你可以通過在對映檔案的person屬性,顯式宣告batch-size,改變其行為:

...隨之,hibernate將只需要執行三次查詢,分別為10、10、 5。

你也可以在集合級別定義批量抓取。例如,如果每個person都擁有乙個延遲載入的cats集合, 現在,sesssion中載入了10個person物件,遍歷person集合將會引起10次select查詢, 每次查詢都會呼叫getcats()方法。如果你在person的對映定義部分,允許對cats批量抓取, 那麼,hibernate將可以預先抓取整個集合。請看例子:

...如果整個的batch-size是3,那麼hibernate將會分四次執行select查詢, 按照3、3、3、1的大小分別載入資料。

這裡的每次載入的資料量還具體依賴於當前session中未例項化集合的個數。

延遲抓取要注意的問題。在乙個開啟的hibernate session上下文之外呼叫延遲集合會導致一次意外。

比如:

s = sessions.opensession();

transaction tx = s.begintransaction();

user u = (user) s.createquery("from user u where u.name=:username").setstring("username", username).uniqueresult();

map permissions = u.getpermissions();

tx.commit();

s.close();

integer accesslevel = (integer) permissions.get("accounts"); // error!

在session關閉後,permessions集合將是未例項化的、不再可用,因此無法正常載入其狀態。

hibernate對脫管物件不支援延遲例項化. 這裡的修改方法是:將permissions讀取資料的** 移到tx.commit()之前。

通常情況下,我們並不使用對映文件進行抓取策略的定製。更多的是,保持其預設值,然後在特定的事務中,使用hql的左連線抓取(left join fetch) 對其進行過載。這將通知 hibernate在第一次查詢中使用外部關聯(outer join),直接得到其關聯資料。

在條件查詢 api中,應該呼叫 setfetchmode(fetchmode.join)語句。

例如:

user user = (user) session.createcriteria(user.class)

.setfetchmode("permissions", fetchmode.join)

.add( restrictions.ideq(userid) )

.uniqueresult();

截然不同的一種避免n+1次查詢的方法是,使用二級快取

使用子查詢抓取(using subselect fetching)

假若乙個延遲集合或單值**需要抓取,hibernate會使用乙個subselect重新執行原來的查詢,一次性讀入所有的例項。這和批量抓取的實現方法是一樣的,不會有破碎的載入。

關聯(查詢引用實體),批量(類批量抓取,集合批量抓取)

hibernate載入策略

物件的三種狀態 hibernate管理的物件 1.1 臨時狀態 1.2 持久狀態 1.3 游離狀態 1 hibernate通過管理物件來運算元據庫,這裡物件指的是持久態的物件 2 各種狀態的物件是可以相互轉換 一級快取 快照 orm特性 u u u 一級快取又被稱為sesion級別的快取 載入策略 ...

Hibernate載入策略

物件的三種狀態 hibernate管理的物件 1.1 臨時狀態 1.2 持久狀態 1.3 游離狀態 1 hibernate通過管理物件來運算元據庫,這裡物件指的是持久態的物件 2 各種狀態的物件是可以相互轉換 一級快取 快照 orm特性 u u u 載入策略 3.1 立即載入 3.2 延遲載入 物件...

Hibernate載入策略

物件的三種狀態 hibernate管理的物件 1.1 臨時狀態 1.2 持久狀態 1.3 游離狀態 hibernate通過管理物件來運算元據庫,這裡物件指的是持久態的物件。各種狀態的物件是可以相互轉換。2.一級快取 快照 orm特性 transaction transaction session.b...