Hibernate 框架檢索策略

查詢數據需要考慮的兩個問題

  • 不浪費內存:當 Hibernate 從數據庫中加載 Customer 對象時, 如果同時加載所有關聯的 Order 對象, 而程序實際上僅僅需要訪問 Customer 對象, 那麼這些關聯的 Order 對象就白白浪費了許多內存.
  • 更高的查詢效率:發送儘可能少的 SQL 語句

類級別的檢索策略

類級別可選的檢索策略包括立即檢索(立即加載檢索方法指定的對象)和延遲檢索(延遲加載檢索方法指定的對象。在使用具體的屬性時,再進行加載), 默認爲延遲檢索
類級別的檢索策略可以通過 <class> 元素的 lazy 屬性進行設置
如果程序加載一個對象的目的是爲了訪問它的屬性, 可以採取立即檢索.
如果程序加載一個持久化對象的目的是僅僅爲了獲得它的引用, 可以採用延遲檢索。注意出現懶加載異常!
無論 <class> 元素的 lazy 屬性是 true 還是 false, Session 的 get() 方法及 Query 的 list() 方法在類級別總是使用立即檢索策略
若 <class>元素的 lazy 屬性爲 true 或取默認值, Session 的 load() 方法不會執行查詢數據表的 SELECT 語句, 僅返回代理類對象的實例, 該代理類實例有如下特徵:

  • 由 Hibernate 在運行時採用 CGLIB 工具動態生成
  • Hibernate 創建代理類實例時, 僅初始化其 OID 屬性
  • 在應用程序第一次訪問代理類實例的非 OID 屬性時, Hibernate 會初始化代理類實例

一對多和多對多的檢索策略

在映射文件中, 用 <set> 元素來配置一對多關聯及多對多關聯關係. <set> 元素有 lazy 和 fetch 屬性
lazy: 主要決定 orders 集合被初始化的時機. 即到底是在加載 Customer 對象時就被初始化, 還是在程序訪問 orders 集合時被初始化
fetch: 取值爲 “select” 或 “subselect” 時, 決定初始化 orders 的查詢語句的形式; 若取值爲”join”, 則決定 orders 集合被初始化的時機
若把 fetch 設置爲 “join”, lazy 屬性將被忽略
<set> 元素的 batch-size 屬性:用來爲延遲檢索策略或立即檢索策略設定批量檢索的數量. 批量檢索能減少 SELECT 語句的數目, 提高延遲檢索或立即檢索的運行性能.

<set> 元素的 lazy 和 fetch 屬性

這裏寫圖片描述

延遲檢索和增強延遲檢索

在延遲檢索(lazy 屬性值爲 true) 集合屬性時, Hibernate 在以下情況下初始化集合代理類實例

  • 應用程序第一次訪問集合屬性: iterator(), size(), isEmpty(), contains() 等方法
  • 通過 Hibernate.initialize() 靜態方法顯式初始化

增強延遲檢索(lazy 屬性爲 extra): 與 lazy=“true” 類似. 主要區別是增強延遲檢索策略能進一步延遲 Customer 對象的 orders 集合代理實例的初始化時機:

  • 當程序第一次訪問 orders 屬性的 iterator() 方法時, 會導致 orders 集合代理類實例的初始化
  • 當程序第一次訪問 order 屬性的 size(), contains() 和 isEmpty() 方法時, Hibernate 不會初始化 orders 集合類的實例, 僅通過特定的 select 語句查詢必要的信息, 不會檢索所有的 Order 對象

<set> 元素的 batch-size 屬性

<set> 元素有一個 batch-size 屬性, 用來爲延遲檢索策略或立即檢索策略設定批量檢索的數量. 批量檢索能減少 SELECT 語句的數目, 提高延遲檢索或立即檢索的運行性能. (如果lazy設置爲extra,此屬性被忽略)

<set> 元素的 fetch 屬性:

取值爲 “select” 或 “subselect” 時, 決定初始化 orders 的查詢語句的形式; 若取值爲”join”, 則決定 orders 集合被初始化的時機,lazy 屬性將被忽略.默認值爲 select
當 fetch 屬性爲 “subselect” 時

  • 假定 Session 緩存中有 n 個 orders 集合代理類實例沒有被初始化, Hibernate 能夠通過帶子查詢的 select 語句, 來批量初始化 n 個 orders 集合代理類實例
  • batch-size 屬性將被忽略
  • 子查詢中的 select 語句爲查詢 CUSTOMERS 表 OID 的 SELECT 語句
  • 當 fetch 屬性爲 “join” 時:

檢索 Customer 對象時, 會採用迫切左外連接(通過左外連接加載與檢索指定的對象關聯的對象)策略來檢索所有關聯的 Order 對象

  • lazy 屬性將被忽略
  • Query 的list() 方法會忽略映射文件中配置的迫切左外連接檢索策略, 而依舊採用延遲加載策略

多對一和一對一關聯的檢索策略

和 <set> 一樣, <many-to-one> 元素也有一個 lazy 屬性和 fetch 屬性.
這裏寫圖片描述

  • 若 fetch 屬性設爲 join, 那麼 lazy 屬性被忽略
  • 迫切左外連接檢索策略的優點在於比立即檢索策略使用的 SELECT 語句更少.
  • 無代理延遲檢索需要增強持久化類的字節碼才能實現

類級別和關聯級別可選的檢索策略及默認的檢索策略

這裏寫圖片描述

3 種檢索策略的運行機制

這裏寫圖片描述

映射文件中用於設定檢索策略的幾個屬性

這裏寫圖片描述

比較 Hibernate 的三種檢索策略

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章