Spring Cache Evict不起作用

时间:2016-05-03 16:48:38

标签: java spring caching

执行方法时,我遇到干净缓存问题。 这是我的配置和缓存方法:

@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;
}

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

3 个答案:

答案 0 :(得分:3)

您从哪里调用save()方法?

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

因此我的问题:你知道spring aop proxy吗?您必须从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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

我找到了解决问题的方法。我不得不将注释上移到spring数据jpa interace。

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 {
}