Sunday 1 July 2012

Hibernate Caching

Caching is widely used for optimizing database applications. A cache is designed to reduce traffic between your application and the database by conserving data already loaded from the database. Database access is necessary only when retrieving data that is not currently available in the cache. The application may need to empty (invalidate) the cache from time to time if the database is updated or modified in some way, because it has no way of knowing whether the cache is up to date.

When we use hibernate as persistence layer framework, we can cache objects using first level cache (associated with Session object) and second level cache (associated with SessionFactory object). The first level cache is used on transaction basis. Hibernate caches objects used in transaction as it may be read or updated multiple times. Whereas second level cache holds the object across multiple transactions. These objects are available to the whole application, not just to the user running the query. This way, each time a query returns an object that is already loaded in the cache, one or more database transactions potentially are avoided.

Also caching mechanism depends on your access strategies. There are four caching strategies:
  • Read-only: This strategy is useful for data that is read frequently but never updated. This is by far the simplest and best-performing cache strategy.
  • Read/write: Read/write caches may be appropriate if your data needs to be updated. They carry more overhead than read-only caches. In non-JTA environments, each transaction should be completed when Session.close() or Session.disconnect() is called.
  • Nonstrict read/write: This strategy does not guarantee that two transactions won't simultaneously modify the same data. Therefore, it may be most appropriate for data that is read often but only occasionally modified.
  • Transactional: This is a fully transactional cache that may be used only in a JTA environment.
 Hibernate supports the following open-source cache implementations out-of-the-box:
  • EHCache (org.hibernate.cache.EhCacheProvider)
  • OSCache (org.hibernate.cache.OSCacheProvider)
  • SwarmCache (org.hibernate.cache.SwarmCacheProvider)
  • JBoss TreeCache (org.hibernate.cache.TreeCacheProvider)

Cache
Read
only
Nonstrict Read/write
Read/write
Transactional
Clustering
Suitable for
EHCache
Yes
Yes
Yes
No
No
lightweight, and easy-to-use
OSCache
Yes
Yes
Yes
No
Basic (JavaGroups or JMS)
JSP pages or arbitrary objects
SwarmCache
Yes
Yes
No
No
Based on JavaGroups
many more read operations than write operations
JBoss TreeCache
Yes
No
No
Yes
Powerful
transaction-capable caching architecture

To activate second-level caching, you need to define the hibernate.cache.provider_class property in the hibernate.cfg.xml file as follows:

<hibernate-configuration>
<session-factory>
...
<property name="hibernate.cache.provider_class">
org.hibernate.cache.EHCacheProvider
</property>
...
</session-factory>
</hibernate-configuration>
 
Second-level caching can be activated in one of the two following ways:
  1. On a class-by-class basis in the *.hbm.xml file, using the cache attribute:
    
    <hibernate-mapping package="com.avid.hibernate.caching">
    <class name="Currency" table="tbl_currency" dynamic-update="true">
    <meta attribute="implement-equals">true</meta>
    <cache usage="read-only"/>
    ...
    </class>
    </hibernate-mapping>
    
  2.  You can store all cache information in the hibernate.cfg.xml file, using the class-cache  attribute:
    
    <hibernate-configuration>
    <session-factory>
    ...
    <property name="hibernate.cache.provider_class">org.hibernate.cache.EHCacheProvider</property>
    ...
    <class-cache class="com.avid.hibernate.caching.Currency" usage="read-only" />
    </session-factory>
    </hibernate-configuration>
    
 
Next, you need to configure the cache rules for this class. Let's take an example of EHCache, but remember that each cache implementation is different. EHCache needs a configuration file (generally called ehcache.xml) at the classpath root.

<ehcache>
 <diskStore path="java.io.tmpdir"/>
 <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120"
      timeToLiveSeconds="120" overflowToDisk="true" diskPersistent="false"
      diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" />
 
  <cache name="com.avid.hibernate.caching.Currency" eternal="true" overflowToDisk="false" />
 </ehcache>

The beauty of hibernate lies in the declarative style. You do all these configurations and are ready to run. No need to change even a single line of code and performance is improved.

0 comments:

Post a Comment