Search This Blog

Wednesday 28 August 2013

CacheModes in Hibernate

Hibernate offers us a CacheMode option. This is something that allows us to control the behavior of the second level cache. Consider the below code:
public static void testGetMode() {
    Statistics statistics = sessionFactory.getStatistics();

    Session session1 = sessionFactory.openSession();
    System.out.println("Cache Put Count : "
        + statistics.getSecondLevelCachePutCount());
    session1.get(BookType.class, 1);
    System.out.println("Cache Put Count : "
        + statistics.getSecondLevelCachePutCount());
    session1.close();

    Session session2 = sessionFactory.openSession();
    session2.setCacheMode(CacheMode.GET);
    session2.get(BookType.class, 1);
    session2.get(BookType.class, 2);
    System.out.println("Cache Put Count : "
        + statistics.getSecondLevelCachePutCount());
    session2.close();
}
The above method simply loads records from the database. The session.get call results in a load from the database and also an addition to the cache.
The second step involved opening a session and setting the Cache Mode to GET. This means the session will be able to read records that are present in the second level cache. However no new records will be added to the cache. Also if a fetched record were modified the cache entry if present will be invalidated.
The output is as below:
Cache Put Count : 0
Hibernate: 
    /* load com.object.cache.BookType */ 
    select
        booktype0_.ID as ID0_0_,
        booktype0_.NAME as NAME0_0_ 
    from
        BOOK_TYPE_MASTER booktype0_ 
    where
        booktype0_.ID=?
Cache Put Count : 1 
Hibernate: 
    /* load com.object.cache.BookType */ 
    select
        booktype0_.ID as ID0_0_,
        booktype0_.NAME as NAME0_0_ 
    from
        BOOK_TYPE_MASTER booktype0_ 
    where
        booktype0_.ID=?
Cache Put Count : 1
As can be seen the cache size became 1 after the first fetch. However the second session is set with a CacheMode.GET . Thus the record with id 1 was read from the cache. The record with id 2 was not in the cache - it was fetched from the database but not added to the second level cache.
public static void testIgnoreMode() {
    Statistics statistics = sessionFactory.getStatistics();

    Session session1 = sessionFactory.openSession();
    System.out.println("Cache Put Count : "
        + statistics.getSecondLevelCachePutCount());
    session1.get(BookType.class, 1);
    System.out.println("Cache Put Count : "
        + statistics.getSecondLevelCachePutCount());
    session1.close();
    System.out.println("Running in Ignore mode");
    Session session2 = sessionFactory.openSession();
    session2.setCacheMode(CacheMode.IGNORE);
    session2.get(BookType.class, 1);
    session2.get(BookType.class, 2);
    session2.get(BookType.class, 3);
    System.out.println("Cache Put Count : "
        + statistics.getSecondLevelCachePutCount());
    System.out.println("Cache Hit Count : "
        + statistics.getSecondLevelCacheHitCount());
    session2.close();
}
The next one I tried is CacheMode.IGNORE . Once this setting is added to a session, it will not add or read objects from the second level cache. However if an object loaded in the session is modified, Hibernate will invalidate its entry from the second level cache. This ensures data integrity for other sessions that work with the second level cache. In the above code, the first session read a record which resulted in a PUT in the second level cache. The next session opened used a CacheMode of type IGNORE. This meant that for all three GET calls three SQL queries were fired. No data was read from or added to the second level cache. The output indicates the same:
Cache Put Count : 0
Hibernate: 
    /* load com.object.cache.BookType */ 
    select
        booktype0_.ID as ID0_0_,
        booktype0_.NAME as NAME0_0_ 
    from
        BOOK_TYPE_MASTER booktype0_ 
    where
        booktype0_.ID=?
Cache Put Count : 1
Running in Ignore mode
Hibernate: 
    /* load com.object.cache.BookType */ 
    select
        booktype0_.ID as ID0_0_,
        booktype0_.NAME as NAME0_0_ 
    from
        BOOK_TYPE_MASTER booktype0_ 
    where
        booktype0_.ID=?
Hibernate: 
    /* load com.object.cache.BookType */ 
    select
        booktype0_.ID as ID0_0_,
        booktype0_.NAME as NAME0_0_ 
    from
        BOOK_TYPE_MASTER booktype0_ 
    where
        booktype0_.ID=?
Hibernate: 
    /* load com.object.cache.BookType */ 
    select
        booktype0_.ID as ID0_0_,
        booktype0_.NAME as NAME0_0_ 
    from
        BOOK_TYPE_MASTER booktype0_ 
    where
        booktype0_.ID=?
Cache Put Count : 1
Cache Hit Count : 0
As can be seen the PUT count remained unchanged while the HIT count was zero indicating no interaction with the second level cache.
As seen till now the cache mode setting controls a session's interaction with the second level cache. In the next post we shall explore remaining CacheMode options.

1 comment:

  1. Now, I think that can't clear cache when using CacheMode.IGNORE.
    Please give me idea to resolve this problem clear cache in session not use method clear().

    ReplyDelete