hibernate緩存使用

 

Hibernate緩存是一種提高系統性能的比較好的工具,如果使用合理,則能極大地提高系統性能,但如果使用不合理也會使用系統性能下降。Hibernate緩存比較複雜,要想靈活使用hibernate緩存,必須深入研究hiberante緩存原理,最好能分析hibernate的源代碼。有很多人使用hibernate的時間比較長也不能正確理解hibernate緩存,下面我就談談hibernate緩存的使用,希望能對大家有點幫助。

Session緩存(一級緩存):當調用Session的保存、更新、查詢操作時,在Session緩存中不存在相應對象,則把這些對象加入Session緩存。同一個Session操作,第一次通過ID調用load()或get()查詢持久對象,先從Session緩存中查詢發現該對象不命中,隨即發送一條SQL語句生成一個持久對象並把該對象放入Session緩存。第二次再通過相同ID調用load()或get()查詢時將直接從Session緩存將該對象返回,避免多餘的數據庫連接和查詢的開銷。

Session的load()和get()方法使用區別:

1、當數據庫不存在對應ID數據時,調用load()方法將會拋出ObjectNotFoundException異常,get()方法將返回null,我比較喜歡使用get()方法。

2、當對象.hbm.xml配置文件<class>元素的lazy屬性設置爲true時,調用load()方法時則返回持久對象的代理類實例,此時的代理類實例是由運行時動態生成的類,該代理類實例包括原目標對象的所有屬性和方法,該代理類實例的屬性除了ID不爲null外,所在屬性爲null值,查看日誌並沒有Hibernate SQL輸出,說明沒有執行查詢操作,當代理類實例通過getXXX()方法獲取屬性值時,Hiberante才真正執行數據庫查詢操作。當對象.hbm.xml配置文件<class>元素的lazy屬性設置爲false時,調用load()方法則是立即執行數據庫並直接返回實體類,並不返回代理類。而調用get()方法時不管lazy爲何值,都直接返回實體類。

3、load()和get()都會先從Session緩存中查找,如果沒有找到對應的對象,則查詢Hibernate二級緩存,再找不到該對象,則發送一條SQL語句查詢。關於這點,很多資料說明get ()不會查詢二級緩存,比如夏昕編著的《深入淺出Hibernate》245頁描述get()方法不查詢二級緩存。但我測試發現load()和get()方法都會查詢二級緩存,我上網看了很多緩存方面資料也證實了這點,大家可以看看這篇文章:http://blog.csdn.net/woshichenxu/archive/2006/01/22/586361.aspx
Session的evict()方法將持久對象從Session緩存中清除,clear()方法將清空整個緩存。

二級緩存(SesionFactory): 二級緩存由SessionFactory創建的所有Session對象共享使用, 二級緩存可使用第三方的緩存插件,如EHCache、OSChahe、SwarmCache、JBossCache,下面分別介紹二級緩存的類緩存、集合緩存和查詢緩存。

1、類緩存:類緩存的key是持久對象的ID,value爲持久化對象POJO,無論調用list(),load()還是iterate()查詢,只要讀出一個持久化對象POJO,都會根據POJO的ID作爲key,value爲POJO填充到類緩存中。當通過iterate()方法查詢時,先會向數據庫發送一條select id from POJO的SQL語句,將所有ID查詢出來,再根據ID一個個地作爲key到類緩存中查詢相應POJO,如果類緩存中存在(命中),則從緩存中返回,否則向數據庫發一條select * from POJO  where  id=?語句將查詢該對象返回,並填充到類緩存中。當通過list()方法查詢時,不會象iterate()先查詢ID再查詢類緩存,而是直接發送SQL查詢數據庫將結果返回,但會將查詢結果填充到類緩存中,可供itetator()使用。

配置類緩存的同步策略:在hibernate中啓動二級類緩存,需要在hibernate.cfg.xml配置以下參數:

<hibernate-configuration>

 <session-factory>
    ……
    <property name=”hibernate.cache.provider_class”>
     org.hibernate.cache.EhCacheProvider
<./property>
 </session-factory>
</hibernate-configuration>
 在這裏以EHCache配置爲例,如果用spring的applicationContext.xml配置,參數爲:
<beans>
    <bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
   ……
   <property name="hibernateProperties">
    ……
    <prop key="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</prop>
……
</bean>
</beans>
在這還需要對EHCache進行配置,ehcache.xml配置爲:
<ehcache>
 <diskStore path="java.io.tmpdir"/>
 <defaultCache
    maxElementsInMemory="10000"
    eternal="false"
    timeToIdleSeconds="10000"
    timeToLiveSeconds="10000"
    overflowToDisk="true"
 />
  <cache  name="com.hour41.hibernate.vo.common.City"
    maxElementsInMemory="10000"
    eternal="false"
    timeToIdleSeconds="10000"
    timeToLiveSeconds="10000"
    overflowToDisk="true"
 />
</ehcache>

上面配置了默認類緩存和城市類緩存策略:

<diskStore>表示當內存緩存中對象數量超過類設置內存緩存數量時,將緩存對象寫到硬盤,path=”java.io.tmpdir”表示把數據寫到這個目錄下。Java.io.tmpdir目錄在運行時會根據相對路徑生成。
<defaultCache>表示設定緩存的默認數據過期策略。
<cache>表示設定用具體的命名緩存的數據過期策略。
name表示具體的緩存命名。
maxElementsInMemory表示cache中最大允許保存的對象數據量。
eternal表示cache中數據是否爲常量。
timeToIdleSeconds表示緩存數據鈍化時間
timeToLiveSeconds表示緩存數據的生命時間。
overflowToDisk表示內存不足時,是否啓用磁盤緩存。

Hibernate提供了四種緩存同步策略:

read-only策略:只讀,對於數據庫表的數據不會改變的數據,可以使用只讀型緩存。例如城市表的數據不會發生變化,則可配置類緩存爲:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.hour41.hibernate.vo.common.City" table="tbl_city" lazy="false" mutable="false">
       <cache usage="read-only" />
        <id name="id" type="java.lang.Integer">
            <column name="cityId" />
            <generator class="native"></generator>
        </id>
        <property name="cnName" type="java.lang.String">
            <column name="cityCnName"/>
        </property>
        <property name="enName" type="java.lang.String">
            <column name="cityEnName"/>
        </property>
        <property name="provinceId" type="java.lang.Integer">
            <column name="provinceId" />
        </property>
   </class>
</hibernate-mapping>

nonstrict-read-write策略:如果程序對併發數據修改要求不是非常嚴格,只是偶爾需要更新數據,可以採用本選項,以減少無謂的檢查,獲得較好的性能。
read-write策略:嚴格可讀寫緩存。
transactional策略:事務型緩存。

發佈了84 篇原創文章 · 獲贊 15 · 訪問量 53萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章