1. 程式人生 > >Hibernate(八):檢索策略

Hibernate(八):檢索策略

  Hibernate的Session在載入一個Java物件時,可以將與這個物件相關聯的其他物件都載入到快取中,以便程式及時呼叫。但在一些情況下,不需要載入太多沒有用的物件到快取中去,這會增加快取的負荷和訪問資料庫的次數,所以為了合理的利用快取。Hibernate提供了幾種檢索策略

作用域

   1.檢索策略的作用域分為: 類級別和關聯級別。

  • 類級別的作用域在檢索資料時,檢索的物件只包含一個數據,不涉及與該類有關的其他物件
  • 關聯級別的作用域檢索的資料包含相關聯的多個類的物件。例如:Customer物件與Order物件存在關聯關係,檢索一個Customer物件,還會涉及到與之關聯的Order物件

   2. 作用域對比:

檢索策略的作用域 可選的檢索策略 預設的檢索策略 執行時行為受影響的檢索方法
類級別 立即檢索
延遲檢索
延遲檢索 僅影響Session的load()方法
關聯級別 立即檢索
延遲檢索
迫切左外連線檢索
 
延遲檢索 影響Session的load()和get()方法,以及Query的API會忽略
對映檔案中設定的迫切左外連線檢索策略

Hibernate的檢索策略

      檢索策略分為三種:立即檢索,延遲檢索,左外連線檢索

   1.立即檢索

  (1)  採用立即檢索策略,會把被檢索的物件,以及和這個物件關聯額一對多物件都載入到快取中。Session的get()方法就是採用的立即檢索的策略

  (2) 無論 <class> 元素的 lazy 屬性是 true 還是 false, Session 的 get() 方法及 Query 的 list() 方法在類級別總是使用立即檢索策略

    若 <class> 元素的 lazy 屬性為 true 或取預設值, Session 的 load() 方法不會執行查詢資料表的 SELECT 語句, 僅返回代理類物件的例項, 該代理類例項有如下特徵:

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

  (3)優點:頻繁使用的物件會被載入到快取中,程式呼叫方便,很及時

           缺點:佔用的記憶體過多 ,而且資料庫訪問次數也會很頻繁,效率低下

   2.延遲檢索

 (1)採用延遲檢索策略,就不會載入關聯物件的內容。直到第一次呼叫關聯物件時,才會載入關聯物件。在不涉及關聯類操作時,延遲檢索策略只使用於Session的load()方法。涉及關聯類操作時,延遲檢索策略也能夠適用於get,list等操作

 (2)類級別操作:只加載類的OID不載入類的其他屬性,只用當第一次訪問其他屬性時,才會回訪資料庫去載入內容。

         關聯級別操作:只加載類本事,不載入關聯類。直到第一次呼叫關聯物件,才去載入關聯物件。

(3) 如果需要指定延遲載入策略,需要在配置檔案設定<class>的lazy=true,<set>的lazy=true或extra(增強延遲),<many-to-one>的lazy=proxy和no-proxy

(4)延遲檢索和增強延遲檢索

         ->在延遲檢索(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 物件

(5)優點:由程式決定載入哪些類和內容,而不必全部載入,避免記憶體的大量佔用和資料庫的頻繁訪問

         缺點:在Session關閉後,就不能訪問關聯類物件。需要確保Session一直處於開啟開啟狀態,呼叫關聯物件之後關閉Session物件

  3.左外連線檢索

  (1)採用左外連線檢索,能夠使用SQL的外連線查詢,將需要載入的關聯物件載入在快取中

  (2)<set>fetch設定為join,<many-to-one>fetch設定為join

 (3)  優點:對應用程式完全透明,不管物件處於持久化狀態,還是遊離狀態,應用程式都可以方便的從一個物件導航到與它關聯的物件。使用了外連線,select語句數目減少

           缺點:可能會載入應用程式不需要訪問的物件,會浪費許多記憶體空間。複雜的資料庫表連線也會檢索效能。

 4.三種檢索的執行機制

   

5.比較三種檢索策略


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

1.在對映檔案中, 用 <set> 元素來配置檢索策略. <set> 元素屬性:

(1)lazy: 主要決定 orders 集合被初始化的時機. 即到底是在載入 Customer 物件時就被初始化, 還是在程式訪問 orders 集合時被初始化

 (2)fetch: 取值為 “select” 或 “subselect” 時, 決定初始化 orders 的查詢語句的形式;  若取值為”join”, 則決定 orders 集合被初始化的時機(若把 fetch 設定為 “join”, lazy 屬性將被忽略)

     -> 當fetch屬性為“subselect”時:

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

 (3)lazy屬性和fetch屬性的使用:

(4) batch-size 屬性:用來為延遲檢索策略或立即檢索策略設定批量檢索的數量. 批量檢索能減少 SELECT 語句的數目, 提高延遲檢索或立即檢索的執行效能. 

2.<many-to-one>元素的屬性配置檢索策略:

(1)lazy屬性和fetch屬性的使用:


 若fetch屬性為“join”,那麼lazy屬性將被忽略

3.總結-對映檔案中用於設定檢索策略的幾個屬性