How hibernate second level cache works?

Spread the words...Share on Google+29Share on Facebook50Tweet about this on Twitter7Share on LinkedIn8Buffer this pageShare on StumbleUpon0Share on Reddit0

Caching is facility provided by ORM frameworks which help users to get fast running web application, while help framework itself to reduce number of queries made to database in a single transaction. Hibernate also provide this caching functionality, in two layers.

  • Fist level cache: This is enabled by default and works in session scope. Read more about hibernate first level cache.
  • Second level cache: This is apart from first level cache which is available to be used globally in session factory scope.

Above statement means, second level cache is created in session factory scope and is available to be used in all sessions which are created using that particular session factory.
It also means that once session factory is closed, all cache associated with it die and cache manager also closed down.
Further, It also means that if you have two instances of session factory (normally no application does that), you will have two cache managers in your application and while accessing cache stored in physical store, you might get unpredictable results like cache-miss.

hibernate first and second level cache_example

Hibernate first and second level cache

In this tutorial, I am giving concepts around hibernate second level cache and give example using code snippets.

How second level cache works

Lets write all the facts point by point:

  1. Whenever hibernate session try to load an entity, the very first place it look for cached copy of entity in first level cache (associated with particular hibernate session).
  2. If cached copy of entity is present in first level cache, it is returned as result of load method.
  3. If there is no cached entity in first level cache, then second level cache is looked up for cached entity.
  4. If second level cache has cached entity, it is returned as result of load method. But, before returning the entity, it is stored in first level cache also so that next invocation to load method for entity will return the entity from first level cache itself, and there will not be need to go to second level cache again.
  5. If entity is not found in first level cache and second level cache also, then database query is executed and entity is stored in both cache levels, before returning as response of load() method.
  6. Second level cache validate itself for modified entities, if modification has been done through hibernate session APIs.
  7. If some user or process make changes directly in database, the there is no way that second level cache update itself until “timeToLiveSeconds” duration has passed for that cache region. In this case, it is good idea to invalidate whole cache and let hibernate build its cache once again. You can use below code snippet to invalidate whole hibernate second level cache.
/**
 * Evicts all second level cache hibernate entites. This is generally only
 * needed when an external application modifies the databaase.
 */
public void evict2ndLevelCache() {
    try {
        Map<String, ClassMetadata> classesMetadata = sessionFactory.getAllClassMetadata();
        for (String entityName : classesMetadata.keySet()) {
            logger.info("Evicting Entity from 2nd level cache: " + entityName);
            sessionFactory.evictEntity(entityName);
        }
    } catch (Exception e) {
        logger.logp(Level.SEVERE, "SessionController", "evict2ndLevelCache", "Error evicting 2nd level hibernate cache entities: ", e);
    }
}

To understand more using examples, I wrote an application for testing in which I configured EhCache as 2nd level cache. Lets see various scenarios:

a) Entity is fetched very first time

DepartmentEntity department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

System.out.println(HibernateUtil.getSessionFactory().getStatistics().getEntityFetchCount());           //Prints 1
System.out.println(HibernateUtil.getSessionFactory().getStatistics().getSecondLevelCacheHitCount());   //Prints 0

Output: 1 0

Explanation: Entity is not present in either 1st or 2nd level cache so, it is fetched from database.

b) Entity is fetched second time

//Entity is fecthed very first time
DepartmentEntity department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

//fetch the department entity again
department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

System.out.println(HibernateUtil.getSessionFactory().getStatistics().getEntityFetchCount());           //Prints 1
System.out.println(HibernateUtil.getSessionFactory().getStatistics().getSecondLevelCacheHitCount());   //Prints 0

Output: 1 0

Explanation: Entity is present in first level cache so, it is fetched from there. No need to go to second level cache.

c) Entity is evicted from first level cache and fetched again

//Entity is fecthed very first time
DepartmentEntity department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

//fetch the department entity again
department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

//Evict from first level cache
session.evict(department);
			
department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

System.out.println(HibernateUtil.getSessionFactory().getStatistics().getEntityFetchCount());           //Prints 1
System.out.println(HibernateUtil.getSessionFactory().getStatistics().getSecondLevelCacheHitCount());   //Prints 1

Output: 1 1

Explanation: First time entity is fetched from database. Which cause it store in 1st and 2nd level cache. Second load call fetched from first level cache. Then we evicted entity from 1st level cache. So third load() call goes to second level cache and getSecondLevelCacheHitCount() returns 1.

d) Access second level cache from another session

//Entity is fecthed very first time
DepartmentEntity department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

//fetch the department entity again
department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

//Evict from first level cache
session.evict(department);
			
department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

department = (DepartmentEntity) anotherSession.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

System.out.println(HibernateUtil.getSessionFactory().getStatistics().getEntityFetchCount());           //Prints 1
System.out.println(HibernateUtil.getSessionFactory().getStatistics().getSecondLevelCacheHitCount());   //Prints 2

Output: 1 2

Explanation: When another session created from same session factory try to get entity, it is successfully looked up in second level cache and no database call is made.

So now we are clear on how second level cache is used by hibernate.

Download sourcecode

Drop me a comment if any query or suggestion.

Happy Learning !!

Spread the words...Share on Google+29Share on Facebook50Tweet about this on Twitter7Share on LinkedIn8Buffer this pageShare on StumbleUpon0Share on Reddit0

 

 

Give me your email address and whenever I write any tutorial or discuss any java concept, you will receive a little email in your inbox.

Join 2,866 other subscribers

42 thoughts on “How hibernate second level cache works?”

  1. Thanks Lokesh for sharing it.

    You mentioned first level cache is available by default. What about second level cache. Do we need to have some configuration for the 2nd level cache.
    If yes, how we do it? Can you please elaborate?

  2. Hi Lokesh,

    which scenario we can use first level cache since it belongs to session and will not available in other methods.

    1. Hibernate uses first level cache mainly to reduce the number of SQL queries it needs to generate within a given transaction. For example, if an object is modified several times within the same transaction, Hibernate will generate only one SQL UPDATE statement at the end of the transaction, containing all the modifications.

  3. Hi Loken,

    Your tutorials are really useful for understanding each concept very clearly. In one of the interview they asked me how to refresh web page content that database changes every 30 minutes automatically using any caching? if possible could you please explain me with examples?

      1. Thanks for your reply but they were asked me using hibernate caching mechanism that is only new changes during that 30 minutes period need to get from database and existing results should get from hibernate cache and same needs to display to the user.

          1. Yes, we need to do use server side cache. if possible could you please provide me sample code how can we set time interval at server side cache.

  4. Hey Lokesh,
    thanx for the early reply….Can u suugest me one: I am implementing rest Webservices, Now i need to implement Caching for the same, I have gone through so many Articles in the net regarding the Http etcc, but i am not able to cache my rest WS, can u put some light on the same…….

  5. Hi Lokesh…..
    I have a doubt:
    My scenario: i am implementing hibernate second level caching:
    I have totally different application to alter the Database, i never use my HIbernate application for insert or update, i just use for Retrieving the data. suppose i have retrieved a data and i alter the database with different application, can u tell me whether the second level cache still works for the same database which i have altered using diff application…..

    1. Hibernate second level cache works at “SessionFactory scope/level”. So, till the time you have common SessionFactory for different sessions in your application you are good. But, in your case you have a completely different application with (assuming) different SessionFactory altogether, So in your case, second level cache WILL NOT WORK with exact behavior as in single application.

      Please do not misunderstood me here. Although the caching will happen at both applications but it will be independent at both ends regardless the changes done by any of application.

  6. Hi Lokesh Gupta, Nice tutorials your posted i Have Implemented Second level Cache Mechanism.session is not loaded from the Second level cache if your remove the department.getName() its not hitting Second level Cache Mechanism could you tel me what is reason

  7. Can u please explain about concurrency strategies used to configure second level cache at class level like transactional, read-write etc . i mean which strategy to be used when?

  8. HI Lokesh
    I followed your step to print out below two lines
    System.out.println(HibernateUtil.getSessionFactory().getStatistics().getEntityFetchCount());
    System.out.println(HibernateUtil.getSessionFactory().getStatistics().getSecondLevelCacheHitCount());

    above four conditions you mentioned, it always shows 0 0
    could you help me to figure it out?

    Thank you

    1. Try setting following in hibernate configuration properties

      hibernate.generate_statistics————————– true
      hibernate.cache.use_structured_entrie————– true

      1. Hi, Lokesh,
        Thank you for replying
        I put those settings in xml file,
        a,b works well, but c shows 2 0 not 1 1
        do you know why it is ?
        Thank you

        1. It must me 0 2…………. not 2 0.
          Reason is second level cache is already created. So DB hits are 0. Delete the second level cache from file system and you will get desired result.

  9. Very very helping. Thanks. I need something which can differentiate b/w SOAP and REST web services . Can you please help me ?

  10. Thanks for your very nice post.

    Could you answer some questions from me?
    Can I disable the 2nd cache level? I know the advantages of caching mechanism but I think there are some disadvantages of it, so could tell me more about this?

    Thank you a lot, I’m waiting for your response.

    1. 1) Want to disable second level cache? Don’t configure it. Simple and most obvious.
      2) Yes, caching is boon to your application but it introduces certain overhead also. Everytime, you update something or delete something or even create create something, you need to invalidate certain cache blocks and re-build them so they have latest data. This step becomes more complex when cache is distributed. But believe me, advantages outweigh any such overhead.

  11. Is cache applicable for only load methods or it is also for save/update methods.
    Mean when we save an entity will it be stored in cache before saving in DB ?

    1. NO. “Cache is only for selecting the data”. When you update something, if method return the updated entity, then in back-end it automatically fires a SELECT query which invalidate/update the first/second level caches. Otherwise if its only update operation, you will have to fetch the updated entity once again.

  12. Hi Gupta, Nice tutorials your posted. I want Second Level Cache Implementation by using Hiberante4 with Maven. I tried many ways. There is proper resource to implement. Please Can you provide one example by using Hibernate4.

  13. Ih,
    If i would like to use NO-SQL DB as hibernate second level cache, what i have to do..?
    what are the classes i need to customise.

Want to ask any question? Or suggest anything?