1. 程式人生 > >Hibernate緩衝策略 一

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還有第三種快取:查詢快取。什麼是查詢快取?查詢緩衝和一級,二級快取的區別是什麼,將在下篇部落格中說明。