Spring Ehcache只有在相同请求中调用方法

时间:2018-01-21 08:53:22

标签: hibernate spring-mvc spring-data ehcache

我正在尝试缓存我的结果,但每次调用页面(刷新)都会命中数据库。任何帮助表示感谢,谢谢。

控制器

showPage(){
    MyPage<PhoneInfo> myPage = (MyPage<PhoneInfo>) phoneInfoService.findAllByOption(options, new MyPage<PhoneInfo>(page.intValue(), size.intValue()));
    //further experiment.. below does not hit db
    myPage = (MyPage<PhoneInfo>) phoneInfoService.findAllByOption(options, new MyPage<PhoneInfo>(page.intValue(), size.intValue()));
}

第二次调用service方法不会进行db调用,这是正确的。 但是,页面刷新再次调用showPage(),第一次调用服务再次调用db。我希望它来自缓存。

我测试了2个单元测试,两个测试都有相同的服务方法调用,测试1命中db而测试2跳过,这是正确的。测试中的多个服务调用也会被跳过,这也是正确的。

功能

  

Spring 4.3.3.RELEASE,Security 4.2.3.RELEASE,Hibernate 5.2.8.Final,   Ehcache 2.10.4

CacheConfig

@Configuration
@EnableCaching
public class CachingConfig {
    @Bean
    public CacheManager cacheManager(net.sf.ehcache.CacheManager cacheManager) {
        return new EhCacheCacheManager(cacheManager);
    }

    @Bean
    public EhCacheManagerFactoryBean ehCacheCacheManager() {
        EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean();
        cmfb.setConfigLocation(new ClassPathResource("ehcache.xml"));
        cmfb.setShared(true);
        return cmfb;
    }
}

的src /资源/ ehcache.xml中

<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xsi:noNamespaceSchemaLocation="ehcache.xsd"     updateCheck="true"  monitoring="autodetect"     dynamicConfig="true">

    <diskStore path="java.io.tmpdir" />

    <cache name="myPageCache"       maxEntriesLocalHeap="1000"      maxEntriesLocalDisk="10000"         eternal="false"         diskSpoolBufferSizeMB="20"      timeToIdleSeconds="86400" timeToLiveSeconds="86400"         overflowToDisk="false"      memoryStoreEvictionPolicy="LFU"         transactionalMode="off">        <persistence strategy="localTempSwap" />    </cache>

</ehcache>

更新1 列出下面的服务方法

Cacheable(value = "myPageCache", key = "{#options, #pageable}")
public MyPage<PhoneInfo>findAllByOption(PhoneOption options, MyPage<PhoneInfo> pageable){
    MyPage<PhoneInfo> myPage = phoneInfoRepoImpl.findAll(options, pageable);
    myPage.setTotalRows(_phoneInfoService.getCount(options, pageable));
    return myPage;
}

@Cacheable(value = "myPageCache", key = "#options")
public int getCount(PhoneOption options, MyPage<PhoneInfo> pageable){
    return phoneInfoRepoImpl.getCount(options, pageable);
}

更新2 单元测试

@Test
public void test1(){
    PhoneOption options = new PhoneOption();
    options.setName("239");
    options.setStatus('1');
    MyPage<PhoneInfo> myPage = phoneInfoService.findAllByOption(options, new MyPage<PhoneInfo>()); //hits db, Ok
    myPage = phoneInfoService.findAllByOption(options, new MyPage<PhoneInfo>()); //skips db, OK
    myPage = phoneInfoService.findAllByOption(options, new MyPage<PhoneInfo>(2, 20)); //hits db, OK as MyPage changed
}

@Test
public void test2(){
    PhoneOption options = new PhoneOption();
    options.setName("239");
    options.setStatus('1');
    MyPage<PhoneInfo> myPage = phoneInfoService.findAllByOption(options, new MyPage<PhoneInfo>()); //these options exactly same as Test1, skips db, OK!
    myPage = phoneInfoService.findAllByOption(options, new MyPage<PhoneInfo>()); //skips db, Ok
    myPage = phoneInfoService.findAllByOption(options, new MyPage<PhoneInfo>(2, 20)); //skips db, Ok
}

更新3 在所有测试对象中实现了hashCode和equals

现在在单元测试中它一直在击中db!所以行为恶化了。 hashcode对于相同/相同的对象是相同的,等于也正常工作,对于具有相似属性的对象返回true。

2 个答案:

答案 0 :(得分:1)

构成密钥的元素需要定义正确的equalshashcode,这样即使您最终得到不同的实例,相同的值也会导致正确的缓存命中。

答案 1 :(得分:0)

您的密钥"{#options, #pageable}"每次都会有新值,即使您在这些对象中传递相同的值集,因为它们在每次刷新页面后都是完全新对象。因此,他们每次在第一次通话时都会被缓存。为了避免这种情况,您需要更改密钥。尝试使用对象内的字段,如#object.field