Ehcache для Hibernate

Я использую ehcache-2.9.0 с Hibernate 4.3.5, я настроил его правильно, и EHCache отлично работает в следующих стратегиях параллелизма кеша: READ_ONLY NONSTRICT_READ_WRITE TRANSACTIONAL

Но это не работает для READ_WRITE, статистика статистики = sessionFactory.getStatistics(); stats.getSecondLevelCacheHitCount()) всегда равен 0 в случае READ_WRITE. Я использую его в простом проекте JAVA. Пожалуйста, просмотрите код и файлы конфигурации. Пожалуйста помоги.

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>

ТестКласс

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

person Brajesh    schedule 21.03.2017    source источник


Ответы (1)


Кэширование работает отлично. Дело в том, что фильм выселили. Таким образом, даже если он находится в Ehcache, Hibernate не вернет его, потому что он не подходит. Его выселили.

То же самое, если вы чередуете два сеанса. Что-то, загруженное в кеш одним сеансом, не может быть использовано, пока сеанс не завершится.

Однако, если у вас есть два отдельных сеанса, вы увидите попадание в кеш. См. код ниже.

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();
}
person Henri    schedule 22.03.2017
comment
Анри, спасибо за ответ, но даже если я не использую session.evict(movie); тогда также количество попаданий в кэш второго уровня = 0. Обратите внимание, что только в случае READ_WRITE он не работает, все остальные стратегии работают должным образом. Пожалуйста, проверьте один для стратегии READ_WRITE. - person Brajesh; 22.03.2017
comment
Это не сработает из-за транзакции. Вы пробовали мою версию в двух отдельных сессиях? Потому что это отлично работает, и я вижу количество попаданий. - person Henri; 23.03.2017
comment
да, я пробовал вашу версию, она тоже работает для всех стратегий, кроме READ_WRITE. В документе Ehcache они упомянули, что READ_WRITE будет работать. Но просто стратегия READ_WRITE не работает. Сейчас, как вы сказали, попробую без транзакции и проверю. - person Brajesh; 23.03.2017
comment
Я не уверен, что случилось. READ_WRITE означает, что вы не можете прочитать из кеша запись, которая была прочитана из другой транзакции. - person Henri; 24.03.2017