Ehcache for Hibernate

495 Views Asked by At

I am using ehcache-2.9.0 with Hibernate 4.3.5, i have configured it properly and EHCache is working fine in the following cache concurrency strategies : READ_ONLY NONSTRICT_READ_WRITE TRANSACTIONAL

But its not working for READ_WRITE, the Statistics stats = sessionFactory.getStatistics(); stats.getSecondLevelCacheHitCount()) is always 0 in case of READ_WRITE. I am using it in simple JAVA Project. Please go through the code and configuration files. Please help.

ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"
    monitoring="autodetect" dynamicConfig="true">

    <defaultCache 
        maxEntriesLocalHeap="10000"
        eternal="false"
        timeToIdleSeconds="120" 
        timeToLiveSeconds="120" 
        diskSpoolBufferSizeMB="30"
        maxEntriesLocalDisk="10000000" 
        memoryStoreEvictionPolicy="LRU" 
        statistics="true">
        <persistence strategy="localTempSwap" />
    </defaultCache>

    <cache name="com.slc.entities.Movie"
        maxEntriesLocalHeap="100"
        maxEntriesLocalDisk="100"
        eternal="false"
        diskSpoolBufferSizeMB="20"
        timeToIdleSeconds="300" 
        timeToLiveSeconds="600"
        memoryStoreEvictionPolicy="LFU"
        transactionalMode="off">
        <persistence strategy="localTempSwap" />
    </cache>

      <cache
        name="org.hibernate.cache.StandardQueryCache"
        maxEntriesLocalHeap="5"
        eternal="false"
        timeToLiveSeconds="120">
        <persistence strategy="localTempSwap"/>
    </cache>
</ehcache>


hibernate.cfg.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                                             "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
        <session-factory>
            <property name="connection.url">jdbc:oracle:thin:@localhost:1521:xe</property>
            <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
            <property name="connection.username">usr</property>
            <property name="connection.password">pwd</property>
            <property name="hibernate.hbm2ddl.auto">update</property>

            <property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
            <property name="show_sql">true</property>

            <property name="hibernate.cache.use_second_level_cache">true</property>

            <property name="hibernate.cache.use_query_cache">true</property>
            <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

            <!-- Generate Statistics about the Second Level Cache. -->
            <property name="hibernate.generate_statistics">true</property>

            <mapping resource="com/slc/entities/Movie.hbm.xml" />

            <class-cache usage="read-write" class="com.slc.entities.Movie"/>
        </session-factory>
    </hibernate-configuration>

Movie.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.slc.entities">

    <class name="Movie" table="MOVIE" mutable="false">
        <cache usage="read-write" region="com.slc.entities.Movie" />

        <id name="movieId" column="MOVIE_ID">
            <generator class="increment"/>
        </id>
        <property name="movieName" column="MOVIE_NAME"/>
        <property name="genere" column="GENERE"/>
        <property name="releaseYear" column="RELEASE_YEAR"/>
    </class>
</hibernate-mapping>

TestClass

public class SLCTest {

    public static void main(String[] args) {
        Movie movie = null;
        try {

            // Initialize Sessions
            SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
            Statistics stats = sessionFactory.getStatistics();
            System.out.println("Stats enabled=" + stats.isStatisticsEnabled());

            Session session = sessionFactory.openSession();
            Session otherSession = sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();
            Transaction otherTransaction = otherSession.beginTransaction();

            printStats(stats, 0);

            movie = (Movie) session.load(Movie.class, 1);
            printData(movie, stats, 1);

            movie = (Movie) session.load(Movie.class, 1);;
            printData(movie, stats, 2);

            // clear first level cache, so that second level cache is used
            session.evict(movie);
            movie = (Movie) session.load(Movie.class, 1);
            printData(movie, stats, 3);

            movie = (Movie) session.load(Movie.class, 3);
            printData(movie, stats, 4);
            transaction.commit();
            session.close();

            movie = (Movie) otherSession.load(Movie.class, 1);
            printData(movie, stats, 5);

            // Release resources

            otherTransaction.commit();
            sessionFactory.close();

        } finally {
            HibernateUtil.closeSessionFactory();
        }
    }

    private static void printStats(Statistics stats, int i) {
        System.out.println("***** " + i + " *****");
        System.out.println("Fetch Count=" + stats.getEntityFetchCount());
        System.out.println("Second Level Hit Count="
                + stats.getSecondLevelCacheHitCount());
        System.out.println("Second Level Miss Count="
                + stats.getSecondLevelCacheMissCount());
        System.out.println("Second Level Put Count="
                + stats.getSecondLevelCachePutCount());
        System.out.println("****** end stats ******");
    }

    private static void printData(Movie movie, Statistics stats, int count) {
        System.out.println(movie);
        System.out.println(movie.getMovieName());
        printStats(stats, count);
    }
}
1

There are 1 best solutions below

4
Henri On

You caching is working perfectly. The thing is that the movie was evicted. So even though it is in Ehcache, Hibernate won't return it because it isn't eligible. It was evicted.

Same thing is you interleave two sessions. Something loaded in cache by one session can't be used until the session is finished.

However, if you have two separate sessions, you will see a cache hit. See the code below.

Movie movie;
try {
  // Initialize Sessions
  SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
  Statistics stats = sessionFactory.getStatistics();

  Session session = sessionFactory.openSession();
  Transaction transaction = session.beginTransaction();

  movie = (Movie) session.load(Movie.class, 1);
  printData(movie, stats, 1);

  transaction.commit();
  session.close();

  Session otherSession = sessionFactory.openSession();
  Transaction otherTransaction = otherSession.beginTransaction();

  movie = (Movie) otherSession.load(Movie.class, 1);
  printData(movie, stats, 3);

  otherTransaction.commit();
  otherSession.close();

} finally {
  HibernateUtil.closeSessionFactory();
}