如何在不使用查询缓存的情况下缓存 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;
}
}
相关文章