【问题标题】:Spring Cache Evict does not workSpring Cache Evict 不起作用
【发布时间】:2016-08-28 20:04:49
【问题描述】:

您好,我在执行方法时遇到了清理缓存的问题。 这是我的配置和缓存方法:

@Configuration
@EnableCaching
@AutoConfigureAfter(value = {MetricsConfiguration.class, DatabaseConfiguration.class})
@Profile("!" + Constants.SPRING_PROFILE_FAST)
public class CacheConfiguration {

    private final Logger log = LoggerFactory.getLogger(CacheConfiguration.class);
    public static final String STOCK_DETAILS_BY_TICKER_CACHE = "stockDetailsByTickerCache";
    public static final String RSS_NEWS_BY_TYPE_CACHE = "rssNewsByTypeCache";

    @Bean
    public CacheManager cacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        List<Cache> caches = new ArrayList<Cache>();
        caches.add(new ConcurrentMapCache(STOCK_DETAILS_BY_TICKER_CACHE));
        caches.add(new ConcurrentMapCache(RSS_NEWS_BY_TYPE_CACHE));
        cacheManager.setCaches(caches);
        return cacheManager;
    }
}

我要缓存的这个方法:

@Cacheable(cacheNames = CacheConfiguration.RSS_NEWS_BY_TYPE_CACHE, key = "#type")
    public ResponseEntity<List<NewsDetailsDTO>> getLatestNewsMessageByType(RssType type) {
        Pageable pageable = new PageRequest(0, 5, Sort.Direction.DESC, "createdDate");
        List<NewsMessage> latestNewsMessage = newsMessageRepository.findByType(type, pageable).getContent();
        return new ResponseEntity<List<NewsDetailsDTO>>(mapToDTO(latestNewsMessage), HttpStatus.OK);
    }

在执行此方法时,我想按类型清理缓存:

@CacheEvict(cacheNames={CacheConfiguration.RSS_NEWS_BY_TYPE_CACHE}, beforeInvocation = true, key = "#news.type")
    public void save(NewsMessage news) {
        newsMessageRepository.save(news);
    }

NewsMessage 对象看起来像:

@Entity
@Table(name = "NEWS_MESSAGE")
public class NewsMessage extends ChatMessage {

    <other fileds>

    @NotNull
    @Enumerated(EnumType.STRING)
    private RssType type;
}

缓存工作正常,第一次查询到数据库第二次,然后从缓存中获取数据。问题是当我更新数据时,@CacheEvict 不会清理缓存。我试图使用此注释清理所有缓存: @CacheEvict(cacheNames={CacheConfiguration.RSS_NEWS_BY_TYPE_CACHE}, allEntries = true) 但它也不起作用。你能帮帮我吗?

【问题讨论】:

    标签: java spring caching


    【解决方案1】:

    从哪里调用save() 方法?

    在您自己的答案中,您似乎已将注释移动到另一个类/接口以调用该类/接口的代理对象(顺便说一句,通常不应在接口中使用注释,因为它们通常不会被捕获默认配置)。

    因此我的问题是:你知道spring aop代理吗?您必须从 MessageRepository 类之外的方法调用带注释的方法来调用代理对象。

    一般文档在这里:http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#aop-understanding-aop-proxies

    或者这里有例子http://spring.io/blog/2012/05/23/transactions-caching-and-aop-understanding-proxy-usage-in-spring

    【讨论】:

    • 你说得对,我想念spring proxy的概念。感谢您的链接。
    【解决方案2】:

    我找到了解决问题的方法。我不得不将注释上移到弹簧数据 jpa 接口。

    public interface NewsMessageRepository extends JpaRepository<NewsMessage, Long> {
    
        @CacheEvict(cacheNames = {CacheConfiguration.RSS_NEWS_BY_TYPE_CACHE}, beforeInvocation = true, key = "#p0.type")
        NewsMessage save(NewsMessage news);
    }
    

    现在它按我的预期工作,但仍然不知道为什么它在我的服务中不起作用。可能是因为我的服务实现了两个接口?

    @Service
    public class NewsMessageService implements RssObserver, NewsMessageServiceable {
    }
    

    【讨论】:

      【解决方案3】:

      您需要在 NewsMessage 类中使用公共 RssType getType() 方法。 @CacheEvict 注释中的键表达式“#news.type”需要一个名为“type”的公共字段或一个名为“getType”的公共 getter 方法。

      【讨论】:

      • 我有以下吸气剂: public RssType getType() { return type;所以它应该可以正常工作。但请注意 allEntires=true 的 cacheEvict 也不起作用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-27
      • 2011-08-14
      • 1970-01-01
      相关资源
      最近更新 更多