2016-05-03 144 views
3

嗨我有方法執行時乾淨的緩存問題。 這裏是我的配置和高速緩存方法:Spring Cache Evict不起作用

@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) 但它也不起作用。你可以幫幫我嗎?

回答

0

您需要在NewsMessage類中使用公共的RssType getType()方法。 @CacheEvict註釋中的關鍵表達式「#news.type」期望一個名爲「type」的公共字段或一個名爲「getType」的公共getter方法。

+0

我有以下的getter: \t公共RssType的getType(){ \t \t返回類型; \t} 所以它應該很好。但請注意,allEntires = true的cacheEvict也不起作用。 – Pulkownik

0

我找到了解決我的問題的方法。我不得不將註釋上移到彈簧數據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 { 
} 
2

從哪裏調用save()方法?

在你自己的答案,它看起來像你已經將註釋移動到另一個類/接口來調用該類/接口的代理對象(順便說一下,註釋通常不應該在接口中使用,因爲它們通常不會被捕獲機智默認配置)。

因此我的問題:你知道春季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

+0

你是對的,我想知道春季代理的概念。感謝您的鏈接。 – Pulkownik