Sunday, March 19, 2017

Difference between First and Second Level Cache in Hibernate

If you have used Hibernate in past then you know that one of the strongest points of Hibernate framework is caching, which can drastically improve the performance of Java application's persistence layer if configured and used correctly. Hibernate provides caching at many levels e.g. first level cache at Session level, second level cache at the SessionFactory level, and query cache to cache frequently executed SQL queries. The first level cache minimizes database access for the same object. For example, if you call the get() method to access Employee object with id = 1 from one session, it will go the database and load the object into memory, but it will also cache the object in the first level cache.

When you will call the get() method again for the same object from the same session, even after doing some updates on the object, it will return the object from the cache without accessing the database. You can confirm this from Hibernate's log file by observing how many queries are executed. This is also one of the frequently asked Hibernate Interview Questions, so it will not only help to improve the performance of your Java application but also help you to do well on your next interview.

This session level cache greatly improves the performance of Java application by minimizing database roundtrips and executing less number of queries. For example, if an object is modified several times within the same transaction, then Hibernate will only generate one SQL UPDATE statement at the end of the transaction, containing all the modification.


But, since this cache is associated with the Session object, which is a short-lived object in Hibernate, as soon as you close the session, all the information held in the cache is lost. So, if you try to load the same object using the get() method, Hibernate will go to the database again and fetch the record.

This poses significant performance challenge in an application where multiple sessions are used, but you don't need to worry. Hibernate provides another application level cache, known as second level cache, which can be shared among multiple sessions. This means a request for the same object will not go to the database even if it is executed from multiple session, provided object is present in the second level cache.

The second level cache is maintained at the SessionFactory level, which is used to open sessions, hence every session is linked to SessionFactory. This cache is opposite to first level cache which is by default enabled in Hibernate, this one is by default disabled and you need to configure the second level cache in Hibernate configuration file to enable it.


The second level cache is provided with the help of caching providers e.g. EhCache and OSCache. If you look at the cache package in Hibernate, you can see the implementation of Caching related interfaces by these providers. Depending upon which cache you want to use, you can configure them in the Hibernate Configuration file.

Once configured, every request for an object will go to the second level cache if it is not found in the first level cache. It won't hit the database without consulting second level cache, which means improved performance.

It's very important for a Java and Hibernate developer to know about Caching in Hibernate. It's not just important from Interview point of view but also from the application development and performance improvement point of view. You will often face performance related challenges in a real world application which contain millions of records, by correctly configuring Hibernate sessions and writing code which make use of caching, your Java application can float above water even in the case of a significant load. If you want to learn more about Hibernate performance, I suggest reading  I suggest reading High-Performance Java Persistence by Vlad Mihalcea, one of the best and up-to-date resources on hibernate performance at the moment.

What is First Level and Second Level Cache in Hibernate



Difference between First and Second Level Cache in Hibernate

Now that we know what is first level and second level cache in Hibernate, let's revise some key differences between them from interview point of view.

Scope
First level cache is associated with Session Object, while the Second level cache is associated with the SessionFactory object. This means first level cache's scope is limited to session level while second level cache's scope is at the application level. Since Session object is created on demand from the SessionFactory and it's destroyed once the session is closed, the same query if run from two different sessions will hit the database twice if the second level cache is not configured. On the other hand, second level cache remains available throughout the application's life-cycle.


Configuration
First level cache is by default enabled in Hibernate, while the second level cache is optional. If you need it then you need to explicitly enable the second level cache on Hibernate configuration file i.e. the hibernate.cfg.xml file.

You can use the hibernate.cache.provider_class and hibernate.cache.use_second_level_cache properties to enable the second level cache in Hibernate. The first one is the name of the class which implements Second level cache and could be different, depending upon which cache you use e.g. EhCache or OSCache.

By default,  hibernate.cache.provider_class is set to org.hibernate.cache.NoCacheProvider class, which means the second level cache is disabled. You can enable it by setting something like org.hibernate.cache.EhCacheProvider if you want to use EhCache as the second level cache.

Here is a sample configuration to configure Second level cache with EhCache:

<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>

Don't forget to include hibernate-ehcache.jar into your classpath. This class comes from that JAR. You can also see Java Persistence with Hibernate, 2nd edition to learn more about other configuration options available to second level cache.

How to configure Second Level Cache in Hibernate



Availability
First level cache is available only until the session is open, once the session is closed, the first level cache is destroyed. On the other hand, second level cache is available through the application's life-cycle, it is only destroyed and recreated when you restart your application.


Order
If an entity or object is loaded by calling the get() method then Hibernate first checked the first level cache, if it doesn't found the object then it goes to the second level cache if configured. If the object is not found then it finally goes to the database and returns the object, if there is no corresponding row in the table then it return null. When an object is loaded from the database is put on both second level and first level cache, so that other session who request the same object can now get it from the second level cache.

In case if the object is not found in the first level cache but found in the second level cache because some other sessions have loaded the object before then it is not only returned from first level cache but also cached at first level cache, so that next time if your code request the same object, it should be returned from 1st level cache rather than going to the 2nd level cache.

Difference between First and Second Level Cache in Hibernate


In general. When an object is pass to save(), update(), or saveOrUpdate() method and retrieved by load(), get(), list(), iterate(), or scroll() method, that object is added to the internal cache of the Session and when the flush() is subsequently called, the state of the object is sychronized with the database.

Second level cache can also be configured on a per-class and per-collection basis, which means it can cache a class or a collection. You can use class-cache and colleection-cache elements in hibernate.cfg.xml to specify which class or collection to cache at 2nd level cache. You should remember that second level cache by default doesn't cache any entitty until you configure it.

You can also use JPA Annoation @Cacheable to specify which entity is cacheable. and Hibernate annoation @Cache to specify caching startegy e.g. CacheConcurrencyStrategies like READ_WRITE or READ_ONLY to tell Hibernate how the second level cache should behave.


That's all about difference between first and second level cache in Hibernate. It's not just an ORM tool, hibernate is much more than that and in-built caching is one of the biggest benefit of using Hibernate to implement psersistence of DAO layer in Hibernate. By correctly configuring second level cache and writing code to leverage both first level and second level cache in Hibernate, you can get improved performance in Java application.

Further Learning
Introduction To Hibernate
Spring with JPA and Hibernate
Hibernate Performance tuning

For curious developers, who want to go deeper and understand other caching options and performance improvement tricks in Hibernate, I suggest reading High-Performance Java Persistence by Vlad Mihalcea, he is an autority in Hibernate world and has shared some neat information related to performance of Hibernate and JPA in his book.

Difference between First Level and Second Level Cache in Hibernate

Other Hibernate Articles and Interview Questions you may like
  • Difference between First and Second level cache in Hibernate? (answer)
  • Difference between get() and load() method in Hibernate? (answer)
  • 5 Spring and Hibernate Training Courses for Java developers (list)
  • 2 Books to Learn Hibernate in 2017 (books)
  • 5 Books to Learn Spring Framework in 2017 (books)
  • Why Hibernate Entity class should not be final in Java? (answer)
  • 10 Hibernate Questions from Java Interviews (list)

Thanks for reading this article, if you like this article and interview question then please share with your friends and colleagues. If you have any question or feedback then please drop a comment.

4 comments :

Sanjay Jain said...

Nice introductory information about chacheing in hibernate. Thanks

Unknown said...

I've worked with hibernate for years but in my current position we don't use Spring. So we have to commit transactions through the hibernate api, which flushes the session. If we used Spring AOP I think we do not need to flush the sessions as often. Is this correct?

Anonymous said...

How does the cache behave when there are multiple apps writing to the db? Will it know to invalidate ab entity if it was updated by other service?

Javin Paul said...

@Anonymous, if multiple application is writing into the DB then second level cache may not be accurate. The whole idea is that any DB write will happen via hiberante, but if that is not the case and you are updating data using SQL scripts in backend, then values cached at second level cache will become stale.

Post a Comment