简体   繁体   中英

JPA + Spring + Hibernate + DBUnit : cacheable query : how force reload?

I'm trying to setup my project to use cache (ehcache) with Spring + hibernate in junit mode, and Spring+hibernate+JTA (Glassfish).

here my spring-hiberrnate config for 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> 

I annotated some Entity with @Cachable (only entity that I want cached)

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

and I set some query : setCacheable(true).

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

and I have a object (named CacheMap) with @PostConstruct

that will load some query and populate few Map.

When I lunch my junit my CacheMap object will fetch some data, and after that DBUnit will insert a set of data.

The problem is when I call listPlatform it returns empty, because the query was first called my CacheMap. There is a way to tell Hibernate to invalidate the current cache ?

EDIT :

I added this code like suggested after the insert via DBunit, but when I rerun my query, it's the cached values that are returns.

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

EDIT 2. I remove the lines suggested and replace them with

sessionFactory.getCache().evictQueryRegions();
sessionFactory.getCache().evictDefaultQueryRegion();

and remove Spring cache from my config and now it works for Query, but no Entity are put into Cache Level 2. I'll continue my tests and post a complete solution.

Here the statistics :

NO CACHE Statistics=Statistics[start time=1388275898144,sessions opened=16,sessions closed=16,transactions=32,successful transactions=16,optimistic lock failures=0,flushes=87,connections obtained=16,statements prepared=1518,statements closed=1518,second level cache puts=0,second level cache hits=0,second level cache misses=0,entities loaded=943,entities updated=3,entities inserted=334,entities deleted=0,entities fetched=64,collections loaded=459,collections updated=149,collections removed=0,collections recreated=200,collections fetched=459,queries executed to database=422,query cache puts=0,query cache hits=0,query cache misses=0,max query time=321]

With CACHE Statistics=Statistics[start time=1388275940458,sessions opened=16,sessions closed=16,transactions=32,successful transactions=16,optimistic lock failures=0,flushes=84,connections obtained=16,statements prepared=1341,statements closed=1341,second level cache puts=0,second level cache hits=0,second level cache misses=0,entities loaded=841,entities updated=3,entities inserted=334,entities deleted=0,entities fetched=93,collections loaded=403,collections updated=149,collections removed=0,collections recreated=200,collections fetched=293,queries executed to database=382,query cache puts=231,query cache hits=40,query cache misses=231,max query time=137]

EDIT 3 :

I found how to cache Entity into Level 2 Cache. It's seem slower when I cached the entity.

cache :read-write Statistics=Statistics[start time=1388278575470,sessions opened=16,sessions closed=16,transactions=32,successful transactions=16,optimistic lock failures=0,flushes=84,connections obtained=16,statements prepared=1377,statements closed=1377,second level cache puts=37,second level cache hits=77,second level cache misses=2,entities loaded=764,entities updated=3,entities inserted=334,entities deleted=0,entities fetched=38,collections loaded=403,collections updated=149,collections removed=0,collections recreated=200,collections fetched=403,queries executed to database=363,query cache puts=233,query cache hits=59,query cache misses=233,max query time=161]

No entity cache Statistics=Statistics[start time=1388278655759,sessions opened=16,sessions closed=16,transactions=32,successful transactions=16,optimistic lock failures=0,flushes=84,connections obtained=16,statements prepared=1333,statements closed=1333,second level cache puts=0,second level cache hits=0,second level cache misses=0,entities loaded=841,entities updated=3,entities inserted=334,entities deleted=0,entities fetched=104,collections loaded=403,collections updated=149,collections removed=0,collections recreated=200,collections fetched=293,queries executed to database=363,query cache puts=233,query cache hits=59,query cache misses=233,max query time=147]

Here my 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>

here my pom (a part of it)

<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>

You need to get your cacheManager, then fetch all the caches and remove them.

Below code sample will give you idea on how to achieve this:

EhCacheCacheManager cacheManager;   // injected cacheManger

String[] names = cacheManager.getCacheNames();

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

    cache.removeAll();
}

I had to do that

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

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

and reload my entities. Works fine.

I also have my entity in hibernate.xml

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM