Ключевые проблемы кэширования с Jcache
Я использую JSR107 кеширование с Springboot. У меня есть следующий метод.
@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 без учета кэша?
При отладке пружинных классов было установлено, что org.springframework.cache.interceptor.SimpleKeyGenerator используется с генерацией ключа кэша, даже если @CacheResult существует. РЕДАКТИРОВАТЬ и усилить вопрос:
Кроме того, если getAllBooks имеет перегруженные методы, а затем вызывает этот кэшированный метод с помощью отдельного перегруженного метода, в этом случае также не работает кэширование метода.
2 ответа
Как предложил @Henri, мы можем использовать кеш-данные. Но для этого нам нужны методы. Ниже мы можем обновить кеш, очень похожий на кеш-память,
// перегруженный метод доступен как 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);
// перегружен только метод
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();
// Правильно (это с весны)
Object cacheKey = SimpleKeyGenerator.generateKey(bookIdCatCache.toArray(new Object[bookIdCatCache.size()]));
Я не эксперт по аннотациям JSR107 в контексте Spring. Вместо этого я использую аннотации Spring Cache.
При использовании JSR107 используется ключ GeneratedCacheKey
, Так вот что вы должны поместить в свой кеш. Не toString()
этого Обратите внимание, что SimpleKeyGenerator
не возвращает GeneratedCacheKey
, Возвращает SimpleKey
который является ключом, используемым Spring при использовании его собственных аннотаций кэша вместо JSR-107. Для JSR-107 вам нужен SimpleGeneratedCacheKey
,
Затем, если вы хотите предварительно загрузить кеш, просто позвоните getAllBooks
прежде чем это нужно.
Если вы хотите предварительно загрузить кэш другим способом, @javax.cache.annotation.CachePut
должен сделать свое дело. Смотрите его Javadoc для примера.