1. 程式人生 > >Hibernate中的快取機制與可能遇到的問題

Hibernate中的快取機制與可能遇到的問題

使用hibernate二級快取,我們首先需要對其進行配置,配置步驟如下:

1.hibernate並沒有提供相應的二級快取的元件,所以需要加入額外的二級快取包,常用的二級快取包是EHcache。這個我們在下載好的hibernate的lib->optional->ehcache下可以找到(我這裡使用的hibernate4.1.7版本),然後將裡面的幾個jar包匯入即可。

2.在hibernate.cfg.xml配置檔案中配置我們二級快取的一些屬性:

     <!-- 開啟二級快取 -->
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <!-- 二級快取的提供類 在hibernate4.0版本以後我們都是配置這個屬性來指定二級快取的提供類-->
        <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
        <!-- 二級快取配置檔案的位置 -->
        <property name="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</property>

3.配置hibernate的二級快取是通過使用 ehcache的快取包,所以我們需要建立一個 ehcache.xml 的配置檔案,來配置我們的快取資訊,將其放到專案根目錄下

<ehcache>

    <!-- Sets the path to the directory where cache .data files are created.

         If the path is a Java System Property it is replaced by
         its value in the running VM.

         The following properties are translated:
         user.home - User's home directory
         user.dir - User's current working directory
         java.io.tmpdir - Default temp file path -->
  
  <!--指定二級快取存放在磁碟上的位置-->
    <diskStore path="user.dir"/>  

  <!--我們可以給每個實體類指定一個對應的快取,如果沒有匹配到該類,則使用這個預設的快取配置-->
    <defaultCache
        maxElementsInMemory="10000"  //在記憶體中存放的最大物件數
        eternal="false"         //是否永久儲存快取,設定成false
        timeToIdleSeconds="120"    
        timeToLiveSeconds="120"    
        overflowToDisk="true"     //如果物件數量超過記憶體中最大的數,是否將其儲存到磁碟中,設定成true
        />
  
  <!--
    1、timeToLiveSeconds的定義是:以建立時間為基準開始計算的超時時長;
    2、timeToIdleSeconds的定義是:在建立時間和最近訪問時間中取出離現在最近的時間作為基準計算的超時時長;
    3、如果僅設定了timeToLiveSeconds,則該物件的超時時間=建立時間+timeToLiveSeconds,假設為A;
    4、如果沒設定timeToLiveSeconds,則該物件的超時時間=max(建立時間,最近訪問時間)+timeToIdleSeconds,假設為B;
    5、如果兩者都設定了,則取出A、B最少的值,即min(A,B),表示只要有一個超時成立即算超時。

  -->

  <!--可以給每個實體類指定一個配置檔案,通過name屬性指定,要使用類的全名-->
    <cache name="com.xiaoluo.bean.Student"
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />

    <cache name="sampleCache2"
        maxElementsInMemory="1000"
        eternal="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        overflowToDisk="false"
        /> -->


</ehcache>

4.開啟我們的二級快取

①如果使用xml配置,我們需要在 Student.hbm.xml 中加上一下配置:

<hibernate-mapping package="com.xiaoluo.bean">
    <class name="Student" table="t_student">
        <!-- 二級快取一般設定為只讀的 -->
        <cache usage="read-only"/>
        <id name="id" type="int" column="id">
            <generator class="native"/>
        </id>
        <property name="name" column="name" type="string"></property>
        <property name="sex" column="sex" type="string"></property>
        <many-to-one name="room" column="rid" fetch="join"></many-to-one>
    </class>
</hibernate-mapping>

二級快取的使用策略一般有這幾種:read-only、nonstrict-read-write、read-write、transactional。注意:我們通常使用二級快取都是將其配置成 read-only ,即我們應當在那些不需要進行修改的實體類上使用二級快取,否則如果對快取進行讀寫的話,效能會變差,這樣設定快取就失去了意義。

②如果使用annotation配置,我們需要在Student這個類上加上這樣一個註解:

@Entity
@Table(name="t_student")
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)  //  表示開啟二級快取,並使用read-only策略
public class Student
{
    private int id;
    private String name;
    private String sex;
    private Classroom room;
    .......
}

這樣我們的二級快取配置就算完成了

需要注意的是:

①二級快取是sessionFactory級別的快取

因為二級快取是sessionFactory級別的快取,我們看到,在配置了二級快取以後,當我們session關閉以後,我們再去查詢物件的時候,此時hibernate首先會去二級快取中查詢是否有該物件,有就不會再發sql了。

②二級快取快取的僅僅是物件,如果查詢出來的是物件的一些屬性,則不會被加到快取中去

③通過二級快取來解決 N+1 的問題