如何在不使用查询缓存的情况下缓存 Spring Data JPA 查询方法的结果? [英] How to cache results of a Spring Data JPA query method without using query cache?

查看:57
本文介绍了如何在不使用查询缓存的情况下缓存 Spring Data JPA 查询方法的结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有 Spring Data JPA(休眠后端)存储库类的 Spring Boot 应用程序.我添加了几个自定义查找器方法,其中一些带有特定的 @Query 注释来告诉它如何获取数据.我已经为休眠二级缓存设置了 EhCache,但到目前为止,我可以获得这些结果缓存的唯一方法是启用休眠查询缓存.我更愿意定义一个特定的缓存并将实际的域对象存储在那里,就像它是一个普通的查找器一样.以下是我的回购代码:

I have a Spring Boot app with Spring Data JPA (hibernate backend) repository classes. I've added a couple custom finder methods, some with specific @Query annotation to tell it how to get the data. I have already set up EhCache for the hibernate 2nd level cache, but so far, the only way I can get these results caching is to enable the hibernate query cache. I'd prefer to define a specific cache and store the actual domain objects there just as if it were a normal finder. Below is my repo code:

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"缓存,没有被使用:

And here is the "promotionServiceXrefByCustomerId" cache I defined, that is NOT being used:

<cache name="promotionServiceXrefByCustomerId" overflowToDisk="true" diskPersistent="true"
       maxEntriesLocalHeap="3000000" eternal="true" diskSpoolBufferSizeMB="20" memoryStoreEvictionPolicy="LFU"
       transactionalMode="off" statistics="true">
</cache>

我做错了什么?如果我启用 StandardQueryCache 那么这些数据会被缓存在那里并且休眠不会执行查询.但是当我禁用查询缓存时,它不会被缓存.我在这里做错了什么?请帮忙!

What am I doing wrong? If I enable StandardQueryCache then this data gets cached there and hibernate does not execute a query. But when I disable the query caching, this does not get cached. What am I doing wrong here? PLEASE HELP!

推荐答案

您的代码无法正常工作的原因是 @Cache 不打算以这种方式工作.如果要缓存某个查询方法执行的结果,最简单的方法是使用 Spring 的 缓存抽象.

The reason the code you have is not working is that @Cache is not intended to work that way. If you want to cache the results of a query method execution, the easiest way is to use Spring's caching abstraction.

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(…) 的结果由客户标识符缓存.请注意,我们在重写的 save(…) 方法中添加了 @CacheEvict,这样每当保存实体时,我们使用查询方法填充的缓存就会被清除.这可能也必须传播到 delete(…) 方法.

This setup will cause results of calls to findByCustomerId(…) be cached by the customer identifier. Note, that we added an @CacheEvict to the overridden save(…) method, so that the cache we populate with the query method is evicted, whenever an entity is saved. This probably has to be propagated to the delete(…) methods as well.

现在您可以继续配置一个专用的 CacheManager(参见 参考文档 以插入您喜欢的任何缓存解决方案(在此处使用普通的 ConcurrentHashMap).

Now you can go ahead an configure a dedicated CacheManager (see the reference documentation for details) to plug in whichever caching solution you prefer (using a plain ConcurrentHashMap here).

 @Configuration
 @EnableCaching
 class CachingConfig {

   @Bean
   CacheManager cacheManager() {

     SimpleCacheManager cacheManager = new SimpleCacheManager();
     cacheManager.addCaches(Arrays.asList(new ConcurrentMapCache("servicesByCustomerId)));

     return cacheManager;
   }
 }

这篇关于如何在不使用查询缓存的情况下缓存 Spring Data JPA 查询方法的结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆