JPA + Spring + Hibernate + DBUnit:可缓存查询:如何强制重载?

时间:2013-12-28 02:04:50

标签: spring hibernate jpa ehcache dbunit

我正在尝试设置我的项目在junit模式下使用带有Spring + hibernate的缓存(ehcache),以及Spring + hibernate + JTA(Glassfish)。

这里是我的spring-hiberrnate配置为junit

<bean id="cacheManager" 
    class="org.springframework.cache.ehcache.EhCacheCacheManager">
        <property name="cacheManager" ref="springEhcache"/>
</bean>
<bean id="springEhcache" 
    class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <property name="cacheManagerName" value="method-cache" />
</bean>

<!-- Config Database: ImageManager -->
<bean id="propertyConfigurer"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
    p:location="/jdbc.properties" />

<bean id="dataSource"
    class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
    p:driverClassName="${jdbc.driverClassName}"
    p:url="${jdbc.databaseurl}" p:username="${jdbc.username}"
    p:password="${jdbc.password}" />


<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation">
        <value>classpath:hibernate.cfg.xml</value>
    </property>
    <property name="configurationClass">
        <value>org.hibernate.cfg.AnnotationConfiguration</value>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${jdbc.dialect}</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.generate_statistics">true</prop>
            <prop key="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory</prop>
            <prop key="hibernate.cache.use_second_level_cache">true</prop>
            <prop key="hibernate.cache.use_query_cache">true</prop>
            <prop key="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</prop>
        </props>
    </property>
</bean>

<tx:annotation-driven />

<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean> 

我用@Cachable注释了一些实体(只有我想要缓存的实体)

@Cacheable
@Entity
@Table(name = "PLATFORM")
public class Plaform ...

我设置了一些查询:setCacheable(true)。

@Transactional(readOnly = true)
    public List<Platform> listPlatform() {
        return sessionFactory.getCurrentSession().createQuery("from Platform").setCacheable(true).list();
    }

我有一个带有@PostConstruct

的对象(名为CacheMap)

将加载一些查询并填充少量Map。

当我在junit吃午餐时,我的CacheMap对象将获取一些数据,之后DBUnit将插入一组数据。

问题是当我调用listPlatform时它返回空,因为查询首先被称为我的CacheMap。有一种方法可以告诉Hibernate使当前缓存无效吗?

编辑:

我在插入后通过DBunit添加了此代码,但是当我重新运行查询时,它是返回的缓存值。

for (String name : cacheManager.getCacheNames()) {
    cacheManager.getCache(name).clear();
}

编辑2.我删除建议的行并用

替换它们
sessionFactory.getCache().evictQueryRegions();
sessionFactory.getCache().evictDefaultQueryRegion();

并从我的配置中删除Spring缓存,现在它适用于Query,但没有实体进入缓存级别2.我将继续我的测试并发布完整的解决方案。

这里有统计数据:

没有CACHE 统计=统计[开始时间= 1388275898144,会话开启= 16,会话关闭= 16,交易= 32,成功交易= 16,乐观锁定失败= 0,刷新= 87,获得连接= 16,语句准备= 1518,报表关闭= 1518,二级缓存put = 0,二级缓存命中= 0,二级缓存未命中= 0,实体已加载= 943,实体已更新= 3,实体已插入= 334,实体已删除= 0,实体已获取= 64,集合loaded = 459,集合已更新= 149,集合已删除= 0,集合已重新创建= 200,集合已取出= 459,查询已执行到数据库= 422,查询缓存放置= 0,查询缓存命中数= 0,查询缓存未命中数= 0,最大值查询时间= 321]

使用CACHE 统计=统计[开始时间= 1388275940458,会话开启= 16,会话关闭= 16,事务= 32,成功事务= 16,乐观锁定失败= 0,刷新= 84,获得连接= 16,语句准备= 1341,语句已关闭= 1341,二级缓存put = 0,二级缓存命中= 0,二级缓存未命中= 0,实体已加载= 841,实体已更新= 3,实体已插入= 334,实体已删除= 0,实体已获取= 93,集合loaded = 403,集合已更新= 149,集合已删除= 0,集合已重新创建= 200,集合已取出= 293,查询已执行到数据库= 382,查询缓存放置= 231,查询缓存命中数= 40,查询缓存未命中数= 231,最大值查询时间= 137]

编辑3:

我找到了如何将实体缓存到二级缓存中。当我缓存实体时,它似乎变慢了。

缓存:读写 统计=统计[开始时间= 1388278575470,会话开启= 16,会话关闭= 16,交易= 32,成功交易= 16,乐观锁定失败= 0,刷新= 84,获得连接= 16,语句准备= 1377,语句已关闭= 1377,二级缓存puts = 37,二级缓存命中= 77,二级缓存未命中= 2,实体已加载= 764,实体已更新= 3,实体已插入= 334,实体已删除= 0,实体已获取= 38,集合loaded = 403,集合已更新= 149,集合已删除= 0,集合已重新创建= 200,集合已取出= 403,查询已执行到数据库= 363,查询缓存放置= 233,查询缓存命中数= 59,查询缓存未命中数= 233,最大值查询时间= 161]

没有实体缓存 统计=统计[开始时间= 1388278655759,会话开启= 16,会话关闭= 16,交易= 32,成功交易= 16,乐观锁定失败= 0,刷新= 84,获得连接= 16,语句准备= 1333,语句已关闭= 1333,二级缓存put = 0,二级缓存命中= 0,二级缓存未命中= 0,实体已加载= 841,实体已更新= 3,实体已插入= 334,实体已删除= 0,实体已获取= 104,集合loaded = 403,集合已更新= 149,集合已删除= 0,集合已重新创建= 200,集合已取出= 293,查询已执行到数据库= 363,查询缓存放置= 233,查询缓存命中数= 59,查询缓存未命中数= 233,最大值查询时间= 147]

这是我的ehcache.xml

<ehcache>
    <diskStore path="./resource"/>
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU"
    />

    <cache name="org.hibernate.cache.StandardQueryCache"
        maxElementsInMemory="20"
        eternal="false"
        timeToLiveSeconds="120"
        overflowToDisk="false"/>

    <cache name="org.hibernate.cache.UpdateTimestampsCache"
        maxElementsInMemory="1000"
        eternal="true"
        overflowToDisk="false"/>
</ehcache>

这里是我的pom(它的一部分)

<properties>
    <spring.version>3.2.5.RELEASE</spring.version>
    <hibernate.version>3.6.9.Final</hibernate.version>
</properties>

<!-- Spring 3 dependencies -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${spring.version}</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>${spring.version}</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>${hibernate.version}</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>${hibernate.version}</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-ehcache</artifactId>
    <version>${hibernate.version}</version>
</dependency>
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache-core</artifactId>
    <version>2.6.6</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-annotations</artifactId>
    <version>3.5.6-Final</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.dbunit</groupId>
    <artifactId>dbunit</artifactId>
    <version>2.4.9</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.xbean</groupId>
    <artifactId>xbean-spring</artifactId>
    <version>3.7</version>
</dependency>

2 个答案:

答案 0 :(得分:0)

您需要获取cacheManager,然后获取所有缓存并将其删除。

下面的代码示例将为您提供有关如何实现此目标的建议:

EhCacheCacheManager cacheManager;   // injected cacheManger

String[] names = cacheManager.getCacheNames();

for (String name : names)
{
    Cache cache = cacheManager.getCache(name);

    cache.removeAll();
}

答案 1 :(得分:0)

我必须这样做

currentSessionFactory = sessionFactory;
sessionFactory.getStatistics().isStatisticsEnabled();

try {
    sessionFactory.getCache().evictQueryRegions();
    sessionFactory.getCache().evictDefaultQueryRegion();
} catch (Exception e) {
}

并重新加载我的实体。工作正常。

我的实体也在hibernate.xml

<class-cache usage="read-write" class="entity.Platform" />