如何更新/删除已在项集合中缓存的项目

Man*_*dan 9 spring caching ehcache spring-3 spring-cache

我正在使用Spring和EhCache

我有以下方法

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

我有其他使用@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);
}
Run Code Online (Sandbox Code Playgroud)

我想知道是否可以通过更新/删除位于缓存中的项目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);
}
Run Code Online (Sandbox Code Playgroud)

我不想再打电话给500或499产品缓存到 key="#root.target.PRODUCTS"

这可能吗?怎么样?

提前致谢.

Ste*_*oll 6

使用缓存抽象缓存集合与底层缓存系统正在执行的操作重复.并且因为这是重复的,事实证明你必须以某种方式在你自己的代码中使用某种重复(该集合的重复键是其明显的表示).因为有重复,你必须以某种方式同步状态

如果你真的需要访问整个集合和单个元素,那么你应该使用最简单的一条快捷方式.首先,您应该确保您的缓存包含所有不明显的元素.实际上远非如此.考虑到你有:

//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);
}
Run Code Online (Sandbox Code Playgroud)

elements结果实际上是一个延迟加载地图,以便调用values()可能会抛出异常.您可能想要循环键或其他东西.

您必须记住,缓存抽象可以简化对底层缓存基础结构的访问,并且绝不会替换它:如果您必须直接使用API​​,这可能是您在某种程度上必须执行的操作.

现在,如果您认为我们可以改进该领域的缓存抽象,我们可以保留SPR-12036的转换.谢谢!


Rus*_*zov 5

我认为这样的事情应该有效......实际上,如果“Stéphane Nicoll”回答ofcourse,这只是一个变体,但它可能对某人有用。我写在这里,没有在 IDE 中检查它,但在我的项目中类似的东西。

  1. 覆盖 CacheResolver:

    @Cacheable(value="products", key="#root.target.PRODUCTS", cacheResolver = "customCacheResolver")
    
    Run Code Online (Sandbox Code Playgroud)
  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...
    }
    
    Run Code Online (Sandbox Code Playgroud)

阅读更多关于 EhCache 的 CRUD:EhCache 代码示例

希望能帮助到你。对不起我的英语:(