How is the cache implemented in Hibernate?
In this article, I’m going to familiarize you with the concept of Hibernate in Java and the use of cache in it. In previous java programming
courses, you have become familiar with the basic concepts related to Java and now I will bring you newer concepts in this article.
Caching in Hibernate
One of the other features offered by Hibernate is Caching support. With this feature, the entry of requests into the database decreases and the efficiency of the program increases. Cache is placed between the application and the database and reduces frequent references to the database as much as possible. In short, it can be said that cache in Hibernate increases the performance of the program by reducing the entry of requests into the database.
Cache in hibernate second level layer
In the figure below, you can see that cache in Hibernate is used in 2 levels. The purpose of this paper is to investigate cache in the second level of Hibernate. For this purpose, after providing further explanations, we will first provide you with a short introduction about cache in the first level of Hibernate and then we will talk about cache in the second level of Hibernate.
First level cache or first level cache in Hibernate
Cache is enabled at the first level, at the level of a session, and is used in all requests that are exchanged. This level of cache automatically processes all requests before being sent to the database and prevents duplicate transactions from exchanging with the database. The first-level Cache features can be summarized in the following cases:
- This level of cache is enabled by default, at the level of a session.
- It doesn’t require developers to apply certain settings.
- Developers cannot disable this level.
- This cache is available throughout the session operation.
- If session is disabled, all cached objects will also be lost.
- Cached objects cannot be shared between multiple sessions.
In the figure below, you will see the steps to load an object. In this form, Hibernate first checks the availability of the requested object on the session after getting the request. If this object is available, the data will be refreshed from the session and returned. If the object is not available, the request will go to the database and the data will be extracted from the database. In this case, cache will also be built.
Second level cache or second level cache in Hibernate
The cache in the second level depends on the Session Factory object and loads all objects at the Factory level when executing transactions. As a result, these objects are not limited to one user and will be available at all levels of the program. The cache features in the second level can be summarized in the following cases:
- This level of Cache exists by default, at the level of the Session Factory object.
- Requires developers to apply certain settings.
- Using this cache is optional.
- For this cache, there are various implementations such as EH Cache, OS Cache, SWARM Cache, JBOSS Cache.
The loading steps with this cache are similar to the first level cache. The only difference is that if the data is not found at the Session level, the search will be performed at the more inclusive Session Factory level, and if the search in Session Factory does not result, the request will be sent to the database.
We want to review the implementation of the second level cache using EH Cache. In this program, we activate and use hibernate’s second level cache. After that, we add dependency called Hibernate -ehcache to the project pom.
We also need to make changes to Hibernate settings. Assuming that the factory singleton is equal to the singleton EH Cache Reign Factory, we enable the second level cache and query cache, and the proprietary settings of EH Cache should also be introduced to Hibernate as a separate xml file.
Now these must be determined in the Settings file (ehcache.xml).
- In the <diskstore> tag, a path is specified to hold the cached content.</diskstore> In fact, this cache is done in the main memory and this path is where it is used in case of overflow or overflow of data.
- In the next tag, i.e. the tag <default cache=””>for cache of all entity, the same default settings are applied, but if a entity wants to have different settings, these proprietary settings should be <cache>introduced to Hibernate</cache> in a dedicated tag.</default>
In the persistence element, the cache strategy is determined against Local Temp Swap. Hibernate uses temporary memory and automatically empties as the program resets.
In each section on which the cache is to be applied, a @cache annotation is placed in which, in addition to announcing the cache strategy, a part of the settings file (ehcache.xml) is introduced to apply the settings.
In this step, we will go to the implementation stages of the program. For this purpose, we load the code for two objects under different conditions, but simultaneously we open 2 separate sessions (session B, session A) on Session Factory. Session Factory has a method called get Statistics(). This method contains statistical information about all events that may occur on a Session Factory.
To use this information, they must be enabled. Three of these information are in the second level cache and are used in the print date() method mentioned in this class.
The get Second Level Cache Hit Count() method returns the number of temporary extraction times an entity from the cache. When a record is requested, it is first referred to the cache, and if the record is in the cache, it will be used and a unit will be added to this number.
The get Second Level Cache Miss Count() method returns the number of unsuccessful visits to the cache. In other words, this method indicates the number of times a cache has been referred, but there was no record in the cache.
The get Second Level Cache Put Count() method returns the number of times an entity is placed in the cache. This means that when an entity is extracted from the bank, a copy of it is placed in the cache and this number increases by one unit.
Another method called get Entity Fetch Count method is used here. This method refers to the number of times fetch requests are sent to the database.
We check the process of running the program from the point specified by breakpoint. We load a record of the Employee table from session A. Then, with the method we have already written, we extract the record content and print the statistics about the cache. Printing query text on the console means extracting information directly from the bank. As in the statistical data, it is also visible that the request has been sent to the bank. The number of withdrawals from the cache or Hibernate is zero. Because before, such a record has not been included in the cache. The number of unsuccessful referrals to the cache is equal to 1 and the number of times it is stored in the cache is equal to 1. Because from this moment on, this record will be stored in the cache.
Secondly, we reload the same record as the first stage. The number of times you extract from the bank does not change because this record has already been loaded and is available in the cache. In fact, no operations are performed and there is no change in the parameters related to the cache.
In the third step, by evicting the order, we remove the loaded entity from the session. In the first level cache, by such a command, the first level cache, which is the default cache and at the session level, is erased, but here by removing the entity from the session, the second level cache, which is located at the Session Factory level, will persist. Pay attention to the printed information. This information is no different from the previous step, and in fact, with the loss of information in the session, the second level cache information will not be lost.
Next, we load a new record on this session. We can see that the number of extractions is added to a unit. In contrast, the number of withdrawals from the cache does not change and the number of unsuccessful referrals also increased. Also, the number of times the record is placed in the cache also increased by one unit because the new record has been in the cache from this moment on.
Finally, we load the same initial record this time in a new session. Due to the commonality of the cache at the session level, the request is not sent to the database and the record is removed from the cache.
Therefore, the number of extractions from the cache has increased, but the number of unsuccessful referrals and the number of times it is saved does not change.