`

试用Hibernate二级缓存Ehcache

阅读更多

  Hibernate supports several third-party caching services.  After some research, the team has concluded that Ehcache would be suitable for our requirements, namely the caching of frequently-accessed, read-only tables.

 

Ehcache Evaluation

 

I spent the last couple of days evaluating Ehcache.  I installed the following products locally:

 

  • Hibernate 3.3.2 GA
  • Ehcache 1.2.3 (an optional JAR bundled with Hibernate 3.3.2)
  • Hibernate Annotations 3.4.0 GA

 

I was able to create and test a standalone application using Hibernate/Ehcache in conjunction with SQL Server 2005.  I populated the SQL server database with several thousand records.

 

My test application reads all of the records in the database in several ways:

 

1.  Directly by primary key.

2.  Using a single Query to return a large result set.

3.  Using a series of individual Queries that return small result sets.

 

I used the test program to analyze performance with and without caching.  Caching resulted in substantial improvement; however, I learned that optimal performance requires that:

 

1.  Entities referenced in the transaction are designated as cached.

2.  Associations that are traversed are designated as cached.

3.  Queries are cached.

 

The remainder of this document details the installation and configuration steps needed to enable caching in the Dialogs product.

 

Installation

It is necessary to add the Ehcache JAR to the classpath.   Ehcache JAR is bundled inside the Hibernate distribution JAR in the /optional/ehcache folder:

Ehcache Install

 

Ehcache requires additional third-party JARs; however, it is likely that these additional JARs are already on the Dialogs classpath because they are also required by Hibernate and/or Spring Framework. 

 

Here is the complete set of JARs I used for my local tests:

 


  Ehcache Libs


Configuration

 Successful implementation of Ehcache requires that:

 

  1. Hibernate is configured to enable caching.
  2. An ehcache.xml file is created and placed on the classpath.
  3. Model classes are updated to add @Cache annotations to entities and associations.
  4. Hibernate Query instances are explicitly designated as cacheable before execution.

 

Configuring Hibernate for Caching

Hibernate must be configured to enable caching.  This can be done either through parameters in hibernate.properties or through alternative approaches offered by Spring Framework.

 

Regardless of how they are defined, the following additional properties must be added to enable caching:

 

 

cache.provider_class=org.hibernate.cache.EhCacheProvider

hibernate.cache.use_query_cache=true 
 

 

The following properties are optional, but I recommend that we add them for testing:

 

 

hibernate.generate_statistics=true

hibernate.cache.use_structured_entries=true

show_sql=true 
 

 

In particular, property show_sql=true is helpful for tracing cache behavior.  This setting causes Hibernate to display all SQL statements on the system console.

 

Configuring ehcache.xml

Document ehcache.xml contains caching policies.  For example, it allows you to specify how many instances of a given entity will be retained in cache, the conditions that will cause those instances to be evicted.

 

To obtain optimal caching performance, this file may need to be tuned over time, and its contents may vary based on individual customers’ needs to balance memory utilization and performance.

 

Here is a minimal ehcache.xml file to start:

 

 

<ehcache>

    <defaultCache
            maxElementsInMemory="10000"
            eternal="true"
            overflowToDisk="false"
            memoryStoreEvictionPolicy="FIFO"
            />

</ehcache> 
 

 

This minimal setup will apply the same caching rules to all entities.  Depending on the results of our testing, we may later enhance the ehcache.xml file with one entry for each reference class to be cached to allow granular control 

 

Caching Entities

Model classes can be divided into two broad categories as depicted below:

 

 

  Database ralation

For the purpose of this initial exercise, caching should be limited to reference entities, which are read-only from the standpoint of the transaction being optimized.  All reference entities that are accessed directly or indirectly via method QuestionnarieManager findDisplayQuestion should be designated as cached, particularly the following entities:

 

  • Questionnaire (q_dialog)
  • QuestionSetInNaire (q_dialog_page)
  • QuestionSet (q_page)
  • QuestionInSet (q_page_question)
  • Question (q_question)

 

After reviewing the java logic and the imbedded queries, I believe that this is the complete set of reference entities addressed in method findDisplayQuestion.  If there are any others that have escaped my attention, please designate them as cached as well.

 

Some of the queries in findDisplayQuestion join reference and instance tables.  Instance tables that are joined in this manner include:

 

  • Response (q_response)
  • DisplayFlagRecord (q_displayflag)
  • Dialog (q_dialoginstance)

 

In this initial exercise, we intend to avoid caching instance entities .  We may at a later time decide to enable caching instance entities, but read-write caching will require more research and testing.

 

In order to designate an entity as cached, it is necessary to add annotation @Cache to the model class definition.  Example annotation for entity Questionnaire:

 

@Entity
@Table(name = "q_dialog", uniqueConstraints...)
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class Questionnaire extends QuestionBase implements Serializable 
 

 

Usage CacheConcurrencyStrategy.READ_ONLY should be applied in all cases.  This annotation will cause Hibernate/Ehcache to cache the entity.

 

Caching Collections

Ehcache has the ability to cache association collections, namely those collections that implement 1-to-many or many-to-many associations between entities.  When associations are cached, the Ehcache will bypass the database when an association getter method is called; otherwise, invoking an association get method will trigger in a database SELECT.

 

I recommend that we designate the following associations as cached:

 

  • Questionnaire.getQuestionSetsInNaire()
  • QuestionSet.getQuestionsInSet()
  • QuestionSet.getQuestionsSetInNaires()
  • Question.getQuestionInSets()

 

To enable collection caching, it is necessary to add annotation @Cache to the “getter” method for the association collection.  Example for entity Questionnaire:

 

 

@OneToMany(cascade = CascadeType.ALL, fetch ...)
@OrderBy("sequence asc")
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public Set<QuestionSetInNaire> getQuestionSetsInNaire() 
 

 

This change will cause Ehcache to cache collection Questionnaire questionSetInNaire.

 

Caching Queries

For our initial effort, I recommend that we cache all queries and verify that there are no adverse effects.  In my testing, Query caching made a significant difference.

 

In order for Hibernate to cache a query it is necessary for the Hibernate Query instance to be flagged as cacheable via method Query.setCacheable(true).

 

I’ve learned that Spring Framework’s HibernateTemplate doesn’t enable caching by default.  Some Google searches yielded this solution:

 

 

<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
   <property name="sessionFactory">
      <ref bean="sessionFactory" />
   </property>
   <property name="cacheQueries">
      <value>true</value>
   </property>
</bean> 
 

 

I believe that these specifications will cause the HibernateTemplate class to generate cached Query instances This should effectively enable query caching systemwide. 

 

My knowledge of Spring Framework is limited, so please take this recommendation with a grain of salt.  There are a variety of approaches to solve this problem.  Whichever approach you ultimately use, please verify that Hibernate Query (i.e., QueryImpl) instances are in fact being created with the cacheable property set to true .  You should be able to verify this by single-stepping through the HibernateTemplate with a debugger.

 

Testing

You can verify that caching is taking effect in a number of ways.   When caching is enabled, you should notice a reduction in the number of SQL statements displayed on the server console via Hibernate property show_sql=true .

 

Alternatively, if you have a profiling tool such as YourKit, you can monitor the SQL that is sent to the database.  We’re planning to perform such testing over the wire once the caching enhancements are deployed on the US Dialogs Server.

 

You can also verify that caching is in effect by analyzing data in the performance log:

 

1.  Invoke a test questionnaire using the web client.

2.  Enter any response to the first question on the test questionnaire.

3.  Change the original response to something different.

4.  Reinstate the original response.

 

Check the log file.  If caching has been successfully enabled, there should be a measurable drop in the number of milliseconds required to find the display question (log entry [Finding display question]).  Our most recent tests, show in the range of 250-300 milliseconds.We hope that caching will cause this number to drop significantly.

Trial

1,hibernate.properties

#hibernate.dialect =org.hibernate.dialect.OracleDialect
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
#hibernate.dialect = org.hibernate.dialect.SQLServerDialect
#hibernate.hbm2ddl.auto = update
#hibernate.generate_statistics = false
#hibernate.show_sql =false

hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
hibernate.cache.use_query_cache=true

hibernate.generate_statistics=true
hibernate.show_sql =false
hibernate.cache.use_structured_entries=true
 2,ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" monitoring="autodetect">
    <!--
    Mandatory Default Cache configuration. These settings will be applied to caches
    created programmtically using CacheManager.add(String cacheName).

    The defaultCache has an implicit name "default" which is a reserved cache name.
    -->
    <defaultCache maxElementsInMemory="10000" eternal="true" overflowToDisk="false" memoryStoreEvictionPolicy="FIFO"/>
</ehcache>
 3,model example,Questionnaire.java
@NamedQueries( { @NamedQuery(name = "Questionnaire.findMaxRefId", query = "select max(qn.refId) from Questionnaire qn"),
		@NamedQuery(name = "Questionnaire.findMaxVersionByRefId", query = "select max(qn.version) from Questionnaire qn where qn.refId = :refId") })
@Entity
@Table(name = "q_dialog", uniqueConstraints = { @UniqueConstraint(columnNames = { "ID", "VERSION" }) })
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class Questionnaire extends QuestionBase implements Serializable {
...............................................
}
 4,Query cache,
    Old:
public String getResponseLabel(String value) {
		List<ResponseEntry> lresponseEntity = this.getHibernateTemplate().find("from ResponseEntry as a");
		for (int i = 0; i < lresponseEntity.size(); i++) {
			ResponseEntry r = lresponseEntity.get(i);
			if (r.getValue().equals(value)) {
				return r.getLabel();
			}
		}
		return "";
	}
   New:
public String getResponseLabel(String value) {
		String sql = "from ResponseEntry as a";
		Query query = this.getSession().createQuery(sql);
		query.setCacheable(true);
		List<ResponseEntry> lresponseEntity = query.list();
		for (int i = 0; i < lresponseEntity.size(); i++) {
			ResponseEntry r = lresponseEntity.get(i);
			if (r.getValue().equals(value)) {
				return r.getLabel();
			}
		}
		return "";
	}
 5,Depth Optimization
    Old:
public DisplayFlagRecord findByPageQuestionAndDialogInstance(QuestionInSet pageQuestion, Dialog dialogInstance) {
		String hql = "from DisplayFlagRecord where pageQuestion = :pageQuestion and dialogInstance = :dialogInstance";
		Query query = this.getSession().createQuery(hql);
		query.setCacheable(true);
		
		
		List<DisplayFlagRecord> records = query.setEntity("pageQuestion", pageQuestion).setEntity("dialogInstance", dialogInstance).list();
		if (records != null && records.size()>0) {
			return records.get(0);
		}
		return null;
	}
    New:
public DisplayFlagRecord findByPageQuestionAndDialogInstance(QuestionInSet pageQuestion, Dialog dialogInstance) {
		Iterator listDisplayFlagRecords = dialogInstance.getDisplayFlagRecords().iterator();
		while (listDisplayFlagRecords.hasNext()) {
			DisplayFlagRecord lDisplayFlagRecord = (DisplayFlagRecord) listDisplayFlagRecords.next();
			if (lDisplayFlagRecord.getPageQuestion() == pageQuestion)
				return lDisplayFlagRecord;
		} // Response could not be found:
		return null;
}
private List<Response> findRespose(Long pageInQuestionId, Set aSetResponses,String responseValue) {
		List<Response> lResponses = new ArrayList();
		Iterator listResponses = aSetResponses.iterator();
		while (listResponses.hasNext()) {
			Response lResponse = (Response) listResponses.next();			
			if (lResponse.getQuestion().getId() == pageInQuestionId && lResponse.getValue().equals(responseValue)){
				lResponses.add(lResponse);
			}
				 
		} // Response could not be found:
		return lResponses;
	}
  
If any question I will put in this thread.
分享到:
评论

相关推荐

    springmvc4+spring4+hibernate5.1.3+二级缓存ehcache+fastjson配置

    Ehcache是Hibernate的一个可选二级缓存插件,用于存储数据库查询结果,减少对数据库的直接访问。当相同的数据再次被请求时,可以从缓存中快速获取,提高系统响应速度。在不使用缓存的情况下,可以通过配置关闭。 5...

    Hibernate4二级缓存Ehcache案例

    在这个“Hibernate4二级缓存Ehcache案例”中,我们将深入探讨如何利用Ehcache作为Hibernate的二级缓存提供商,以提升应用性能。 首先,我们需要了解什么是二级缓存。一级缓存是Hibernate Session级别的缓存,每个...

    Hibernate二级缓存(Ehcache)

    【标题】:“Hibernate二级缓存(Ehcache)” 【正文】: Hibernate是一个流行的Java对象关系映射(ORM)框架,它允许开发者用面向对象的方式来处理数据库操作。然而,随着应用规模的扩大,性能优化变得至关重要,...

    hibernate二级缓存包

    在本压缩包“hibernate二级缓存包”中,重点包含的是 Ehcache 这个流行且广泛使用的二级缓存实现。 Ehcache 是一个开源的、高性能的缓存解决方案,它可以被集成到各种Java应用中,包括Hibernate框架。Ehcache 提供...

    Hibernate中二级缓存ehcache缓存案例

    2. **配置hibernate.cfg.xml**:在Hibernate的配置文件中,开启二级缓存支持并指定使用ehcache。添加以下配置: ```xml &lt;property name="hibernate.cache.use_second_level_cache"&gt;true &lt;property name="...

    hibernate二级缓存实例

    在这个"hibernate二级缓存实例"中,我们将深入探讨二级缓存的原理、配置以及在实际项目中的应用。 首先,我们需要了解一级缓存和二级缓存的区别。一级缓存是Session级别的,每个Session都有自己的一级缓存,用于...

    Hibernate二级缓存

    Hibernate二级缓存是一种提高应用程序性能的技术,它将数据存储在SessionFactory级别的缓存中,使得数据可以在不同的Session之间共享。这与一级缓存(Session级别)不同,一级缓存仅存在于单个Session生命周期内,当...

    hibernate一级缓存和二级缓存的区别与联系

    二级缓存可以是内存中的缓存,也可以扩展到硬盘,例如使用第三方缓存提供商(如 EhCache 或者 Infinispan)。二级缓存中存储的是对象的集合数据,而不是单个对象实例,这样可以更高效地处理大量数据。二级缓存可以...

    hibernate二级缓存示例源码

    **hibernate二级缓存详解** Hibernate作为Java领域中广泛使用的对象关系映射(ORM)框架,极大地简化了数据库操作。然而,在处理大量数据时,性能优化显得尤为重要,这就是二级缓存的作用。本文将深入探讨Hibernate...

    day37 05-HIbernate二级缓存:一级缓存更新同步到二级缓存及二级缓存配置文件

    本篇文章将深入探讨Hibernate的二级缓存机制,以及如何进行一级缓存与二级缓存的同步,同时还会介绍二级缓存的配置文件设置。 一级缓存是Hibernate默认提供的缓存,每个SessionFactory实例都有一个一级缓存。当对象...

    hibernate 二级缓存详解

    在Hibernate中,二级缓存可以使用不同的提供商,例如Ehcache和OSCache。配置Ehcache作为二级缓存提供商,需要在Hibernate的配置文件中设置`hibernate.cache.provider_class`为`...

    hibernate一级缓存、二级缓存和查询缓存

    二级缓存的实现需要依赖第三方缓存提供者,如EhCache、Infinispan等。二级缓存的主要特点包括: - **跨事务共享**:与一级缓存不同,二级缓存可以在多个事务之间共享数据,提高了数据的复用性。 - **配置复杂**:二...

    为Spring集成的Hibernate配置二级缓存

    2. **配置Hibernate**:在Hibernate的配置文件`hibernate.cfg.xml`中启用二级缓存并指定缓存提供商。以下是一个使用Ehcache的示例: ```xml &lt;property name="hibernate.cache.use_second_level_cache"&gt;true ...

    Spring集成的Hibernate配置二级缓存

    以EhCache为例,我们需要在项目中引入ehcache-core或ehcache的依赖,并在Hibernate配置文件(hibernate.cfg.xml或persistence.xml)中启用二级缓存,添加如下配置: ```xml &lt;property name="hibernate.cache.use_...

    hibernate二级缓存所需要的 jar包

    本篇将详细介绍Hibernate二级缓存的概念、作用以及所需jar包的作用。 一、Hibernate二级缓存概念 Hibernate的一级缓存是指Session级别的缓存,每个Session内部都有一个一级缓存,用于存储实体对象,当Session关闭时...

    Hibernate 二级缓存 总结整理

    2. **缓存提供者(Cache Provider)**:Hibernate通过缓存提供者来实现二级缓存,常见的有Ehcache、Infinispan等。缓存提供者负责存储和检索数据,以及缓存的同步和过期策略。 3. **缓存策略(Cache Strategy)**:...

    hibernate二级缓存java包下载

    二级缓存是 Hibernate 缓存策略的一部分,它在应用程序的多个会话之间共享数据,进一步优化了数据库访问效率。 二级缓存分为以下关键知识点: 1. **一级缓存与二级缓存的区别**: - 一级缓存:每个 Hibernate ...

    springboot+jpa(hibernate配置redis为二级缓存) springboot2.1.4

    通过以上步骤,我们就成功地在Spring Boot 2.1.4.RELEASE项目中配置了使用Redis作为Hibernate二级缓存的环境。这将显著提升数据库查询效率,减少对数据库的压力,尤其在高并发场景下,效果尤为明显。记得在实际生产...

    Hibernate一级缓存和二级缓存

    **二、Hibernate二级缓存** 二级缓存是SessionFactory级别的,跨越了多个Session,可以被多个线程共享。它通常由第三方插件如EhCache、Infinispan等提供。二级缓存分为以下几种类型: 1. **集合缓存**:用于存储...

Global site tag (gtag.js) - Google Analytics