【问题标题】:Ehcache for Hibernate用于休眠的 Ehcache
【发布时间】:2017-08-12 20:11:39
【问题描述】:

我将 ehcache-2.9.0 与 Hibernate 4.3.5 一起使用,我已正确配置它并且 EHCache 在以下缓存并发策略中工作正常: 只读 NONSTRICT_READ_WRITE 交易性

但它不适用于 READ_WRITE, 这 统计 stats = sessionFactory.getStatistics(); 在 READ_WRITE 的情况下,stats.getSecondLevelCacheHitCount()) 始终为 0。我在简单的 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>

电影.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);
    }
}

【问题讨论】:

    标签: ehcache hibernate-4.x ehcache-bigmemory


    【解决方案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();
    }
    

    【讨论】:

    • Henri,感谢您的回复,但即使我没有使用 session.evict(movie);然后也是二级缓存命中计数=0。请注意,仅在 READ_WRITE 的情况下,它不能正常工作,其他所有策略都按预期工作。请检查 READ_WRITE 策略之一。
    • 因为有事务所以不能用。您是否在两个单独的会话中尝试过我的版本?因为它完美地工作,我可以看到命中数。
    • 是的,我已经尝试过你的版本,它也适用于所有策略,除了 READ_WRITE。在 Ehcache 文档中,他们提到 READ_WRITE 会起作用。但只是 READ_WRITE 策略不起作用。现在,正如您所说,我将尝试不进行交易并进行检查。
    • 我不确定出了什么问题。 READ_WRITE 表示您无法从缓存中读取从另一个事务中读取的条目。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-11
    • 2011-07-13
    • 1970-01-01
    • 2013-09-25
    • 1970-01-01
    • 2011-07-18
    相关资源
    最近更新 更多