【问题标题】:Cache Evict issue with @Cacheable parameterless method@Cacheable 无参数方法的缓存驱逐问题
【发布时间】:2020-04-24 11:59:28
【问题描述】:

我正在尝试在 Spring Boot RESTful 服务中实现 Spring 缓存。这是 getAllBlogs() 和 getBlogById() 方法的缓存代码。

@Cacheable(value="allblogcache")
@Override
public List<Blog> getAllBlogs() {
    System.out.println("******* "+ blogRepository.findAll().toString());
    return (List<Blog>) blogRepository.findAll();

}

@Cacheable(value="blogcache", key = "#blogId")
@Override
public Blog getBlogById(int blogId) {
    Blog retrievedBlog = null;
    retrievedBlog = blogRepository.findById(blogId).get();
    return retrievedBlog;
}

在 saveBlog 方法中,我想清除缓存并使用了以下代码。

 @Caching(evict = {
        @CacheEvict(value="allblogcache"),
        @CacheEvict(value="blogcache", key = "#blog.blogId")
  })
  @Override
  public Blog saveBlog(Blog blog) {
    return blogRepository.save(blog);
  }

在运行时,我使用 Postman 执行了以下操作:

  1. 保存了两个博客。两个博客都被保存到数据库中。
  2. 调用获取所有博客。两个保存的博客都被返回。
  3. 保存了一个新博客。在这里,我假设缓存已被驱逐。
  4. 我调用了获取所有博客。但是,只有两个博客被返回。这 表示博客是从旧缓存中返回的。它没有被驱逐 调用第三次保存。

github repo 位于https://github.com/ximanta/spring-cache

【问题讨论】:

    标签: spring-boot spring-cache


    【解决方案1】:

    如果您在不指定键的情况下驱逐缓存,则需要添加allEntries = true 属性(请参阅docs)。

    在你的情况下,应该是@CacheEvict(value="allblogcache", allEntries = true)

    附:对其进行了测试并设法使其工作。公关:https://github.com/ximanta/spring-cache/pull/1

    【讨论】:

    • 谢谢。这解决了:) 你的一个意见。在 getAllBlogs() 的测试中,我在 service 上调用了 save() 两次,然后在 service 上调用了 getAllBlogs() 多次。在验证模拟存储库交互时,我发现存储库模拟发生了两次交互。验证(blogRepository,次(2)).findAll();我期待 1。因为第一次 getAll() 将从数据库中检索,然后从第二次开始,从缓存中检索。但是它出现了,它从数据库中检索了两次,从第三次调用开始从缓存中检索。我推送了代码。您对此有何看法?
    • 那是因为你在getAllBlogs()里面调用了findAll()方法twice
    • @amsagar 这就是我要提出的观点。第二个 findAll() 应该从缓存中返回,而不是调用存储库。
    • 这是不正确的 - 你将getAllBlogs() 标记为可缓存的,所以如果在外面的某个地方调用它,它应该只执行一次。这不会影响其内部调用(例如,blogRepository.findAll() 调用)。
    【解决方案2】:

    它抛出异常是因为你使用了错误的键表达式:

    @Caching(evict = {
        @CacheEvict(value="allblogcache"),
        @CacheEvict(value="blogcache", key = "#blogId")
                                             ~~~~~~~~~~ => Refer to parameter blogId but not found
    })
    public Blog saveBlog(Blog blog)
    

    正确的表达方式是:

    @Caching(evict = {
        @CacheEvict(value="allblogcache"),
        @CacheEvict(value="blogcache", key = "#blog.id") // Assume that the property for blog ID is "id"
    })
    public Blog saveBlog(Blog blog)
    

    【讨论】:

    • 谢谢曼。根据您的建议,我能够修复错误,但缓存驱逐的核心问题仍然存在。我已经编辑了这个问题。请看一下并提出建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-20
    • 1970-01-01
    • 2017-08-02
    • 1970-01-01
    • 2017-06-17
    • 1970-01-01
    相关资源
    最近更新 更多