3

複数のメソッドを持つサービスがあり、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>

これは既知の機能ですか、それともバグですか?

4

3 に答える 3

1

配列にハッシュまたは文字列表現を使用しても、キャッシュに関して一意性は定義されません。たとえば、配列に 2 つ以上の同一のエントリが含まれているか、順序が異なる場合: ハッシュ/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;
}
}

(上記のコードはテストされておらず、あらゆる種類の配列などに対してより一般的になる可能性があります...)

そして、その getCacheKey() メソッドを SPEL 式で使用します...

@Cacheable("myCache", key="#buildingCode.getCacheKey()") 
public Collection<Building> findBuildingByCode(BuildCodesCacheWrapper buildingCode) {...}
于 2013-08-01T20:46:10.273 に答える