使用数组参数在Spring上缓存

时间:2013-08-01 17:57:44

标签: java spring ehcache spring-annotations

我有多个方法的服务,并尝试使用Spring @Cacheable注释来缓存它们。一切正常,但我发现没有缓存带有数组作为方法参数的方法。考虑到数组可以包含不同的值,这有点合理,但我仍然认为它是可能的。

缓存以下方法:

@Cacheable("myCache")
public Collection<Building> findBuildingByCode(String buildingCode) {...}

@Cacheable("myCache")
public Collection<Building> getBuildings() {...}

但是,如果我将findBuildingByCode方法更改为以下任一方法,则不会缓存它:

@Cacheable("myCache") 
public Collection<Building> findBuildingByCode(String[] buildingCode) {...}

@Cacheable("myCache")
public Collection<Building> findBuildingByCode(String... buildingCode) {...}

以下是相关的 Spring xml 配置:

<!-- Cache beans -->
<cache:annotation-driven/>

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

<!-- EhCache library setup -->
<bean id="ehcache"
    class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />

Ehcache 配置:

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

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

<!-- Default settings -->
<defaultCache eternal="false" maxElementsInMemory="1"
    overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0"
    timeToLiveSeconds="100" memoryStoreEvictionPolicy="LRU" />

<!-- Other caches -->

<cache name="myCache" eternal="false" maxElementsInMemory="500"
    overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0"
    timeToLiveSeconds="43200" memoryStoreEvictionPolicy="LRU" />

 </ehcache>

这是已知功能还是错误?

2 个答案:

答案 0 :(得分:4)

尝试像这样定义缓存键:

@Cacheable(value="myCache", key="#buildingCode.toString()")

#buildingCode.hashCode()。因此缓存管理器将能够缓存该方法。

答案 1 :(得分:1)

对数组使用散列或字符串表示不会在缓存方面定义唯一性。例如,数组包含2个或更多相同的条目或具有不同的顺序:hash / toString将不同......但缓存键可能应该相同。 我要做的是在你的数组周围创建一个包装器...并创建一个getCacheKey(),它可以做任何你需要做的事情......

public class BuildCodesCacheWrapper {
private String[] buildingCodes;

private BuildCodesCacheWrapper(String[] buildingCodes) {
    super();
    this.buildingCodes = buildingCodes;
}

public String getCacheKey(){
    String key = "";
    if(null != buildingCodes){
        for(String code : buildingCodes){
            if(!key.contains("")){
                key += code;
            }
        }
    }
    return key;
}
}

(上面的代码没有经过测试,可以对所有类型的数组等更通用......)

在SPEL表达式中使用getCacheKey()方法......

@Cacheable(“myCache”,key =“#buildingCode.getCacheKey()”) public Collection findBuildingByCode(BuildCodesCacheWrapper buildingCode){...}