We needed to use Tangosol's Coherence cache product with Hibernate, so I used the online documentation at:
http://www.hibernate.org/132.html
as my starting point. However, we also wanted to actually see how our cache was doing, and be able to empty our cache selectively if needed, so I added a few modifications, which I figured would be useful for others going a similar route, so I am posting it here.
Actually the modifications enable you to view your cache in a fairly cache-agnostic way, so a similar strategy could be used for other cache provider and cache implementations as well.
I made the following changes to the CoherenceCacheProvider implementation to retain a reference to the CoherenceCache objects it returns from buildCache().
public class CoherenceCacheProvider implements CacheProvider {
// NamedCache cache;
private static Map<String,CoherenceCache> cacheMap = new HashMap<String,CoherenceCache>();
public Cache buildCache(String regionName, Properties properties) throws CacheException {
//cache = CacheFactory.getCache(regionName);
String cacheName = "hibernate-" + regionName;
CoherenceCache cache = CacheFactory.getCache(CacheFactory.getCache(cacheName));
cacheMap.put(cacheName, cache);
//return new CoherenceCache(cache);
return cache;
}
// method implementations remain unchanged
// ...
// additional static methods to return all cache names or a cache by name
public Set<String> getCacheNames() {
return cacheMap.keySet();
}
public CoherenceCache getCacheByName(String cacheName) {
return cacheMap.get(cacheName);
}
}
and we add a CacheStatistics implementation as a member variable into the CoherenceCache implementation, which is updated every time we do a get or put, so we can calculate things like cache hit ratios. I just show the changes to the Cache.get() method as an example.
public class CoherenceCache implements Cache {
private NamedCache cache;
// also add this
private CacheStatistics statistics;
public CoherenceCache(NamedCache cache) {
this.cache = cache;
// and add this
this.statistics = new CoherenceCacheStatistics();
}
public Object get(Object key) throws CacheException {
long start = System.currentTimeMillis();
Object value = cache.get(key);
long end = System.currentTimeMillis();
statistics.addGet(end - start);
return value;
}
// and so on for the other methods. The idea here is to calculate the time elapsed
// for getting something, so we can pass it to the CoherenceCacheStatistics.addXXX(long millis)
// method
}
and the CacheStatistics implememtation is as follows. I just show the addGet() method and the corresponding getTotalGets(), getTotalGetMillis() and getAverageGetMillis() as an example. The put series of methods are similar and the getHitProbability() method is just a computation of the (get - put)/get.
public class CoherenceCacheStatistics implements CacheStatistics {
private long gets;
private long totalGetMillis;
public void addGet(long millisToGet) {
this.gets++;
this.totalGetMillis += millisToGet;
}
public long getTotalGets() {
return gets;
}
public long getTotalGetsMillis() {
return totalGetMillis;
}
public double getAverageGetMillis() {
return (gets == 0 ? 0 : (totalGetMillis / gets));
}
}
Not sure if the CacheStatistics API is part of the Caching JSR 107, but Tangosol provides an interface which I used to base the impl on.
Adding the two static methods in CoherenceCacheProvider and exposing the CacheStatistics in CoherenceCache allows us to build a JSP page which can list all hibernate caches, list its contents, and allow us to selectively remove an entry from a cache, clear a cache, or clear all hibernate caches.
Before I did this, I was trying to use Tangosol's API to get this list and there were some things I could not figure out how to do. It strikes me that using this approach, we could build cache explorer interfaces for any other cache that can plug into hibernate.
HTH
Sujit