如何在JUnit测试中强制命中我的二级缓存?

时间:2016-02-22 17:19:09

标签: java hibernate junit ehcache second-level-cache

我正在使用Hibernate 4.3.11.Final和随附的ehcache模块。我想在JUnit(v 4.11)测试中验证我的二级缓存配置正确,但我不知道如何强制这种情况。我有一个简单的方法来检索实体的id,即

public T findById(final Serializable id)
{
    T ret = null;
    if (id != null)
    {
        ret = (T) m_entityManager.find(persistentClass, id);
    }   // if
    return ret;
}

然后在我的JUnit测试中,我有了这个

@Test
public void testSecondLevelCache()
{
    long hitCount = m_cache.getStatistics().getCacheHits();

    final String countryId = m_testProps.getProperty("test.country.id");
    m_countryDao.findById(countryId);
    m_countryDao.findById(countryId);

然而,第二次调用击中了Hiberntae的第一级缓存,并且重复调用DAO方法也会遇到Hibernate的第一级缓存。如何强制命中二级缓存?

编辑:以下是我在Spring应用程序上下文中配置事务管理器和其他相关部分的方法......

<cache:annotation-driven />

<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheCacheManager"
p:cacheManager-ref="ehcache"/>

<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:configLocation="classpath:ehcache.xml"
p:shared="true" />

<util:map id="jpaPropertyMap">
    <entry key="hibernate.show_sql" value="true" />
    <entry key="hibernate.dialect" value="org.mainco.subco.core.jpa.SubcoMysql5Dialect" />
    <entry key="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory" />
    <entry key="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider" />
    <entry key="hibernate.cache.use_second_level_cache" value="true" />
    <entry key="hibernate.cache.use_query_cache" value="false" />
    <entry key="hibernate.generate_statistics" value="true" />
    <entry key="javax.persistence.sharedCache.mode" value="ENABLE_SELECTIVE" />
</util:map>

<bean id="sharedEntityManager"
    class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

1 个答案:

答案 0 :(得分:3)

最好使用不同的会话来避免第一级缓存。

首先,您需要从测试或类中删除@Transactional注释,以便手动控制事务。

其次,您编写测试以使用两个EntityManager个实例的连续事务。

@Test
public void testSecondLevelCache() {
    long hitCount = m_cache.getStatistics().getCacheHits();       
    final String countryId = m_testProps.getProperty("test.country.id");

    transactionTemplate.execute((TransactionCallback<Void>) transactionStatus -> {            
        m_countryDao.findById(countryId);
        return null;
    });

    transactionTemplate.execute((TransactionCallback<Void>) transactionStatus -> {
        m_countryDao.findById(countryId);
        return null;
    });
}