Как кэшировать результаты метода запроса Spring Data JPA без использования кэша запросов?
у меня есть приложение Spring Boot с классами репозитория Spring Data JPA (hibernate backend). Я добавил пару пользовательских методов finder, некоторые с конкретными @Query
аннотация, чтобы рассказать ему, как получить данные. Я уже настроил EhCache для кэша hibernate 2-го уровня, но до сих пор единственный способ получить кэширование этих результатов-включить кэш запросов hibernate. Я бы предпочел определить конкретный кэш и сохранить фактические объекты домена там, как если бы это был обычный finder. Ниже мой код РЕПО:
public interface PromotionServiceXrefRepository extends PagingAndSortingRepository<PromotionServiceXref, Integer> {
@Query("SELECT psx FROM Customer c " +
"JOIN c.customerProductPromotions cpp " +
"JOIN cpp.productPromotion pp " +
"JOIN pp.promotion p JOIN p.promotionServiceXrefs psx " +
"WHERE c.customerId = ?1")
@QueryHints(@QueryHint(name = "org.hibernate.cacheable", value = "true"))
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region = "promotionServiceXrefByCustomerId")
Set<PromotionServiceXref> findByCustomerId(int customerId);
}
и вот кэш "promotionServiceXrefByCustomerId", который я определил, который не используется:
<cache name="promotionServiceXrefByCustomerId" overflowToDisk="true" diskPersistent="true"
maxEntriesLocalHeap="3000000" eternal="true" diskSpoolBufferSizeMB="20" memoryStoreEvictionPolicy="LFU"
transactionalMode="off" statistics="true">
</cache>
что я делаю не так? Если я включу StandardQueryCache
затем эти данные кэшируются там и Hibernate не выполняет запрос. Но когда я отключаю кэширование запросов, это не кэшируется. Что я здесь делаю не так? ПОЖАЛУЙСТА, ПОМОГИТЕ!
2 ответов
почему код не работает, заключается в том, что @Cache
не предназначен для работы таким образом. Если вы хотите кэшировать результаты выполнения метода запроса, самый простой способ заключается в использовании пружины абстракция кэширование.
interface PromotionServiceXrefRepository extends PagingAndSortingRepository<PromotionServiceXref, Integer> {
@Query("…")
@Cacheable("servicesByCustomerId")
Set<PromotionServiceXref> findByCustomerId(int customerId);
@Override
@CacheEvict(value = "servicesByCustomerId", key = "#p0.customer.id")
<S extends PromotionServiceXref> S save(S service);
}
Эта настройка вызовет результаты вызовов findByCustomerId(…)
кэширование идентификатором клиента. Обратите внимание, что мы добавили @CacheEvict
в переопределении save(…)
метод, так что кэш, который мы заполняем методом запроса, выселяется всякий раз, когда объект сохраняется. Это, вероятно, должно быть распространено на delete(…)
методы, а также.
теперь вы можете пойти дальше и настроить выделенный CacheManager
(см. документация для деталей), чтобы подключить любое решение кэширования, которое вы предпочитаете (используя простой ConcurrentHashMap
здесь).
@Configuration
@EnableCaching
class CachingConfig {
@Bean
CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.addCaches(Arrays.asList(new ConcurrentMapCache("servicesByCustomerId)));
return cacheManager;
}
}
вы должны знать, что сдаюсь гибернации QueryCache свой несут ответственность за нарушения запросов, которые приедаются при сохранении, обновлении, удалении сущностей, которые повлияли на результат запроса(что Оливер делает, устанавливая CacheEvict "сохранить") - который я думаю, может быть боль - или, по крайней мере, нужно учитывать и игнорировать его, если это не проблема для вашего сценария.