Hibernate provides a powerful caching mechanism; it can either use its built-in cache or integrate with other popular caching frameworks like EhCache, OSCache, SwarmCache, etc.
Hibernate uses two levels of cache: Session Cache (First-Level Cache) and Second-Level Cache.
- Session Cache (First-Level Cache): This is enabled by default and works out of the box without any additional configuration. Each session in Hibernate has its own cache and it’s completely destroyed when the session ends. The session cache ensures that each object is loaded only once within the same session. It also helps in minimizing the number of SQL queries that need to be executed within a session.
- Second-Level Cache: This is an optional cache and first-level cache always talks to this cache before hitting the database. It’s used to cache objects across sessions. When this cache is enabled, once an object is loaded from the database, it’s stored in the cache for future use. Hibernate uses this cache to reduce the number of database hits as much as possible to improve performance.
Hibernate’s second-level cache is pluggable. Hibernate supports integration with several popular caching frameworks, such as EhCache, Infinispan, Hazelcast, and others. You can choose the one that best suits your needs.
It’s also worth noting that hibernate provides a Query Cache, which is used to cache the results of a query. When the query cache is turned on, hibernate will store the results of the query in the cache and retrieve them the next time the same query is executed, instead of hitting the database again.
Caching is a powerful feature for improving the performance of your application, but it’s also complex. It’s important to understand when and how to use it to avoid potential problems. For example, caching is not always beneficial for all types of applications, especially if your data changes frequently or if you have specific requirements for data freshness.
How are updates handled?
both the first level and second-level caches are aware of updates within a Hibernate session.
- First-Level Cache: This is directly associated with the Hibernate Session. If an object is updated within a session, the change is immediately reflected in the first-level cache. When the session is flushed (either manually or automatically), these changes are propagated to the database.
- Second-Level Cache: This cache is associated with the Session Factory, not with individual sessions. If an object is updated within a session, and that object is also stored in the second-level cache, hibernate will update or evict the corresponding entry in the second-level cache when the transaction is committed, thereby keeping the cache consistent with the database.
It’s important to note that the second-level cache does not get updated immediately when an object is updated within a session. The changes are only propagated to the second-level cache when the transaction is committed.
Also, if you have multiple application nodes, you need to set up a cache provider that supports distributed caching, to ensure cache consistency across all nodes.
How to turn ON/OFF cache?
The first-level cache in Hibernate is associated with the Session object and it’s enabled by default. While there’s no direct way to completely turn it off, you can manage it effectively to achieve similar results.
Here are a few ways to do that:
Clear the Session: You can use the clear()
method of the Session object to clear the entire first level cache.
session.clear();
This will clear all the objects in the cache, effectively removing all objects from the first-level cache.
This method is used to clear the session cache. It doesn’t end the session; instead, it just removes all the objects from the session cache (first-level cache). After the session is cleared, the session is still open and you can continue to use it. However, since the session cache is cleared, any subsequent operation that requires an object previously stored in the session cache will cause Hibernate to fetch the object from the database again.
Evict Specific Objects: If you want to remove a specific object from the first-level cache, you can use the evict()
method.
session.evict(object);
This will remove the specified object from the first-level cache.
Close the Session: The first-level cache is associated with the session, so when you close the session, the first-level cache is destroyed:
session.close();
This method is used to end the session and release the resources held by this session. Once a session is closed, it’s considered to be in the “closed” state and you can’t use it anymore. If you try to use a closed session, Hibernate will throw an exception. Also, when a session is closed, all the objects associated with that session will be detached and the first-level cache associated with that session is destroyed.
Remember, the first-level cache is an essential part of Hibernate and it’s there to improve performance by reducing the number of database hits. So, while you can manage it as shown above, it’s generally not recommended to completely bypass it unless you have a specific reason to do so.
Turning on the Second-Level Cache in Hibernate requires some configuration. Here’s a basic example of how to enable it with EhCache:
- Add the EhCache dependency to your project.
- In your Hibernate configuration file (usually
hibernate.cfg.xml
orpersistence.xml
), you need to set the propertyhibernate.cache.use_second_level_cache
totrue
:
<property name="hibernate.cache.use_second_level_cache">true</property>
3. You also need to specify the cache provider:
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
4. Then, in your entity classes, you need to enable caching with the @Cache
annotation:
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class MyEntity {
// ...
}
To turn off the second-level cache, you can set the hibernate.cache.use_second_level_cache
property to false
:
<property name="hibernate.cache.use_second_level_cache">false</property>
Remember, these are just basic examples. The actual configuration can be more complex depending on your specific needs and the cache provider you’re using.