Spring-Boot - 激活Hibernate二级缓存

时间:2017-10-09 15:55:14

标签: spring jpa spring-boot ehcache

我正在尝试在使用spring-boot-starter-data-jpa的Spring-Boot应用程序上激活Hibernate二级缓存。我使用Ehcache 2并在我的类路径中使用hibernate-ehcache

我使用了以下属性

spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.use_query_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
spring.jpa.properties.hibernate.generate_statistics=true

我也在src / main / resources中创建了ehcache.xml(只是一个永不过期的缓存测试)

<ehcache updateCheck="false" monitoring="autodetect"
     dynamicConfig="true">

  <defaultCache
        maxElementsInMemory="100000"
        maxElementsOnDisk="10000000"
        eternal="true"
        overflowToDisk="false">
  </defaultCache>
</ehcache>

此外,实体使用@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)注释,在日志文件中我可以清楚地看到默认缓存用于实体,因此它似乎识别注释并像往常一样初始化缓存。

WARN .h.c.e.AbstractEhcacheRegionFactory : HHH020003: Could not find a specific ehcache configuration for cache named [at.test.demo.persistence.entity.Employee]; using defaults.

现在为了测试这个,我写了一个简单的测试,插入3个Employees并使用通常的JPA-Entitymanager加载它们。之后,我试图通过调用:

来验证加载的Employee是否真正进入了Cache
Assert.assertTrue(em.getEntityManagerFactory().getCache().contains(Employee.class, employeeId));

但总是失败。 SessionFactory-Staticstics也显示了所有内容的零,这是不对的。

有什么想法吗?

修改 我删除了项目并将其添加到公共gitlab repo中,以便您重现它:https://gitlab.com/matrium00/reproduce-cache-issue

由于存在问题,目前只有一个单元测试失败。

EDIT2 以下是em-factory Spring-Boot的工作XML配置示例。我知道我可以手动在Configuration-Class中创建必要的bean,但必须有更好的方法:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
      autowire="byName" depends-on="flyway">
    <property name="packagesToScan" value="at.my.package.demo.persistence.entity"/>
    <property name="dataSource" ref="dataSource"/>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
            <prop key="hibernate.default_schema">${jdbc.schema}</prop>

            <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop>
            <prop key="hibernate.cache.use_second_level_cache">true</prop>
            <prop key="hibernate.cache.use_query_cache">true</prop>
            <prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
        </props>
    </property>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
    </property>
</bean>

1 个答案:

答案 0 :(得分:2)

您的测试方法上有@Transactional注释,测试类上有@DataJpaTest(也就是@Transactional)。

由于只有一个交易,因此会有一个会话。当您在同一事务中访问同一个持久对象时,Hibernate使用一级缓存(会话缓存)。要在二级缓存中获得匹配,您应该具有不同的会话(不同的事务)。

使用@DataJpaTest简单替换@SpringBootTest并从测试方法中删除@Transactional可使测试生效。

另见: