天天看點

Hibernate二級緩存提升性能(注解方式)

       合理的緩存應用可以極大地提高系統性能,最簡單的是在應用層面做緩存(越高層面做緩存,效果往往越好),直接将資料緩存到伺服器中,以全局map方式存儲。在使用的時候直接從緩存的map中取,而不用連接配接資料庫,進而提升性能。這種方式簡單易行,但是map常駐伺服器記憶體,并且在資料變更(增删改)的時候要手動更新map。

       還有一種方式比較通用,就是使用Hibernate二級緩存(SessionFactory級别的全局緩存,程序或叢集級别),是一種通用緩存(一級緩存就不說了,Session級别緩存,hibernate自己管理),hibernate二級緩存多應用在多讀少寫的實體對象中,比如組織機構和系統字典。本文使用hibernate注解方式使用二級緩存,做一個說明(使用Ehcache)。

          1、添加ehcache.xml配置檔案

<ehcache>
 <!--  maxElementsInMemory="10000" 緩存中最大允許建立的對象數 -->
 <!-- eternal="false" 緩存中對象是否為永久的,如果是,逾時設定将被忽略,對象從不過期 -->
 <!-- timeToIdleSeconds="120" 緩存資料鈍化時間(設定對象在它過期之前的空閑時間) -->            
 <!--  timeToLiveSeconds="120" 緩存資料的生存時間(設定對象在它過期之前的生存時間) -->
 <!--  overflowToDisk="true" 記憶體不足時,是否啟用磁盤緩存 -->
    
     <diskStore path="c:\\ehcache\"/>     
     <defaultCache     
  maxElementsInMemory="10000"     
  eternal="false"     
  timeToIdleSeconds="120"     
  timeToLiveSeconds="120"     
  overflowToDisk="true"        
  />     
 </ehcache>            

       2、hibernate配置檔案中,配置Ehcache相關屬性

<!-- 使用二級緩存:false -->
	        hibernate.cache.use_second_level_cache=true
       	    <!-- 啟動查詢緩存:false -->
       	        hibernate.cache.use_query_cache=true
        	    <!-- 二級緩存插件:org.hibernate.cache.EhCacheProvider -->
        	        hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
        	    <!-- 是否收集有助于性能調節的統計資料:true -->
        	        hibernate.generate_statistics=true
		           

           調試的時候,可以設定log4j的log4j.logger.org.hibernate.cache=debug(記錄二級緩存的活動),實際釋出的時候,注釋掉,以免影響性能。

        3、pom檔案中引入相應jar包(Maven項目,如果還在手動添加jar包的,可以嘗試使用maven)

<dependency>
		  <groupId>org.hibernate</groupId>
		  <artifactId>hibernate-ehcache</artifactId>
		  <version>3.6.9.Final</version>
		</dependency>           

            這樣就引入了hibernate-ehcache-3.6.9.jar及其依賴包ehcache-core-2.4.3.jar

       4、注解方式配置實體

       配置了二級緩存後,并不是對所有的實體使用,而是需要指定哪些實體需要用到。如果不配置查詢緩存(查詢緩存會在下面講到),則隻會在根據id查詢的操作中,緩存對象。

     在實體上配置@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 并指定緩存并發政策。ehcache的四種緩存并發政策如下: 

read-write

(讀寫型)

提供Read Committed事務隔離級别

在非叢集的環境中适用

适用經常被讀,很少修改的資料

可以防止髒讀

更新緩存的時候會鎖定緩存中的資料

nonstrict-read-write

(非嚴格讀寫型)

适用極少被修改,偶爾允許髒讀的資料(兩個事務同時修改資料的情況很少見)

不保證緩存和資料庫中資料的一緻性

為緩存資料設定很短的過期時間,進而盡量避免髒讀

不鎖定緩存中的資料

read-only

(隻讀型)

适用從來不會被修改的資料(如參考資料)

在此模式下,如果對資料進行更新操作,會有異常

事務隔離級别低,并發性能高

在叢集環境中也能完美運作

@Entity
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 
@Table(name = "base_dict")
@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler",	"fieldHandler", "parentDict" })
public class Dict implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 5569761987303812150L;

	@Id
	@Column(name = "id", length = 36)
	@GeneratedValue(generator = "uuid")
	@GenericGenerator(name = "uuid", strategy = "org.hibernate.id.UUIDGenerator")
	@JsonProperty("id")
	private String id;

	/** 字典名稱 */
	@ForeignShow
	@Column(name = "name", length = 200)
	private String name;           

     5、查詢緩存的使用   

Query query = session.createQuery(hql);   
  query.setCacheable(true); //啟用查詢緩存
  query.setCacheRegion(“queryCacheRegion”); //設定查詢緩存區域(資料過期政策)
  query.list();
           

       Query Cache隻是在特定的條件下才會發揮作用,而且要求相當嚴格:

        (1) 完全相同的HQL重複執行。(注意,隻有hql)

        (2) 重複執行期間,Query Cache對應的資料表不能有資料變動(比如添、删、改操作)

         絕大多數的查詢并不能從查詢緩存中受益,是以Hibernate預設是不進行查詢緩存的。

      查詢緩存适用于以下場合:

  (1)在應用程式運作時經常使用的查詢語句(參數相同)

  (2)很少對與查詢語句檢索到的資料進行插入、删除或更新操作  

     6、不使用緩存、使用hibernate二級緩存性能對比 

    在人員資訊清單,性别、政治面貌、職稱、職位使用字典對象存儲,使用緩存後,第一次将相應字典緩存,之後在互動将不會重新查詢資料庫,進而提升系統性能。見下圖實驗結果(機關ms)

Hibernate二級緩存提升性能(注解方式)

      從圖中可以看到,使用hibernate二級緩存後性能明顯提升一倍。(第一次未使用緩存,是以第一次用時明顯高)

       7、應用緩存、hibernate二級緩存性能對比

       為了驗證“在應用層面越高的地方做緩存效果越好”這句話,我們來測試下兩種緩存性能之間差别。

            測試場景:初始化字典下拉框,下拉框有24個值。結果如下(機關ms)

Hibernate二級緩存提升性能(注解方式)

     實驗結果很明顯,應用緩存的效果明顯好于前兩者,但是應用緩存在第一次的時候耗時較長,因為要做初始化操作。在更新資料時,要更新緩存,也會存在一定耗時,是以看到應用緩存的第一個點很高。另外一個時間點也比較特殊,就是hibernate查詢緩存中倒數第二個點,這是因為緩存逾時移除,是以重新從資料庫中查詢(從該值接近不使用查詢緩存可看出)。

     要看是否連接配接資料庫查詢,隻需看控制台是否列印出sql語句。

         下篇文章将會說下Hibernate一級緩存與懶加載,以上内容不正之處,請指正。

繼續閱讀