Jcache的缓存关键问题

Cache key issues with Jcache

我在 Springboot 中使用 JSR107 缓存。我有以下方法。

@CacheResult(cacheName = "books.byidAndCat")
public List<Book> getAllBooks(@CacheKey final String bookId, @CacheKey final BookCategory bookCat) {

return <<Make API calls and get actual books>>
}

第一次它进行实际的 API 调用,第二次它加载缓存没有问题。我可以看到日志的以下部分。

Computed cache key SimpleKey [cb5bf774-24b4-41e5-b45c-2dd377493445,LT] for operation CacheResultOperation[CacheMethodDetails ...

但问题是我想在不进行第一次 API 调用的情况下加载缓存,只需要像下面那样填充缓存。

String cacheKey  = SimpleKeyGenerator.generateKey(bookId, bookCategory).toString();     
        cacheManager.getCache("books.byidAndCat").put(cacheKey, deviceList);

当我检查时,缓存键的哈希码在两种情况下都相同,但它正在调用 API。如果两种情况下的哈希码都相同,为什么它在不考虑缓存的情况下进行 API 调用?

调试时 spring 类 发现,org.springframework.cache.interceptor.SimpleKeyGenerator 与缓存键生成一起使用,即使 @CacheResult 在那里。 编辑并增强问题:

除此之外如果 getAllBooks 有重载方法,然后通过单独的重载方法调用这个缓存的方法,在这种情况下方法缓存也不起作用。

我不是 Spring 上下文中的 JSR107 注释专家。我改用 Spring 缓存注释。

使用JSR107时,使用的key是GeneratedCacheKey。所以这就是您应该放入缓存中的内容。不是它的toString()。请注意,SimpleKeyGenerator 不会返回 GeneratedCacheKey。它 returns 一个 SimpleKey 这是 Spring 在使用自己的缓存注释而不是 JSR-107 时使用的键。对于 JSR-107,您需要 SimpleGeneratedCacheKey.

然后,如果要预加载缓存,只需在需要之前调用getAllBooks即可。

如果您想以其他方式预加载缓存,@javax.cache.annotation.CachePut 应该可以解决问题。有关示例,请参见其 javadoc。

正如@Henri 所建议的,我们可以使用 cacheput。但为此我们需要方法。使用下面我们可以更新缓存非常类似于 cacheput,

//id和cat都可用的重载方法

List<Object> bookIdCatCache = new ArrayList<>();
    bookIdCatCache.add(bookId);
    bookIdCatCache.add(deviceCat);
    Object bookIdCatCacheKey  = SimpleKeyGenerator.generateKey(bookIdCatCache.toArray(new Object[bookIdCatCache.size()]));
    cacheManager.getCache("books.byidAndCat").put(bookIdCatCacheKey , bookListWithIdAndCat);

//重载方法只有id存在

List<Object> bookIdCache = new ArrayList<>();
        String nullKey          = null
        bookIdCache.add(bookId);
        bookIdCache.add(nullKey);
        Object bookIdCacheKey  = SimpleKeyGenerator.generateKey(bookIdCache.toArray(new Object[bookIdCache.size()]));
        cacheManager.getCache("books.byidAndCat").put(bookIdCacheKey , bookListWithId);

//不正确(我之前的实现)

String cacheKey  = SimpleKeyGenerator.generateKey(bookId, bookCategory).toString();

//正确(这是从spring得到的)

Object cacheKey  = SimpleKeyGenerator.generateKey(bookIdCatCache.toArray(new Object[bookIdCatCache.size()]));