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 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
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:
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.
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.
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 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
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>
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.
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.
No comments:
Post a Comment