1. 簡介
版本:Hibernate3.2
1.1 目的
1.2 范圍
1.3 定義、首字母縮寫詞和縮略語
1.4 參考資料
1.5 概述
2. 緩存策略
2.1 什么是緩存?
即Hibernate將數據臨時存放在內存中,以便加快數據的存取速度。為此,我們可以想象,緩存的實現,就類似于一個Map對象,首先需要一個key,以便定位相應被緩存的數據,而它的value值,便是被緩存的數據。
2.2 一級緩存
即session級別的緩存,隨著session的關閉而消失,load/iterator操作,會從一級緩存中查找數據,如果找不到,再到數據庫里面查找。Query.list操作,如果沒有配置查詢緩存,將直接從數據庫中獲取數據。
2.3 二級緩存
即SessionFactory級別的緩存。默認的情況下是打開的。這是一個全局緩存策略。它可以對對象的數據進行全局緩存。
2.4 查詢緩存
即對查詢的結果集進行緩存處理,以便下次相同條件相同HQL的情況下可以直接從緩存中獲取數據。
3. 二級緩存
3.1.1 如何打開二級緩存?
需要更改hibernate配置文件:
1、 打開二級緩存(默認情況下是打開的)
a)
2、 指定緩存策略提供商
a)
3.1.2 二級緩存是對對象數據的緩存
為了讓hibernate對對象進行緩存,你必須指定需要緩存哪些類的對象,這有兩種方法可以達到這個目的:
1、 在hibernate配置文件中指定,如
2、 在類的映射文件中(即
如果你打開了對對象的緩存,那么,所有對這個對象的查詢操作的結果,都會被緩存起來。Hibernate將使用對象的鍵值作為緩存的key值,對象的數據作為緩存的value值。
打開了對象緩存,只有在對對象進行查詢操作的時候,才會起作用,如createQuery(“from Student”).iterate()
3.1.3 緩存策略
緩存有幾種形式,可以在映射文件中配置:read-only(只讀,適用于很少變更的靜態數據/歷史數據),nonstrict-read-write,read-write(比較普遍的形式,效率一般),transactional(JTA中,且支持的緩存產品較少)
4. 查詢緩存
查詢緩存的作用,是對list操作的查詢結果集進行緩存!
我們使用list操作的時候,如果啟用了查詢緩存,hibernate將根據當前查詢的HQL語句(及其參數值)計算出一個緩存的key值;查詢結果集,將作為緩存的value值(但如果查詢結果集是一個對象結果集的話,其緩存的value值是對象的ID集合,而不是對象集合本身)。
可以在hibernate配置文件中添加:
以便打開查詢緩存。
查詢緩存,對對象查詢,將緩存其ID列表;對普通查詢,將緩存整個數據集合。所以,對于對象查詢,需要配合二級緩存來使用。
在打開了查詢緩存之后,需要注意,調用query.list()操作之前,必須顯式調用query.setCachable(true)來標識某個查詢使用緩存。
5. 關于load、get、iterate和list操作在緩存中的作用
5.1 Load/get
這個方法,用于加載某個對象。如果打開了二級緩存,加載的對象數據將會被緩存。緩存的key是對象的ID,緩存的value是對象的值。
5.2 Iterate
使用iterate進行查詢,分成兩種不同的情況:
1、 使用iterate方法進行對象查詢,如createQuery(“from Student”).iterate(),這個時候,如果打開了二級緩存,其加載的對象集合,將會被緩存。緩存的key為對象的ID值,緩存的value是對象的數據。
2、 使用iterate方法進行其它查詢,如createQuery(“select name,sex from Student”).iterate(),這個時候,不管有沒有打開二級緩存(以及查詢緩存),其查詢的結果集都不會進行緩存。
5.3 List
查詢緩存只對list操作起作用。
使用List進行查詢,也分成兩種情況:
1、 使用list方法進行對象查詢,如createQuery(“from Student”).list(),這個時候,
a) 如果打開了查詢緩存,并使用查詢緩存(query.setCachable(true);),hibernate將對對象的ID列表進行緩存
b) 如果同時打開了這個對象的二級緩存,那么hibernate就會將這個對象的數據加入二級緩存中。
2、 使用list方法進行普通查詢,如createQuery(“select name,sex from Student”).list(),這個時候,
a) 如果打開了查詢緩存,并使用查詢緩存(query.setCachable(true);),hibernate將對查詢的結果集進行緩存
b) 不管有沒有打開二級緩存,二級緩存的任何設置,對這種類型的查詢,不會產生任何影響(因為二級緩存只對對象的數據進行緩存,而不是某些查詢結果集)
5.4 Session如何與二級緩存交互?
Session接口通過CacheMode來定制與二級緩存之間的交互方法:
6. 抓取策略
抓取策略,即如何獲取數據的策略。
下面以下述模型為例:
班級與學生模型,之間是一對多雙向關聯:
<hibernate-mapping> <class name="com.bjsxt.hibernate.one2many.Classes" lazy="false" batch-size="10" table="T_Classes"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <set name="students" inverse="true" lazy="false" cascade="all" > <key column="classesid"/> <one-to-many class="com.bjsxt.hibernate.one2many.Student"/> </set> </class> <class name="com.bjsxt.hibernate.one2many.Student" lazy="false" table="T_Student"> <id name="id"> <generator class="native"/> </id> <property name="name" length="20"/> <property name="sex" length="10" /> <many-to-one lazy="false" name="classes" column="classesid"/> </class> </hibernate-mapping> |
· 連接抓取(Join fetching) - Hibernate通過 在SELECT語句使用OUTER JOIN(外連接)來 獲得對象的關聯實例或者關聯集合。 連接抓取策略可以被定義在
· 如在Student的
· 或在Classes類的
· 查詢抓取(Select fetching) - 另外發送一條 SELECT 語句抓取當前對象的關聯實體或集合。除非你顯式的指定lazy="false"禁止 延遲抓取(lazy fetching),否則只有當你真正訪問關聯關系的時候,才會執行第二條select語句。 這種抓取策略,設置方法為:fetch=”select”;
· 如在set標簽上設置fetch=”select”,下面的查詢:List list = session.createQuery("from Classes cls where id in (1,22)").list();將產生如下結果:
Hibernate: select classes0_.id as id7_, classes0_.name as name7_ from T_Classes classes0_ where classes0_.id in (1 , 22)
Hibernate: select students0_.classesid as classesid1_, students0_.id as id1_, students0_.id as id8_0_, students0_.name as name8_0_, students0_.sex as sex8_0_, students0_.classesid as classesid8_0_ from T_Student students0_ where students0_.classesid=?
Hibernate: select students0_.classesid as classesid1_, students0_.id as id1_, students0_.id as id8_0_, students0_.name as name8_0_, students0_.sex as sex8_0_, students0_.classesid as classesid8_0_ from T_Student students0_ where students0_.classesid=?
可見,總共發出:第一,查詢Classes的數據;第二,因為查詢結果集中有兩個Classes對象,所以針對每個對象,都發出了一個查詢語句以便查詢其students集合的數據。
·
· 子查詢抓取(Subselect fetching) - 另外發送一條SELECT 語句抓取在前面查詢到(或者抓取到)的所有實體對象的關聯集合。除非你顯式的指定lazy="false" 禁止延遲抓取(lazy fetching),否則只有當你真正訪問關聯關系的時候,才會執行第二條select語句。 設置方法是:fetch=”subselect”,它只能被設置在集合映射的屬性上。
· 如在set標簽上設置fetch=”sebselect”,下面的查詢:List list = session.createQuery("from Classes cls where id in (1,22)").list();在list對象中,將包含兩個Classes對象的實例,假設其集合上配置lazy=”false”,我們立刻就能看到hibernate的subselect抓取策略是:
以下是hibernate生成的SQL語句:
Hibernate: select classes0_.id as id7_, classes0_.name as name7_ from T_Classes classes0_ where classes0_.id in (1 , 22)
------君臨天下,舍我其誰------
謝謝