小编典典

如何在不使用查询缓存的情况下缓存Spring Data JPA查询方法的结果?

spring-boot

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

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将不执行查询。但是当我禁用查询缓存时,不会被缓存。我在这里做错了什么?请帮忙!


阅读 1545

收藏
2020-05-30

共1个答案

小编典典

您拥有的代码无法正常工作的原因@Cache不是要这样工作。如果要缓存查询方法执行的结果,最简单的方法是使用Spring的缓存抽象

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;
   }
 }
2020-05-30