posts - 60,comments - 71,trackbacks - 0

                  Cache就是緩存,它往往是提高系統(tǒng)性能的最重要手段,對數(shù)據(jù)起到一個蓄水池和緩沖的作用。Cache對于大量依賴數(shù)據(jù)讀取操作的系統(tǒng)而言尤其重要。在大并發(fā)量的情況下,如果每次程序都需要向數(shù)據(jù)庫直接做查詢操作,它們所帶來的性能開銷是顯而易見的,頻繁的網(wǎng)絡(luò)輿,數(shù)據(jù)庫磁盤的讀寫操作都會大大降低系統(tǒng)的性能。此時如果能讓數(shù)據(jù)庫在本地內(nèi)存中保留一個鏡像,下次訪問的時候只需要從內(nèi)存中直接獲取,那么顯然可以帶來不小的性能提升。引入Cache機(jī)制的難點(diǎn)是如何保證內(nèi)存中數(shù)據(jù)的有效性,否則臟數(shù)據(jù)的出現(xiàn)將會給系統(tǒng)帶來難以預(yù)知的嚴(yán)重后果。雖然一個設(shè)計(jì)得很好的應(yīng)用程序不用Cache也可以表現(xiàn)出讓人接受的性能,但毫無疑問,一些對讀取操作要求比較高的應(yīng)用程序可以通過Cache獲得更高的性能。對于應(yīng)用程序,Cache通過內(nèi)存或磁盤保存了數(shù)據(jù)庫中的當(dāng)前有關(guān)數(shù)據(jù)狀態(tài),它是一個存儲在本地的數(shù)據(jù)備份。Cache位于數(shù)據(jù)庫和應(yīng)用程序之間,從數(shù)據(jù)庫更新數(shù)據(jù),并給程序提供數(shù)據(jù)。
          Hibernate實(shí)現(xiàn)了良好的Cache機(jī)制,可以借助Hibernate內(nèi)部的Cache迅速提高系統(tǒng)的數(shù)據(jù)讀取性能。Hibernate中的Cache可分為兩層:一級Cache和二級Cache。
          一級Cache:
          Session實(shí)現(xiàn)了第一級Cache,它屬于事務(wù)級數(shù)據(jù)緩沖。一旦事務(wù)結(jié)束,這個Cache也隨之失效。一個Session的生命周期對應(yīng)一個數(shù)據(jù)庫事務(wù)或一個程序事務(wù)。
          Session-cache保證了一個Session中兩次請求同一個對象時,取得的對象是同一個JAVA實(shí)例,有時它可以避免不必要的數(shù)據(jù)沖突。另外,它還能為另一些重要的性能提供保證:
          1:在對一個對象進(jìn)行自我循環(huán)引用時, 不至于產(chǎn)生堆棧溢出。
          2:當(dāng)數(shù)據(jù)庫事務(wù)結(jié)束時,對于同一個數(shù)據(jù)庫行,不會產(chǎn)生數(shù)據(jù)沖突,因?yàn)閷τ跀?shù)據(jù)庫中的一行,最多只有一個對象來表示它。
          3:一個事務(wù)中可能會有很多個處理單元,在每一個處理單元中做的操作都會立即被另外的處理單元得知。
          我們不用刻意去打開Session-cache,它總是被打開并且不能被關(guān)閉。當(dāng)使用save(),update()或saveOrUpdate()來保存數(shù)據(jù)更改,或通過load(),find(),list()等方法來得到對象時,對象就會被加入到Session-cache。
          如果要同步很多數(shù)據(jù)對象,就需要有效地管理Cache,可以用Session的evict()方法從一級Cache中移除對象。如下:
          Session session = HibernateUtil.currentSession();
          Transaction tx 
          = session.beginTransaction();
          for(int i = 0 ; i <100000 ; i++)
          {
              Student stu 
          = new Student();
              
              session.save(stu);
          }

          tx.commit();
          session.close();
          在保存50000個或更多對象時,程序可能會拋出OutOfMemoryException異常,因?yàn)镠ibernate在一級Cache緩存了新加入的所有對象。內(nèi)存溢出。要解決這全問題就需要把JDBC批處理數(shù)量設(shè)置為一個合理的數(shù)值(一般是10~20)。在Hibernate的配置文件中可以加入以下屬性
          <property name="hibernate.jdbc.batch_size"> 20 </property>

          然后我們在程序中一定時刻就提交并更新Session的Cache:
          Session session = HibernateUtil.currentSession();
          Transaction tx 
          = session.beginTransaction();
          for(int i = 0 ; i <100000 ; i++)
          {
              Student stu 
          = new Student();
              
              session.save(stu);
              
          if(i%20 == 0)    //每保存完20個對象后,進(jìn)行如下操作
              {
                  session.flush();
          //這個會提交更新
                  session.clear();//清除Cache,釋放內(nèi)存
              }

          }

          tx.commit();
          session.close();

          二級Cache
          二級Cache是SessionFactory范圍內(nèi)的緩存,所有的Session共享同一個二級Cache。在二級Cache中保存持久性實(shí)例的散裝形式的數(shù)據(jù)。二級Cache的內(nèi)部如何實(shí)現(xiàn)并不重要,重要的是采用哪種正確的緩存策略,以及采用哪個Cache提供器。持久化不同的數(shù)據(jù)需要不同的Cache策略,比如一些因素將影響到Cache策略的選擇:數(shù)據(jù)的讀/寫比例,數(shù)據(jù)表是否能被其他的應(yīng)用程序揚(yáng)訪問等。對于一些讀/寫比例高的數(shù)據(jù)可以打開它的緩存,允許這些數(shù)據(jù)進(jìn)入二級緩存容器有利于系統(tǒng)性能的優(yōu)化;而對于能被其它應(yīng)用程序訪問的數(shù)據(jù)對象,最好將此對象的二級Cache選項(xiàng)關(guān)閉。
          設(shè)置Hibernate的二級Cache需要分兩步進(jìn)行:首先確認(rèn)使用什么數(shù)據(jù)并發(fā)策略,然后配置緩存過期時間并設(shè)置Cache提供器。
          有4種內(nèi)置的Hibernate數(shù)據(jù)并發(fā)沖突策略,代表數(shù)據(jù)庫隔離級別,如下:
          1:事務(wù)(Transaction)僅在受管理的環(huán)境中可用。它保證可重讀的事務(wù)隔離級別,可以對讀/寫比例高,很少更新的數(shù)據(jù)采用該策略。
          2:讀寫(read-write)使用時間戳機(jī)制維護(hù)讀寫提交事務(wù)隔離級別。可以對讀/寫比例高,很少更新的數(shù)據(jù)采用該策略。
          3:非嚴(yán)格讀寫(notstrict-read-write)不保證Cache和數(shù)據(jù)庫之間的數(shù)據(jù)庫的一致性。使用此策略時,應(yīng)該設(shè)置足夠的緩存過期時間,否則可能從緩存中讀出臟數(shù)據(jù)。當(dāng)一些數(shù)據(jù)極少改變,并且當(dāng)這些數(shù)據(jù)和數(shù)據(jù)庫有一部份不量影響不大時,可以使用此策略。
          4:只讀(read-only)當(dāng)確保數(shù)據(jù)永不改變時,可以使用此策略。

          我們確定了Cache策略后,就要挑選一個高效的Cache提供器,它將作為插件被Hibernate調(diào)用。Hibernate允許使用下述幾種緩存插件:
          EhCache:可以在JVM中作為一個簡單進(jìn)程范圍內(nèi)的緩存,它可以把緩存的數(shù)據(jù)放入內(nèi)存或磁盤,并支持Hibernate中可選用的查詢緩存。
          OpenSymphony OSCache:和EhCache相似,并且提供了豐富的緩存過期策略。
          SwarmCache:可作為集群范圍的緩存,但不支持查詢緩存。
          JBossCache:可作為集群范圍的緩沖,但不支持查詢緩存。

          在Hibernate中使用EhCache
          EhCache是一個純JAVA程序,可以在Hibernate中作為一個插件引入。在Hibernate中使用EhCache需要在Hibernate的配置文件中設(shè)置如下:

          <propery name="hibernate.cache.provider_class">
              org.hibernate.cache.EhCacheProvider
          </property>
          EhCacheProvider類是位于Hibernate3.jar包中而不是ehcache-1.1.jar包中。EhCache有自己的配置文檔,名為chcache.xml。Hibernate3.x中的etc目錄下有ehcache.xml的示例文件,只須要將 它COPY到我們的應(yīng)用程序src目錄下(編譯時會把ehcache.xmlCOPY到WEB-INF/classes目錄下)。對其中的相關(guān)值進(jìn)行更改以和自己的程序相適應(yīng)。進(jìn)行配置后,在ehcache.xml文件中的代碼如下:
          <ehcache>
              
          <diskStore path="c:\\cache"/>    //設(shè)置cache.data文件存放位置

              
          <defaultCache
                          
          maxElementsInMemory="10000" //緩存中允許創(chuàng)建的最大對象數(shù)
                          eternal
          ="false"    //緩存中對象是否為永久的
                          timeToIdleSeconds
          ="120"//緩存數(shù)據(jù)鈍化時間(即對象在它過期前的空閑時間)
                          timeToLiveSeconds
          ="120"//緩存數(shù)據(jù)生存時間(即對象在它過期前的生存時間)
                          overflowToDisk
          ="true"
              
          />
              
              
          <cache name="Student"    //用戶自定義的Cache配置
                           maxElementsInMemory
          ="10000"
                           eternal
          ="false"
                           timeToIdleSeconds
          ="300"
                           timeToLiveSeconds
          ="600"
                           overflowToDisk
          ="true"
                           
          />
          </ehcache>
          此外我們還需要在持久化類的映射文件中進(jìn)行配置。例如,Group(班級)和Student(學(xué)生)是一對多的關(guān)系,它們對應(yīng)的數(shù)據(jù)表分別是t_group和t_student。現(xiàn)在要把Student類的數(shù)據(jù)進(jìn)行二級緩存,這需要在二個映射文件中都對二級緩存進(jìn)行配置。
          在Group.hbm.xml中如下
          在其<set></set>中添加
          <cache usage="read-write"/><!--集合中的數(shù)據(jù)被緩存-->
          上述文件雖然在<set>標(biāo)記中設(shè)置了<cache usage="read-write"/>,但Hibernate只是把Group相關(guān)的Student的主鍵ID加入到緩存中,如果希望把整個Student的散裝屬性都加入到二級緩存中,還需要在Student.hbm.xml文件的<class>標(biāo)記中添加<cache>子標(biāo)記。如下:
          <class name="Student" table="t_student">
              
          <cache usage="read-write" /><!--cache標(biāo)記需跟在class標(biāo)記后-->
          </class>
          posted on 2008-05-25 14:11 henry1451 閱讀(284) 評論(0)  編輯  收藏 所屬分類: Hibernate技術(shù)
          主站蜘蛛池模板: 蒲城县| 阆中市| 湖州市| 酉阳| 阿拉善左旗| 海口市| 镇赉县| 郁南县| 苗栗市| 姜堰市| 江西省| 上杭县| 揭阳市| 沙坪坝区| 永嘉县| 宜州市| 奉节县| 普洱| 景东| 五大连池市| 隆子县| 利川市| 汝南县| 武夷山市| 迁安市| 江油市| 南阳市| 玛沁县| 安仁县| 句容市| 贡嘎县| 永吉县| 霍城县| 济源市| 金秀| 厦门市| 万山特区| 博客| 平陆县| 克东县| 嘉善县|