Hibernate緩衝策略 一
一、hibernate為什麼提供快取?
什麼是快取?
在記憶體裡開闢一塊空間把本來應該存在硬盤裡面的資料,存在這個空間裡面,將來,需要這塊資料的時候直接在記憶體中獲取。這個就可以簡單理解為快取。
Hibernate 是一個持久層框架,經常訪問物理資料庫,為了減低應用程式對物理資料來源的訪問頻次,從而提高應用程式的執行效能。
快取內的資料是對物理資料來源中的資料的複製,應用程式在執行時從快取讀寫資料,在特定的時刻或事件,將同步快取和物理資料來源的資料。
那麼,接下來,讓我們來看看Hibernate的快取原理是什麼。
二、Hibernate 的快取
首先,Hibernate的緩衝分兩個級別:一級快取 和 二級快取。Hibernate一級快取又稱為 Session級別的快取 ; 二級快取又稱為“SessionFactory的快取”。由session ,和SessionFactory 中就可以看出,緩衝的作用範圍不同。看兩者的使用。
1、一級緩衝
Hibernate一級快取又稱為 Session級別的快取 。Session的快取是事務範圍的快取,所以一級緩衝的生命週期和session的生命週期是同步的。Session物件的生命週期通常對應一個數據庫事務或者一個應用事務。在一級快取中,持久化類的每個例項都具有唯一的OID。
在同一個session中,我們兩次使用load來載入同一個物件,來看一級快取:
@Test
publicvoid cache1Test(){
Session s=sessionFactory.openSession();
s.beginTransaction ();
Person person=(Person)s.load(Person.class, 1);
System.out.println(person.getName());
//因為Session存在緩衝,所以第二次查詢直接在session中取
Person person2=(Person)s.load(Person.class, 1);
System.out.println(person2.getName());
s.getTransaction().commit();
}
結果是隻發出一條SQL語句,是第一個查詢的sql語句,第二次查詢直接使用的session緩衝中的資料物件。
這就是一級緩衝,只能用在同一個session中,不能跨session來取值,那要是需要跨session取值,怎麼辦呢?
對了,就是sessionFactory級別的緩衝,就像是sessionFactory管理所有的session一樣,這裡的二級緩衝就跳出來session的小圈子,可以供所有的session來取值。
2、二級快取。
二級快取又稱為“SessionFactory的快取”。是SessionFactory級別的緩衝,由於SessionFactory物件的生命週期和應用程式的整個過程對應,因此Hibernate二級快取是程序範圍的快取,有可能出現併發問題,因此需要採用適當的併發訪問策略,該策略為被快取的資料提供了事務隔離級別。
二級快取是可選的,是一個可配置的第三方外掛,預設下SessionFactory不會啟用這個外掛,如果我們需要使用二級緩衝,就事先需要開啟。
第一、開啟快取
我們需要在我們的hibernate.cfg.xml中開啟我們的二級緩衝,如下:
<!-- 開啟緩衝 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!--指定是哪個二級緩衝-->
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<!-- 使用查詢二級緩衝 -->
<propertyname="hibernate.cache.use_query_cache">true</property>
第二:指明那個實體類需要使用緩衝
我們需要指明那個實體類需要使用緩衝,這裡有兩種配置,一種是xml配置,一種是Annotation的配置,分別如下:
Annotation的配置如下:
@Entity
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
@Table(name="p_person")
public class Persion{
}
Xml的配置也有兩種,一種是在各自的hbm檔案配置,一種是在cfg中配置,
hbm檔案的配置如下:
<class name="Person" table="t_person">
<cache usage="read-write"/>
<id name="id">
……
</class>
cfg檔案的配置如下:
<!-- 指定Student使用二級快取 -->
<class-cache class="com.hibernate.Persion" usage="read-only"/>
第三:需要提供第三方的cache。
其實二級緩衝並不是由Hibernate來提供,是由第三方提供的緩衝外掛,通常有以下幾種第三方緩衝外掛:
- EhCache:可作為程序範圍的快取,存放資料的物理介質可以是記憶體或硬碟,對Hibernate的查詢快取提供了支援。
- OSCache:可作為程序範圍的快取,存放資料的物理介質可以是記憶體或硬碟,提供了豐富的快取資料過期策略,對Hibernate的查詢快取提供了支援。
- SwarmCache:可作為叢集範圍內的快取,但不支援Hibernate的查詢快取。
- JBossCache:可作為叢集範圍內的快取,支援事務型併發訪問策略,對Hibernate的查詢快取提供了支援。
預設hibernate使用的是ehcache。預設的配置如下:
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
到這裡配置結束,我們來進行測試。
@Test
publicvoid findTesterjihuanchong(){
Sessions=sessionFactory.openSession();
s.beginTransaction();
Personperson=(Person)s.load(Person.class, 1);
System.out.println(person.getName());
s.getTransaction().commit();
s.close();
// 另起一個session
Sessions2=sessionFactory.openSession();
s2.beginTransaction();
// 不會發SQL語句,讀取的是二級快取中的資料
Personperson2=(Person)s2.load(Person.class, 1);
System.out.println(person2.getName());
s2.getTransaction().commit();
s2.close();
}
結果是:只有第一個session中傳送了一條SQL語句,第二個session中沒有傳送。
以上是Hibernate的 一級快取和二級快取的介紹,其實 Hiberante還有第三種快取:查詢快取。什麼是查詢快取?查詢緩衝和一級,二級快取的區別是什麼,將在下篇部落格中說明。