2014-07-24 79 views
6

我與春的Ehcache如何更新/刪除項目的項目集合

工作中已經被緩存我有以下方法

@Override 
@Cacheable(value="products", key="#root.target.PRODUCTS") 
public Set<Product> findAll() { 
    return new LinkedHashSet<>(this.productRepository.findAll()); 
} 

我有@Cacheable和@CachePut工作的其他方法和@CacheEvict。

現在,想象中的數據庫返回100個產品,且它們通過key="#root.target.PRODUCTS"緩存,那麼其他方法將插入 - 更新 - 刪除一個項目到數據庫中。因此,通過key="#root.target.PRODUCTS"緩存的產品不再像數據庫那樣相同。

我的意思是,檢查兩個以下兩種方法,他們能夠更新/刪除項目,而同一項目在其他key="#root.target.PRODUCTS"

@Override 
@CachePut(value="products", key="#product.id") 
public Product update(Product product) { 
    return this.productRepository.save(product); 
} 

@Override 
@CacheEvict(value="products", key="#id") 
public void delete(Integer id) { 
    this.productRepository.delete(id); 
} 

我想知道是否有可能被緩存通過key="#root.target.PRODUCTS"更新/刪除位於緩存中的項目,如果產品已刪除,它將爲100,產品已更新或499。

我想說的是,我要避免以下:

@Override 
@CachePut(value="products", key="#product.id") 
@CacheEvict(value="products", key="#root.target.PRODUCTS") 
public Product update(Product product) { 
    return this.productRepository.save(product); 
} 

@Override 
@Caching(evict={ 
     @CacheEvict(value="products", key="#id"), 
     @CacheEvict(value="products", key="#root.target.PRODUCTS") 
}) 
public void delete(Integer id) { 
    this.productRepository.delete(id); 
} 

我不想再次調用500級或499的產品被緩存到key="#root.target.PRODUCTS"

有可能做到這一點?怎麼樣?

在此先感謝。

回答

5

使用緩存抽象緩存集合是底層緩存系統正在做什麼的副本。而且因爲這是重複的,事實證明你必須以某種方式或某種方式在你自己的代碼中使用某種重複(這個集合的重複鍵是這種重複的表示)。並且由於存在重複,您必須以某種方式同步狀態

如果您確實需要訪問整個集合和單個元素,那麼您應該使用最簡單的路徑的快捷方式。首先,你應該確保你的緩存包含所有不明顯的元素。實際上遠非如此。考慮到你有:

//EhCacheCache cache = (EhCacheCache) cacheManager.getCache("products"); 


@Override 
public Set<Product> findAll() { 
    Ehcache nativeCache = cache.getNativeCache(); 
    Map<Object, Element> elements = nativeCache.getAll(nativeCache.getKeys()); 
    Set<Product> result = new HashSet<Product>(); 
    for (Element element : elements.values()) { 
     result.add((Product) element.getObjectValue()); 
    } 
    return Collections.unmodifiableSet(result); 
} 

elements結果實際上是一個延遲加載地圖,以便於values()通話可能會拋出異常。你可能想循環使用鍵或其他東西。

您必須記住,緩存抽象簡化了對底層緩存基礎設施的訪問,並且絕不會取代它:如果您必須直接使用API​​,這可能是您在某種情況下必須執行的操作。

現在,如果您認爲我們可以改進該區域的緩存抽象,那麼我們可以在SPR-12036之後繼續進行轉換。謝謝!

+0

謝謝Stephane,我要通過JIRA保持對話。 –

1

我覺得像這樣的東西可以工作......其實這只是一個變化,如果「StéphaneNic​​oll」回答當然,但它可能對某人有用。我在這裏寫它,並沒有在IDE中檢查它,但在我的項目中有類似的作品。

  1. 覆蓋CacheResolver:

    @Cacheable(value="products", key="#root.target.PRODUCTS", cacheResolver = "customCacheResolver") 
    
  2. 在那裏

    public class CustomCacheResolver implements CacheResolver{ 
        private static final String CACHE_NAME = "products"; 
        @Autowired(required = true) private CacheManager cacheManager; 
    
    @SuppressWarnings("unchecked") 
    @Override 
    public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> cacheOperationInvocationContext) { 
        // 1. Take key from query and create new simple key 
        SimpleKey newKey; 
        if (cacheOperationInvocationContext.getArgs().length != null) { //optional 
        newKey = new SimpleKey(args); //It's the key of cached object, which your "@Cachable" search for   
        } else { 
        //Schould never be... DEFAULT work with cache if something wrong with arguments 
        return new ArrayList<>(Arrays.asList(cacheManager.getCache(CACHE_NAME))); 
        } 
    
        // 2. Take cache 
        EhCacheCache ehCache = (EhCacheCache)cacheManager.getCache(CACHE_NAME); //this one we bringing back     
        Ehcache cache = (Ehcache)ehCache.getNativeCache(); //and with this we working   
        // 3. Modify existing Cache if we have it 
        if (cache.getKeys().contains(newKey) && YouWantToModifyIt) { 
        Element element = cache.get(key); 
        if (element != null && !((List<Products>)element.getObjectValue()).isEmpty()) { 
        List<Products> productsList = (List<Products>)element.getObjectValue(); 
        // ---**--- Modify your "productsList" here as you want. You may now Change single element in this list.     
        ehCache.put(key, anfragenList); //this method NOT adds cache, but OVERWRITE existing        
        // 4. Maybe "Create" new cache with this key if we don't have it 
        } else { 
        ehCache.put(newKey, YOUR_ELEMENTS); 
        } 
        return new ArrayList<>(Arrays.asList(ehCache)); //Bring all back - our "new" or "modified" cache is in there now... 
    } 
    

更多實現你自己的緩存解析器,其中搜索 「裏面」 你緩存的項目,做的工作關於EhCache的CRUD:EhCache code samples

希望它有幫助。對不起,我的英語:(