Hibernate is a library that maps database tables to Java objects. Is performance problems arise it's very easy to add database caching for application using Hibernate (just few options in config file). Hibernate is shipped with EHCache, default cache implementation. It works well and is easy to setup.
Sometimes you have to use another caching library that has no direct support for Hibernate. Here the Hibernate API comes into play. I'll show you how to plug Websphere's DistributedMap into Hibernate.
First: you have to map get/put requests into desired API. org.hibernate.cache.Cache is an interface that must be subclassed for this task. This class instance is created by Hibernate for every entity that will be cached (distinguished by regionName).
public class WebsphereCacheImpl implements Cache { private DistributedMap map; private String regionName; public WebsphereCacheImpl(DistributedMap map, String regionName) { this.map = map; this.regionName = regionName; } public void clear() throws CacheException { map.clear(); } public Object get(Object key) throws CacheException { return map.get(getMapKey(key)); } public String getRegionName() { return regionName; } public void put(Object key, Object value) throws CacheException { map.put(getMapKey(key), value); } public Object read(Object key) throws CacheException { return map.get(getMapKey(key)); } public void remove(Object key) throws CacheException { map.remove(getMapKey(key)); } public void update(Object key, Object value) throws CacheException { map.put(getMapKey(key), value); } private String getMapKey(Object key) { return regionName + "." + key; } (...) }
Then you have to prepare factory for such obejcts:
public class WebsphereCacheProviderImpl implements CacheProvider { private DistributedMap distributedMap; public WebsphereCacheProviderImpl() throws NamingException { InitialContext ic = new InitialContext(); distributedMap = (DistributedMap) ic.lookup("services/cache/cache1"); } public Cache buildCache(String regionName, Properties arg1) throws CacheException { return new WebsphereCacheImpl(distributedMap, regionName); } public boolean isMinimalPutsEnabledByDefault() { return false; } public long nextTimestamp() { return new Date().getTime(); } public void start(Properties arg0) throws CacheException { } public void stop() { } }
Then new factory class must be registered in Hibernate configuration:
<property name="hibernate.cache.use_second_level_cache">true</property> <property name="hibernate.cache.use_query_cache">true</property> <property name="cache.provider_class">com.company.project.cache.WebsphereCacheProviderImpl</property>
And voila!