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()]));
我在 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()]));