Dude, Where’s My Hibernate Second-Level Ehcache Hit?

This post, in which we assume you use Spring, shows how to confirm that your hibernate second-level cache is working, which is one of the first things you would want to do after you have completed the necessary configuration.

Trying to use ehcache DEBUG log output to confirm your cache is working may end up wasting your time, rather use the approach documented here.

Step 1: Tell Hibernate to collect statistics in your test spring context

The new line you will include is hibernate.generate_statistics line shown below.

<prop key="hibernate.query.startup_check">false</prop>
<prop key="hibernate.hbm2ddl.auto">create-drop</prop>
<!-- Enable the second-level cache  -->
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.EhCacheRegionFactory</prop>
<prop key="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</prop>
<prop key="hibernate.generate_statistics">true</prop>

Step 2: Create a JUnit test case where you expect a cache hit and check for the hit

You would have, in your ehcache.xml config file, created a cache for each DBO (i.e. JPA @Entity) that you want to have cached. So, now simply create a unit test where you create a set of objects that should be cached, then fetch them, from the cache (hopefully).

Include the following in your Test class, if its not there already:

@Autowired
private ApplicationContext applicationContext;

Now write a test case such as the following:

@Test
public void testGenerateStuff() {
   int stuffNumber = databaseHelper.generateStuff();
   Stuff stuff = databaseHelper.getStuff(stuffNumber);
   // Pertinent lines ...
   EntityManagerFactoryInfo entityManagerFactoryInfo = (EntityManagerFactoryInfo) applicationContext.getBean("entityManagerFactory");
   EntityManagerFactory emf = entityManagerFactoryInfo.getNativeEntityManagerFactory();
   EntityManagerFactoryImpl emfImp = (EntityManagerFactoryImpl)emf;
   Statistics stats = emfImp.getSessionFactory().getStatistics();
   printStats(stats);
   assertTrue(stats.getSecondLevelCacheHitCount() > 0);
}

public static void printStats(Statistics stats) {
   System.out.println(stats.toString());
   System.out.println("Second Level Cache Put Count ==> " + stats.getSecondLevelCachePutCount());
   System.out.println("Second Level Cache Hit Count ==> " + stats.getSecondLevelCacheHitCount());
   System.out.println("Second Level Cache Miss Count ==> " + stats.getSecondLevelCacheMissCount());
}
Advertisements

Spring JUnit Ehcache: Hibernate Second-Level Caching: Another unnamed CacheManager already exists in the same VM.

If you are quite simply trying to introduce Hibernate second level caching into your Spring based application using Ehcache, you may end up banging your head against this wall when running your Junit tests: Another unnamed CacheManager already exists in the same VM.

Even worse, you may get sidetracked by posts such as this one which has to do with Spring 3.1 caching.

It may be that you have decided to included a version of Ehcache > 2.5, if that is the case, then before wasting more time on this, like I did, downgrade to Ehcache 2.4.7:

BEFORE

<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.5.2</version>
</dependency>

AFTER

<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.4.7</version>
</dependency>

One more tip, to get started with you ehcache.xml config, copy the defaults in ehcache-failsafe.xml and go from there, dump the file in your resources folder in your project and consult the Ehcache Hibernate Second-Level Cache Documentation.