Spring Ehcache integration (Second-level caching in Hibernate)
Integrating Ehcache with Spring-based applications is actually fairly easy. Let's look at this integration with a sample BuddyManagement application.
Integrating Ehcache with Spring-based applications is actually fairly easy. Let's look at this integration with a sample BuddyManagement application.
We have a BuddyManagementSample application. The application specifies that there are some groups and these groups have some contacts (or buddies) stored in them. We have specified two operations in this application. One is fetching the count of the contacts in a group and the other is fetching the list of the contacts in a group. We have the below files in the application:
- Entity classes: Contact.java and Groups.java
- DAO classes: ContactsDAOImpl.java
- Service Impl class: ContactsServiceFacadeImpl.java
- Utility class: BuddyMgmtUtils.java
- Configuration xmls: Ehcache.xml , applicationContext.xml
- Persistence Unit xml: persistence.xml
- Libraries: Ehcache-1.5.0.jar and supporting jar backport-util-concurrent-3.0.jar
- Other supporting libraries for the spring framework and remaining java functionalities
Below is the step-by-step process of integrating Ehcache with our application:
1. The Ehcache implementation requires two of its jars to be added in the code:
Ehcache-1.5.0.jar
Download location: http://mirrors.ibiblio.org/pub/mirrors/maven2/net/sf/Ehcache/Ehcache/1.5.0/Ehcache-1.5.0.jar
The jar Ehcache-1.5.0 is dependent on backport-util-concurrent-3.0.jar. So we need the below jar as well.
backport-util-concurrent-3.0.jar
Download location: http://mirrors.ibiblio.org/pub/mirrors/maven/backport-util-concurrent/jars/backport-util-concurrent-3.0.jar
Below is a snapshot of the project BuddyManagement application in Netbeans, where the jars are to be added in the Libraries.
2. Include caching annotation in all entities:
The caching annotation is to be included in all entities that are going to be cached.
In Master Data entities (Read only entities) this annotation can be used:
Eg. @Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
In transactional entities (entities which require updates) the below annotation can be used:
Eg.@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
Below is the code snippet for the Groups.java entity where we have added the @Cache annotation for caching this entity. Similar kind of annotation has to be added in other entities as well which need to be cached using the Ehcache.
3. Include caching annotation in all the data access object (DAO) classes extending JpaDaoSupport:
In DAO classes, caching can be introduced for the hibernate template query and this query caching is done using the property ‘setHint’.
Eg. The property has to be used as:
query.setHint("org.hibernate.cacheable", true);
The ContactsDAOImpl.java class of the BuddyManagementSample application has a method fetchBuddyCountForGroup(). This method fetches the count of the buddies in a particular group of the user. We have a query ‘queryBuddyCountForUserId’ which fetches the count of the buddies in the group. This query results can be fetched using the below property of the query
queryBuddyCountForUserId.setHint(("org.hibernate.cacheable", true);
Below is the sample piece of DAO code where we have introduced query caching.
4. Ehcache.xml:
After including the appropriate jars and making the required changes in the code for the Ehcache implementation, we need to configure Hibernate to use the second level cache.
The configurations needed for all entities to be cached and also the caching properties that need to be configured are placed in an xml file named ‘Ehcache.xml’. The Ehcache.xml is used for all the configurations of Ehcache regions, and is placed directly in the root of the class path.
The caching properties that can be configured in the Ehcache.xml are:
<defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="1200" timeToLiveSeconds="1200" overflowToDisk="true" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"/>
You can also specify the ‘maxElementsInMemory’ per entity listed in the xml.
Eg. <cache name="com.demo.entity.CommentsOnContent"
maxElementsInMemory="10000"/>
The various attributes used in the Ehcache.xml are described below:
- maxInMemory- maximum number of objects that will be created in memory
- eternal -whether elements are eternal. If eternal, timeouts are ignored and the element is never expired.
- timeToIdleSeconds - sets the time to idle for an element before it expires. A value of 0 means that an element can idle indefinitely.
- timeToLiveSecond -sets the time to live for an element before it expires.
- overflowToDisk - sets whether elements can overflow to disk when the in-memory cache has reached the maxInMemory limit.
The Ehcache.xml of the BuddyManagement application is shown above. Here we are caching two of its entities- Contact and Groups. The entities will be cached and stored in the temp dir of the server. The other properties are also configured as required.
5. Persistence.xml:
The persistence.xml is the configuration file required to integrate Hibernate with the application. It is generated when we create the first new entity and there is no persistence unit already present in the application. The persistence unit is required to enable the entity class to persist.
Persistence.xml contains the entities that are expected to persist. To enable second level caching, we also need to ensure persistence for the entries of the required cache provider and the configuration resource.
Below are the property tags that need to be added in persistence.xml:
<properties>
<property name="hibernate.cache.provider_class"
value="net.sf.Ehcache.hibernate.SingletonEhcacheProvider"/>
<property name="net.sf.Ehcache.configurationResourceName"
value="/Ehcache.xml"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.generate_statistics" value="true"/>
</properties>
For any persistence.xml file, ‘hibernate.cache.provider_class’ should be specific to the provider to be used. Here we are mentioning the provider for Ehcache. Also, the "hibernate.cache.use_query_cache" property is required to be set to "true." As already mentioned above, the Query cache should be used in conjunction with the second level cache.
The persistence.xml used in the BuddyManagement application is shown below. The entities Groups and Contacts are to be persisted and they are specified in the xml.