简体   繁体   中英

Ehcache for Hibernate

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);
    }
}

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();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM