DEV Community

Cover image for Hibernate Caching Internals, Practical Example
Sameh Muhammed
Sameh Muhammed

Posted on

Hibernate Caching Internals, Practical Example

Introduction

When any application server starts (ex: Tomcat), it creates what called by Thread Pool, a Thread Pool is a group of threads that are created and ready to serve any request comes to any application attached with this application server.

Image description

Image above describes the request life cycle

  1. Client send the request to the server (/students/50).

  2. Application server pick a thread from thread pool then attach the request processing to it.

  3. Thread starts its journey in the back-end service till get the result and come back to the client.

In this way application server mange requests came to them each request is executed in separate thread, and during the execution, the thread is busy and can not process any another request till it finish, and after finish it became available for another one, and so on.

Return to Hibernate

Hibernate in order to execute queries on database, it has what called SessionFactory, this factory is responsible for creating a session with database so it can deal with it.

Hibernate creates a session per thread, so regarding to what we discussed before, each request can be processed by separate thread and Hibernate creates a session for each thread to communicate with database, with this way Hibernate manage communication with database.

Image description

Hibernate caching

Hibernate provides a way for query result caching to enhance performance of repetitive queries done among database, and it has multiple strategies for this.

First level cache

While Hibernate creates a session per thread, it does a caching in this session object, as below image if you tried this scenario.

Image description

The first call will fire a query to the database and Hibernate is smart enough to cache this information with Session object by id, and in the subsequent call Hibernate not need to fire another query, it first looks into Session object if it has an id like this, if true then retrieve it.

this what called First Level Caching and this is done by default.

Second level caching

As first level cache is done upon Session objects that created by SessionFactory, Hibernate also provide a caching mechanism upon SessionFactory that all sessions created from that factory, which means that the first request only will be served from database and all other requests for same data will be served from cache until this data updated.

Image description

this strategy of caching needs a cache provider like redis or Ehcache or Memcache, you can use whatever you want, but you need to specify that to Hibernate

Implementation

First of all, second level cache not enabled by default in Hibernate you have to explicitly enable it.
we will use Ehcache as database for caching with Hibernate in this example.

so we need to add this to pom file

<dependency
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>5.6.5.Final</version>
</dependency>>

and add these properties to property file

spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactorye
and entity like below

Image description

Note: @Cachable is works as meta-data for this entity, but real caching happen with @Cache

Cache by query

Both first level and second level caching is working only with getting entity by id, but what if you want to form another query and cache it, this can be done through these steps

add this property to enable cache by query

spring.jpa.properties.hibernate.cache.use_query_cache=true

and this to the query or method

Image description

But this is working in different way, it's not cache reference to entities, instead it just cache the IDs from query result, so first query will be like below

Hibernate:
select
student0_.id as id1_0_,
student0_.name as name2_0_
from
students student0_
where
student0_.name=?

Hibernate will cache the IDs of result of this query, and in subsequent requests for same query and same bind parameters it will get the IDs from caching and fire query like below

Hibernate:
select
student0_.id as id1_0_0_,
student0_.name as name2_0_0_
from
students student0_
where
student0_.id=?

This will help performance off course as ID column always indexed in databases so it will be faster than real query, but in order to get most benefit you can enable second level cache with query cache, so that the IDs cached in query cache layer and the entity cached in second level cache layer and no need to go to database at all.

Resources

IF YOU LIKED THE POST,YOU CAN SUPPORT SUCH CONTENT WITH A CUP OF COFFEE, THANKS IN ADVANCE.

Buy Me A Coffee

Top comments (0)