JavaEnterprise JavaJPA 2.0 Cache Vs. Hibernate Cache: Differences in Approach

JPA 2.0 Cache Vs. Hibernate Cache: Differences in Approach

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Hibernate and the Java Persistence API (JPA) are two leading technologies for managing the persistence and object relational mapping (ORM) of Java EE and Java SE applications. Hibernate‘s open source, lightweight and transparent framework simplified ORM by mapping database tables to persistent classes in XML files and generating the SQL script at runtime. JPA then made XML-based ORM much simpler by replacing the traditional XML mapping files with metadata annotation, enabling developers to persist the state of their Java applications to relational databases through metadata.

JPA Level 2 Cache

Level 2 cache was introduced in the JPA 2.0 release. JPA provides a Cache API for basic cache operations, while level 2 cache shares the state of an entity — which is accessed with the help of the entity manager factory — across various persistence contexts. Level 2 cache underlies the persistence context, which is highly transparent to the application. Figure 2 shows a diagram of JPA level 2 cache.

Level 2 cache is used typically to increase performance. However, using cache may lead to “stale” data, so you may choose to disable caching. To enable or disable caching on a class, you can use the @Cacheable annotation.

public interface Cache {/*** Whether the cache contains data for the given entity.*/public boolean contains(Class cls, Object primaryKey);/*** Remove the data for the given entity from the cache.*/public void evict(Class cls, Object primaryKey);/*** Remove the data for entities of the specified class (and its* subclasses) from the cache.*/public void evict(Class cls);/*** Clear the cache.*/public void evictAll();}

The Cache API provided by JPA 2.0 also allows you to refresh or bypass caching by using query hints, which are defined with two enums: CacheRetrieveMode and CacheStoreMode. You use CacheRetrieveMode to read entity data from the cache (the default) by specifying this enum when the data is retrieved as follows:

javax.persistence.cache.retrieveMode: CacheRetrieveMode

To bypass the cache, you would get data directly from the database.

You use CacheStoreMode to insert/update entity data into cache when the data is read from a database and committed into a database (the default) by specifying when the data is committed to the database as follows:

javax.persistence.cache.storeMode: CacheStoreMode

CacheStoreMode does not force a refresh of already cached items when reading from the database.

To bypass the cache, don’t insert into cache. To refresh the cache, insert/update entity data into cache when the data is read from the database and committed into the database. This will force a refresh of cache for items read from database.

When Level 2 cache is enabled, the persistence provider will look for the entities in the persistence context first. If it does not find them there, the persistence provider will look in the Level 2 cache next instead of sending a query to the database.

Pros, Cons and Best Uses of JPA Level 2 Cache

Here are the pros and cons of JPA Level 2 cache:

  • Pros:
    • Avoids database access for already loaded entities
    • Faster for reading frequently accessed unmodified entities
  • Cons:
    • Memory consumption for large amount of objects
    • Stale data for updated objects
    • Concurrency for write (optimistic lock exception or pessimistic lock)
    • Bad scalability for frequent or concurrently updated entities

Level 2 cache is best used for entities that are frequently read, infrequently modified, and not critical if stale. You can use the query cache technique to cache queries that are executed often with the same parameters for tables that are rarely modified.

Caching in Hibernate

Hibernate also maintains two levels of cache: first-level and second-level cache. The first-level cache is responsible for storing the results within a particular session instance, while the second-level cache is associated with the SessionFactory instance.

Hibernate uses first-level cache by default to store the objects for every transaction. Hibernate’s second-level cache, which is supported by the SessionFactory, enables the objects to be accessed at the application level, thereby reducing the number of database transactions required for accessing an object. Hibernate achieves caching by storing the individual property values of the instance rather than storing the objects themselves.

Hibernate 3.0 supports the following four open source caching implementations for second-level cache:

  • EHCache (org.hibernate.cache.EhCacheProvider) — Default
  • OSCache (org.hibernate.cache.OSCacheProvider)
  • SwarmCache (org.hibernate.cache.SwarmCacheProvider)
  • JBoss TreeCache (org.hibernate.cache.TreeCacheProvider)

The second-level cache can be enabled or disabled by setting the property hibernate.cache.use_second_level_cache to true (the default for classes that specify <cache> mapping) or false, respectively. Here is a true setting:

<property name="hibernate.cache.use_second_level_cache">true</property>

You can choose which implementation to use for an application by setting the hibernate.cache.provider_class property in the hibernate.cfg.xml file as follows.

<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

You also can enable caching at the class level or the collection level by setting the <cache> element in the mapping file as follows:

<cache usage="read-only" region="regionName" include="all"/>

Here’s a breakdown of the elements in the above code:

  • Usage specifies the caching strategy and can take other values such as transactional, read-write and nonstrict-read-write.
  • Region is an optional attribute that specifies the second-level cache region. By default it is the name of the class/collection.
  • Include is an optional attribute that takes the all value by default. If the value non-lazy is set to include then entities having lazy=true cannot be cached.

You can also enable caching by setting the <class-cache> and <collection-cache> elements in the hibernate.cfg.xml file, after which you would configure the cache rule for classes for which you want cache to be enabled in a separate EhCache configuration file (ehcache.xml) and place it in the root directory of the project.

You can also cache queries that are executed very frequently with the same set of parameters by using query cache. Query cache is set to false by default and you can enable it by adding the following property in the hibernate.cfg.xml file:

<property name="hibernate.cache.use_query_cache">true</property>

This query adds StandardQueryCache and UpdateTimestampsCache regions, which hold the query cached results and the time stamps of the most recent update to the table, respectively. The query results can be cached for a particular query by calling setCacheable(true) on the query instance.

Hibernate 3.5 Caching

The Hibernate caching strategies remain the same in version 3.5, but certain additional cache providers such as JBoss Cache 2, JBoss Cache 1.x (part of Hibernate 3.2) and Hashtable (not for production) have been added.

The other major advancement in Hibernate 3.5 is the addition of Infinispan as another standard for second-level cache. Infinispan is an open source, scalable data grid platform that exposes a JCache (JSR-107)-compatible cache interface. Infinispan provides a much higher degree of concurrency because it uses a specialized data structure, provides a massive heap capability and is not tied just to Java. It also supports PHP, Python, Ruby etc.

Conclusion

In this article we compared caching in JPA 2.0 with the caching in Hibernate. By introducing new caching features and promoting standardization, JPA 2.0 has made many tasks easier for developers. However, Hibernate is far ahead in many aspects because all its features have been supported for much longer.

Acknowledgements

The authors would like to sincerely thank Mr. Subrahmanya SV (VP, ECOM Research Group, E&R) for his ideas, guidance, support and constant encouragement and Ms. Mahalakshmi for kindly reviewing this article and providing valuable comments.

About the Authors

Sangeetha S. works as a Senior Technical Architect at the E-Commerce Research Labs at Infosys Technologies. She has over 10 years of experience in design and development of Java and Java EE applications. She has co-authored a book on ‘J2EE Architecture’ and also has written articles for online Java publications.

Nitin KL works at the E-Commerce Research Labs at Infosys Technologies. He is involved in design and development of Java EE applications using Hibernate, iBATIS, and JPA.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories