hibernate 緩存優化

1,下降訪問數據庫的頻率,減小select語句的數目,實現手段有:使用迫切左外鏈接或迫切內鏈接;對延遲檢索或當即檢索設置批量檢索數目;使用查詢緩存。node

  2,避免加載多餘的應用程序不須要訪問的數據,實現手段有:使用延遲加載策略;使用集合過濾。數據庫

  3,避免報表查詢數據佔用緩存,實現手段爲利用投影查詢功能,查詢出實體的部分屬性。windows

  4,減小select語句中的字段,從而下降訪問數據庫的數據量,實現手段爲利用Query的iterate()方法。緩存

  Query的iterate()方法首先檢索ID字段,而後根據ID字段到hibernate的第一級緩存以及第二級緩存中查找匹配的 Customer對象,若是存在,就直接把它加入到查詢結果集中,不然就執行額外的select語句,根據ID字段到數據庫中檢索該對象。安全

  Query query = session.createQuery("from Customer where age<30");服務器

  Iterator result = erate();session

  對於常用的查詢語句,若是啓用了查詢緩存,當第一次執行查詢語句時,hibernate會把查詢結果存放在第二級緩存中,之後再次執行該查 詢語句時,只需從緩存中得到查詢結果,從而提升查詢性能。若是查詢結果中包含實體,第二級緩存只會存放實體的OID,而對於投影查詢,第二級緩存會存放所 有的數據值。併發

  查詢緩存適用於如下場合:在應用程序運行時常用的查詢語句;不多對與查詢語句關聯的數據庫數據進行插入,刪除,更新操做。oracle

  對查詢語句啓用查詢緩存的步驟以下:app

  1,配置第二級緩存。

  2,在hibernate的配置文件中設置查詢緩存屬性:hibernate.cache.use_query_cache=true

  3,即便設置了緩存,在執行查詢語句時仍然不會啓用查詢緩存,只有在調用query.setCacheable()後才啓用緩存:

  Query query = session.createQuery("from Customer c where c.age > :age");

  query.setInteger("age", age):

  query.setCacheable(true);

  若是但願更加精粒度地控制查詢緩存,能夠設置緩存區域:query.setCacheRegion("customerQueries");

  hibernate提供了3種和查詢相關的緩存區域:

  1,默認的查詢緩存區域:net.sf.hibernate.cache.StandardQueryCache。

  2,用戶自定義的查詢緩存區域:如customerQueries。

  3,時間戳緩存區域:net.sf.hibernate.cache.UpdateTimestampCache。

  默認的查詢緩存區域以及用戶自定義的查詢緩存區域都用於存放查詢結果,而時間戳緩存區域存放了對於查詢結果相關的表進行插入,更新,刪除操做的 時間戳。hibernate經過時間戳緩存區域來判斷被緩存的查詢結果是否過時。當應用進程對數據庫的相關數據作了修改,hibernate會自動刷新緩 存的查詢結果。可是若是其它應用進程對數據庫的相關數據作了修改,hibernate沒法監測到這一變化,此時必須由應用程序負責監測這一變化(如經過發 送和接收事件或消息機制),而後手工刷新查詢結果。

  Query.setForceCacheRefresh(true)方法容許手工刷新查詢結果,它使得hibernate丟棄查詢緩存區域中己有的查詢結果,從新到數據庫中查詢數據,再把查詢結果存放在查詢緩存區域中。

  一個session能夠和多個事務對應:

  Transaction trans1 = session.beginTransaction();

  ... ...//數據庫操做

  mit();//提交第一個事務

  session.disconnect();//釋放數據庫鏈接

  ... ...//執行一些耗時的操做,這段操做不屬於任何事務

  session.reconnect();//從新獲取數據庫鏈接

  Transaction trans2 = session.beginTransaction();//開始第二個事務

  ... ...//數據庫操做

  mit();//提交第二個事務

  注意:若是在執行session的一個事務時出現了異常,就必須當即關閉這個session,不能再利用這個session來執行其它的事務。

  許多數據庫系統都有自動管理鎖的功能,它們能根據事務執行的SQL語句,自動在保證事務間的隔離性與保證事務間的併發性之間作出權衡,而後自動爲數據庫資源加上適當的鎖,在運行期間還會自動升級鎖的類型,以優化系統的性能。

  對於普通的併發性事務,經過系統的自動鎖定管理機制基本能夠保證事務之間的隔離性,但若是對數據安全,數據庫完整性和一致性有特殊要求,也能夠由事務自己來控制對數據資源的鎖定和解鎖。

  數據庫系統可以鎖定的資源包括:數據庫,表,區域,頁面,鍵值(指帶有索引的行數據),行(即表中的單行數據)。在數據庫系統中,通常都支持鎖升級,以提升性能。

  按照封鎖程序,鎖能夠分爲:共享鎖,獨佔鎖,更新鎖。

  共享鎖:用於讀數據操做,它是非獨佔的,容許其它事務同時讀取其鎖定的資源,但不容許其它事務更新它。

  獨佔鎖:也稱排它鎖,適用於修改數據的場合,它所銷定的資源,其它事務不能讀取也不能修改。

  更新鎖:在更新操做的初始化階段用來鎖定可能要被修改的資源,這能夠避免使用共享鎖形成的死鎖現象。

  許多的數據庫系統可以自動按期搜索和處理死鎖問題,當檢測到鎖定請求環時,系統將結束死鎖優先級最低的事務,而且撤銷該事務。

  應用程序中能夠採用下面的一些方法儘可能避免死鎖:

  1,合理安排表訪問順序;

  2,使用短事務;

  3,若是對數據的一致性要求不高,能夠容許髒讀,髒讀不須要對數據資源加鎖,能夠避免衝突;

  4,若是可能的話,錯開多個事務訪問相同數據資源的時間,以防止鎖衝突。

  5,使用盡量低的事務隔離級別。

  爲了實現短事務,在應用程序中能夠考慮使用如下策略:

  1,若是可能的話,嘗試把大的事務分解爲多個小的事務,而後分別執行,這保證每一個小事務都很快完成,不會對數據資源鎖定很長時間。

  2,應該在處理事務以前就準備好用戶必須提供的數據,不該該在執行事務過程當中,停下來長時間等待輸入數據。

  數據庫系統提供了四種事務隔離級別供用戶選擇:

  1,Serializable:串行化。

  2,Repeatable Read:可重複讀。

  3,Read Commited:讀己提交數據。

  4,Read Uncommited:讀未提交數據。

  隔離級別越高,越能保證數據的完整性和一致性,可是對併發性能的影響也越大。對於多數應用程序,能夠優先把數據庫系統的隔離級別設爲 ReadCommited,它可以避免髒讀,並且具備較好的併發性能,儘管它會致使不可重複讀,虛讀和第二類丟失更新這些併發問題,在可能出現這類問題的 個別場合,能夠由應用程序採用悲觀鎖或樂觀鎖來控制。

  JDBC數據庫鏈接使用數據庫系統默認的隔離級別,在hibernate的配置文件中能夠顯式地設置隔離級別(nnection.isolation=2),每一種隔離級別都對應一個整數。

  1:Read Uncommitted;

  2:Read Committed;

  4:Repeatable Read;

  8:Serializable

  在受管理的環境中,若是hibernate使用的是數據庫鏈接來自於應用服務器提供的數據源,hibernate不會修改這些鏈接的事務隔離級別,在這種狀況下,應該經過修改應用服務器的數據源配置來修改隔離級別。

  悲觀鎖:指在應用程序中顯式地爲數據資源加鎖,先鎖定資源再進行操做,儘管悲觀鎖可以防止丟失更新和不可重複讀這類併發問題,可是它會影響併發性能,所以應該很謹慎地使用悲觀鎖。

  樂觀鎖:徹底依靠數據庫的隔離級別來自動管理鎖的工做,應用程序採用版本控制手段來避免可能出現的併發問題。

  悲觀鎖有兩種實現方式:1,在應用程序中顯式指定採用數據庫系統的獨佔鎖來鎖定數據資源;2,在數據庫表中增長一個代表記錄狀態的LOCK字段,當它取值爲Y時,表示該記錄己經被某個事務鎖定,若是爲N,代表該記錄處於空閒狀態,事務能夠訪問它。

  如下select語句,指定採用獨佔鎖來鎖定查詢的記錄:select ... for update;執行該查詢語句的事務持有這把鎖,直到事務結束纔會釋放鎖。

  hibernate能夠採用以下方式聲明使用悲觀鎖:Account account = (Account)session.get(Account.class, 1, LockMode.UPGRADE);

  net.sf.hibernate.LockMode類表示鎖模式,它的取值以下:

  LockMode.NONE:默認值。先查緩存,緩存沒有再去數據庫中查。

  LockMode.READ:老是查詢數據庫,若是映射文件設置了版本元素,就執行版本比較。主要用於對一個遊離對象進行版本檢查。

  LockMode.UPGRADE:老是查詢數據庫,若是映射文件設置了版本元素,就執行版本比較。若是數據庫支持悲觀鎖就執行.... for update。不然執行普通查詢。

  LockMode.UPGRADE_NOWAIT:和UPGRADE功能同樣,此外,對oracle數據庫執行... for update nowait; nowait代表,若是不能當即得到悲觀鎖就拋出異常。

  LockMode.WRITE:當hibernate向數據庫保存或更新一個對象時,會自動使用這種模式,它僅供hibernate內部使用,應用程序中不該該使用它。

  若是數據庫不支持select ... for update語句,也能夠由應用程序來實現悲觀鎖,這須要要表中增長一個鎖字段lock。

  hibernate映射文件中的<version>和<timestamp>元素都具備版本控制功 能。<version>利用一個遞增的整數來跟蹤數據庫表中記錄的版本,<timestamp>用時間戳來跟蹤數據庫表中記錄的 版本。

  version的用法以下:

  配置文件中:<version name="version" column="VERSION"/>必須緊跟在<id>元素的後面。數據庫中的version(int)字段與version屬性映射。

  應用程序無需爲JavaBean的version屬性顯示賦值,在持久化JavaBean對象時,hibernate會自動爲它賦初始值0,在 更新數據時,hibernate會更新自動version屬性:update ACCOUNTS set NAME='Tom',BALANCE=1100,VERSION=1 where ID=1 and VERSION=0;

  若是在此過程當中有其它程序操做過此記錄,那麼它的version就會有更新,再次執行update語句時會找不到匹配的記錄,此時hibernate會拋出StaleObjectStateException。在應用程序中應該處理這種異常,處理方法有兩種:

  1,自動撤消事務,通知用戶信息己被其它事務修改,須要從新開始事務。

  2,通知用戶信息己被其它事務修改,顯示最新數據,由用戶決定若是繼續。

  只有當hibernate經過update語句更新一個對象時,纔會修改它的version屬性,對於存在關聯關係的對象,只更新發生變化的對象,對沒有發生變化的關聯對象是不會更新的,也就是說version不具備級聯特性。

  timestamp用法以下:

  配置文件和表中各加一個屬性(表中是timestamp類型):<timestamp name="lastUpdatedTime" column="LAST_UPDATED_TIME" />必須緊跟在<id>元素的後面。

  當持久化一個JavaBean對象時,hibernate會自動用當前的系統時間爲lastUpdatedTime屬性賦值,更新時也會用系統 時間來更新此字段。理論上<version>元素比<timestamp>更安全一些,由於<timestamp> 只能精確到秒,不能處理毫秒內的同步。

  所以,建議使用基於整數的<version>元素。

  對遊離對象進行版本檢查,若是不一致,會拋出StaleObjectStateException()。:

  Transaction trans = session.beginTransaction();

  session.lock(account, LockMode.READ);//僅僅執行版本檢查(與數據庫中的最新數據進行比較),而不會保存數據庫。

  mit();

  若是數據庫中不包含表明版本或時間戳的字段,hibernate提供了其它方法實現樂觀鎖,把<class>元素的 optimistic-lock屬性設爲all。把<class>元素的optimistic-lock屬性設爲all或dirty。必須同 時把dynamic-update屬性設爲true。

  optimistic-lock=true時,hibernate更新時會在where子句中包含JavaBean對象被加載時的全部屬性。

  optimistic-lock=dirty時,hibernate更新時會在where子句中僅包含被更新過的屬性。

  儘管這種方法也能實現樂觀鎖,可是這種方法速度很慢,並且只適用於在同一個session中加載了該對象,而後又在同一個session中更新 了此對象的場合。若是在不一樣的session中,會致使第二個session沒法知道JavaBean對象被第一個session加載時全部屬性的初始 值,所以不能在update語句的where子句中包含JavaBean對象的屬性的初始值,所以執行如下update語句:update ACCOUNTS set NAME='tom',BALANCE=900 where ID=1;這會致使當前事務覆蓋其它事務對這條記錄己作的更新。

  hibernate的二級緩存自己的實現很複雜,必須實現併發訪問策略以及數據過時策略。SessionFactory的外置緩存是一個可配置的緩存插件,在默認狀況下不會啓用。

  二級緩存,進程範圍或羣集範圍,會出現併發問題,對二級緩存能夠設定如下四種類型的併發訪問策略,每一種策略對應一種事務隔離級別。

  1,事務型:僅僅在受管理環境中適用,它提供Repeatable Read事務隔離級別,對於常常讀可是不多寫的數據,能夠採用這種隔離級別,由於它能夠防止髒讀和不可重複讀這類併發問題。

  2,讀寫型:提供Read Committed事務隔離級別,僅僅在非羣集的環境中適用,對於常常讀可是不多寫的數據,能夠採用這種隔離類型,由於它能夠防止髒讀這類併發問題。

  3,非嚴格讀寫型:不保證緩存與數據庫中數據的一致性。若是存在兩個事務同時訪問緩存中相同數據的可能,必須爲該數據配置一個很短的數據過時時間,從而儘可能避免髒讀,對於極少被修改而且容許髒讀的數據,能夠採用這種併發訪問策略。

  4,只讀型:對於歷來不會寫的數據,可使用這種併發訪問策略。

  事務型策略的隔離級別最高,只讀型的最低,事務隔離級別越高,併發性能越低,若是二級緩存中存放中的數據會常常被事務修改,就不得不提升緩存的事務隔離級別,但這又會下降併發性能,所以,只有符合如下條件的數據才適合於存放到二級緩存中:

  1,不多被修改;2,不是很重要的數據,容許偶爾出現併發問題;3,不會被併發訪問的數據;4,參考數據;

  如下數據不適合於存放到二級緩存中:

  1,常常被修改的數據;2,財務數據,絕對不容許出現併發問題;3,與其它應用共享的數據;

  hibernate還爲查詢結果提供了一個查詢緩存,它依賴於二級緩存。

  Session爲應用程序提供了兩個管理一緩存的方法:

  evict():從緩存中清除參數指定的持久化對象;若是在映射文件關聯關係的cascade爲all或all-delete-orphan 時,會級聯清除;它適用於不但願session繼續按照該對象的狀態變化來同步更新數據庫;在批量更新或指量刪除的場合,當更新或刪除一個對象後,及時釋 放該對象佔用的內存;值得注意的是,批量更新或刪除的最佳方式是直接經過JDBC API執行相關的SQL語句或者調用相關的存儲過程。

  clear():清空緩存中全部持久化對象;

  在多數狀況下,不提倡經過evict()和clear()方法來管理一級緩存,由於它們並不能顯着地提升應用的性能,管理一級緩存的最有效的方法是採用合理的檢索策略和檢索方式,如經過延遲加載,集合過濾,投影查詢等手段來節省內存開銷。

  hibernate中直接經過JDBC API來執行更新或刪除操做的方法以下:

  Transaction trans = session.beginTransaction();

  Connection conn = nnection();

  PreparedStatement statement = conn.prepareStatement("update ACCOUNTS set AGE=AGE+1 where AGE>0");

  statement.executeUpdate();

  mit();

  若是底層數據庫支持存儲過程,也能夠直接調用存儲過程來執行指量更新:

  Transaction trans = session.beginTransaction();

  Connection conn = nnection();

  CallableStatement statement = conn.prepareCall("{call batchUpdateCustomer(?)}");

  statement.setInt(1, 0);//把第1個參數的值設爲0

  statement.executeUpdate();

  mit();

  hibernate中session的各類重載的update()方法一次都只能更新一個對象,而delete()方法有些重載形式容許以HQL語句做爲參數,如:

  session.delete("from Customer c where c.age>0");

  可是它並非執行一條delete語句,而是把符合條件的數據先查找出來,再一個個地執行delete操做。

  hibernate的二級緩存容許選用如下類型的緩存插件:

  1,EHCache:可做爲進程範圍內的緩存,存放數據的物理介質能夠是內存或硬盤,對hibernate的查詢緩存提供了支持。

  2,OpenSymphony OSCache:可做爲進程範圍內的緩存,存放數據的物理介質能夠是內存或硬盤,提供了豐富的緩存數據過時策略,對hibernate的查詢緩存提供了支持。

  3,SwarmCache:可做爲羣集範圍內的緩存,但不支持hibernate的查詢緩存。

  4,JBossCache:可做爲羣集範圍內的緩存,支持事務型併發訪問策略,對hibernate的查詢緩存提供了支持。

  下表列出了以上四種類型的緩存插件支持的併發訪問策略:

  

  以面的四種緩存插件都是由第三方提供的。EHCache來自於hibernate開放源代碼組織的另外一個項目;JBossCache由 JBoss開放源代碼組織提供;爲了把這些緩存插件集成到hibernate中,hibernate提供了 net.sf.hibernate.cache.CacheProvider接口,它是緩存插件與hibernate之間的適配器。hibernate爲 以上緩存插件分別提供了內置的CacheProvider實現:

  net.sf.hibernate.cache.EhCacheProvider

  net.sf.hibernate.cache.OSCacheProvider

  net.sf.hibernate.cache.SwarmCacheProvider

  net.sf.hibernate.cache.TreeCacheProvider:JBossCache插件適配器。

  配置進程範圍內的二級緩存主要包含如下步驟:

  1,選擇須要使用二級緩存的持久化類。設置它的命名緩存的併發訪問策略。hibernate既容許在分散的各個映射文件中爲持久化類設置二級緩 存,還容許在hibernate的配置文件hibernate.cfg.xml中集中設置二級緩存,後一種方式更有利於和緩存相關的配置代碼的維護。示例 以下:

  <hibernate-configuration>

  <session-factory>

  <property ... >

  <!-- 設置JBossCache適配器 -->

  <property name="cache.provider_class">net.sf.hibernate.cache.TreeCacheProvider</property>

  <property name="cache.use_minimal_puts">true</property>

  <mapping .../>

  <!-- 設置Category類的二級緩存的併發訪問策略 -->

  <class-cache class="mypack.Category" usage="transaction" />

  <!-- 設置Category類的items集合的二級緩存的併發訪問策略 -->

  <collection-cache collection="ems" usage="transactional" />

  <!-- 設置Item類的二級緩存的併發訪問策略 -->

  <class-cache class="mypack.Item" usage="transactional" />

  </session-factory>

  </hibernate-configuration>

  cache.use_minimal_puts屬性爲true,表示hibernate會先檢查對象是否己經存在於緩存中,只有當對象不在緩存 中,纔會向緩存加入該對象的散裝數據,默認爲false。對於羣集範圍的緩存,若是讀緩存的系統開銷比寫緩存的系統開銷小,能夠將此屬性設爲true,從 而提升訪問緩存的性能,而對於進程範圍內的緩存,此屬性應該取默認值false。

  2,選擇合適的緩存插件,每種插件都有自帶的配置文件,所以須要手工編輯該配置文件,EHCache的配置文件爲ehcache.xml,而JBossCache的配置文件爲treecache.xml。在配置文件中須要爲每一個命名緩存設置數據過時策略。

  hibernate容許在類和集合的粒度上設置二級緩存,在映射文件中,<class>和<set>元素都有一 個<cache>子元素,這個子元素用來配置二級緩存,例如如下代碼把Category實例放入二級緩存中,採用讀寫併發訪問策略:

  <class name="mypack.Category" talbe="CATEGORIES">

  <cache usage="read-write"/>

  <id ...>

  </id>

  ...

  </class>

  每當應用程序從其它對象導航到Category對象,或者從數據庫中加載Category對象時,hibernate就會把這個對象放到第二級 緩存中,<class>元素的<cache>子元素代表hibernate會緩存Category對象的簡單屬性的值,可是它並 不會同時緩存Category對象的集合屬性,若是但願緩存集合屬性中的元素,必須在<set>元素中加入<cache>子元 素:

  <set name="items" inverse="true" lazy="true">

  <cache usage="read-write" />

  <key ...>

  </set>

  當應用程序調用category.getItems(erate()方法時,hibernate會把item集合中的元素存放到緩存中,此時 hibernate僅僅把與Category關聯的Item對象的OID存放到緩存中,若是但願把整個Item對象的散裝數據存入緩存,應該在 Item.hbm.xml文件的<class>元素中加入<cache>子元素。

  EHCache緩存插件是理想的進程範圍內的緩存實現。若是使用這種緩存插件,須要在hibernate的hibernate.properties配置文件中指定EhCacheProvider適配器,代碼以下:

  hibernate.cache.provider=net.sf.hibernate.cache.EhCacheProvider

  EHCache緩存有本身的配置文件,名爲ehcache.xml,這個文件必須存放於應用的classpath中,下面是一個樣例:

  <ehcache>

  <diskStore path="C:\\temp"/>

  <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"/>

  <cache name="mypack.Category" maxElementsInMemory="500" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false"/>

  <cache name="ems" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true"/>

  <cache name="mypack.Item" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true"/>

  </ehcache>

  hibernate軟件包的etc目錄下提供了ehcache.xml文件的樣例,而且對於它的配置元素作了詳細的說明。

  ehcache.xml目錄下提供了ehcache.xml文件的樣例,而且對它的配置元素作了詳細的說明:

  <diskStore>:指定一個文件目錄,當EHCache把數據寫到硬盤上時,將把數據寫到這個文件目錄下。

  <defaultCache>:設定緩存的默認數據過時策略。

  <cache>:設定具體的命名緩存的數據過時策略。

  在映射文件中,對每一個須要二級緩存的類和集合都作了單獨的配置,與此對應,在ehcache.xml文件中經過<cache>元素來爲每一個須要二級緩存的類和集合設定緩存的數據過時策略。下面解釋一下<cache>元素的各個屬性的做用:

  name:設置緩存的名字,它的取值爲類的完整名字或者類的集合的名字,若是name屬性爲mypack.Category,表示Category類的二級緩存;若是name屬性爲ems,表示Category類的items集合的二級緩存。

  maxInMemory:設置基於內存的緩存可存放的對象的最大數目。

  eternal:若是爲true,表示對象永遠不會過時,此時會忽略timeToIdleSeconds和timeToLiveSeconds屬性。默認爲false。

  timeToIdleSeconds:設定容許對象處於空閒狀態的最長時間,以秒爲單位,當對象從最近一次被訪問後,若是處於空閒狀態的時間超 過了指定的值,這個對象會過時,EHCache將把它從緩存中清除,只有當eternal屬性爲false,它纔有效,值爲0表示對象能夠無限期地處於空 閒狀態。

  timeToLiveSeconds:設定對象容許存在於緩存中的最長時間,以秒爲單位,當對象自從被放入緩存中後,若是處於緩存中的時間超過 了指定的值,這個對象就會過時,EHCache將把它從緩存中清除,只有當eternal屬性爲false,它纔有效,值爲0表示對象能夠無限期地處於空 閒狀態。它的值必須大於或等於timeToIdleSeconds的值纔有意義。

  overflowToDisk:若是爲true,表示當基於內存的緩存中的對象數目達到了maxInMemory界限,會把溢出的對象寫到基於硬盤的緩存中。

  每一個命名緩存表明一個緩存區域,每一個緩存區域有各自的數據過時策略,命名緩存機制使得用戶可以在每一個類以及類的每一個集合的粒度上設置數據過時策略。

  EHCache適用於hibernate應用發佈在單個機器中的場合。

  在羣集環境下,能夠用JBossCache做爲hibernate的二級緩存,它的配置步驟以下:

  1,在hibernate配置文件中設置JBossCache適配器,而且爲須要使用二級緩存的類和集合設置緩存的併發訪問策略。

  2,編輯JBossCache自身的配置文件,名爲treecache.xml,這個文件必須放在classpath中,對於羣集環境中的每一個 節點,都必須提供單獨的treecache.xml文件,假如羣集環境中有兩個節點node A和node B,node A節點的名字爲ClusterA,下面是node A節點的treecache.xml文件的樣例:

  <?xml version="1.0" encoding="UTF-8"?>

  <server>

  <classpath codebase="./lib" archives="jboss-cache.jar,jgroups.jar"/>

  <!-- 把TreeCache發佈爲JBoss的一個JMX服務 -->

  <mbean code="org.jboss.cache.TreeCache" name="jboss.cache:service=TreeCache">

  <depends>jboss:service=Naming</depends>

  <depends>jboss:service=TransactionManager</depends>

  <!-- TreeCache運行在羣集環境的名爲ClusterA的節點上 -->

  <attribute name="ClusterName">ClusterA</attribute>

  <!-- TreeCache採用同步通訊機制 -->

  <attribute name="CacheMode">REPL_SYNC</attribute>

  <attribute name="SyncReplTimeout">10000</attribute>

  <attribute name="LockAcquisitionTimeout">15000</attribute>

  <attribute name="FetchStateOnStartup">true</attribute>

  <!-- TreeCache採用內置的數據過時策略:LRUPolicy -->

  <attribute name="EvictionPolicyClass">org.jboss.cache.eviction,LRUPolicy</attribute>

  <attribute name="EvictionPolicyConfig">

  <config>

  <attribute name="wakeUpIntervalSeconds">5</attribute>

  <!-- Cache wide default -->

  <region name="/_default_">

  <attribute name="maxNodes">5000</attribute>

  <attribute name="timeToIdleSeconds">1000</attribute>

  </region>

  <!-- 配置Category類的數據過時策略 -->

  <region name="/mypack/Category">

  <attribute name="maxNodes">500</attribute>

  <attribute name="timeToIdleSeconds">5000</attribute>

  </region>

  <!-- 配置Category類的items集合的數據過時策略 -->

  <region name="/mypack/Category/items">

  <attribute name="maxNodes">5000</attribute>

  <attribute name="timeToIdleSeconds">1800</attribute>

  </region>

  </config>

  </attribute>

  <!-- 配置JGroup -->

  <attribute name="ClusterConfig">

  <config>

  <UDP bind_addr="202.145.1.2" ip_mcast="true" loopback="false" />

  <PING timeout="2000" num_initial_members="3" up_thread="false" down_thread="false" />

  <FD_SOCK/>

  <pbcast.NAKACK gc_lag="50" retransmit_timeout="600,1200,2400,4800" max_xmit_size="8192" up_thread="false" down_thread="false" />

  <UNICAST timeout="600,1200,2400" window_size="100" min_threshold="10" down_thread="false" />

  <pbcast.STABLE desired_avg_gossip="20000" up_thread="false" down_thread="false" />

  <FRAG frag_size="8192" down_thread="false" up_thread="false" />

  <pbcast.GMS join_timeout="5000" join_retry_timeout="2000" shun="true" print_local_addr="true" />

  <pbcast.STATE_TRANSFER up_thread="true" down_thread="true" />

  </config>

  </attribute>

  </mbean>

  </server>

  以上配置文件把JBossCache配置爲JBoss的一個JMX服務,此外還配置了JGroup,它是一個通訊庫。JBoss爲 JBossCache提供了幾種實現,hibernate採用的是TreeCache實現。treecache.xml文件夾的開頭幾行是JBoss的 JMX服務的發佈描述符,若是TreeCache不運行在JBoss服務器中,這幾行會被忽略。

  TreeCache採用內置的org.jboss.cache.eviction.LRUPolicy策略,它是一種控制緩存中的數據過時的策 略,因爲當一個對象過時後,就會從緩存中清除,所以數據過時策略也叫作數據清除策略。接下來配置了Category類和它的items集合設置了具體的數 據過時策略。

  最後配置了JGroup,它包含一系列通訊協議,這些通訊協議的次序很重要,不能隨意修改它們。第一個協議爲UDP,它和一個IP地址 202.145.1.1綁定,這是當前節點的IP地址,UDP協議使得該節點支持廣播通訊,若是節點選用的是微軟的windows平臺,必須把 loopback屬性設爲true。其它的JGroup屬性很複雜,它們主要用於管理羣集中節點之間的通訊,想進一步瞭解,能夠參考JBoss網站上的 JGroup文檔。

  能夠按照一樣的方式配置node B節點的treecache.xml文件,只需修改其中UDP協議的IP綁定地址。

  經過以上配置,hibernate將啓用羣集範圍內的事務型緩存,每當一個新的元素加入到一個節點的緩存中時,這個元素就會被複制到其它節點的緩存中,若是緩存中的一個元素被更新,那麼它就會過時,並從緩存中清除。

  只有在hibernate的配置文件或映射文件中爲一個持久化類設置了二級緩存,hibernate在加載這個類的實例時纔會啓用二級緩存。

  SessionFactory也提供了evict()方法用於從二級緩存中清除對象的散裝數據,如:

  sessionFactory.evict(Category.class, 1);//清除二級緩存中OID爲1的Category對象

  sessionFactory.evict("mypack.Category");//清除二級緩存中全部的Category對象

  sessionFactory.evictCollection("ems");//清除二級緩存中Category類的全部對象的items集合

相關文章
相關標籤/搜索