[英]spring data jpa - hibernate second level cache without @QueryHints
我在我的spring boot应用程序中使用spring data jpa ,我需要启用hibernate二级缓存来缓存一些实体。 我使用 Redis 作为我的应用程序的缓存服务器,因此我需要将Redisson
与它的 Spring Boot 集成一起使用。 这是我启用二级缓存的一些代码示例:
@Entity
@Cacheable
@Cache(region = "baseInfoCache", usage = CacheConcurrencyStrategy.READ_WRITE)
public class BaseInfo {
}
application.yml
:
spring:
jpa:
properties:
hibernate:
cache:
use_query_cache: true
use_second_level_cache: true
use_structured_entries: true
region_prefix: dd_hibernate
region:
factory_class: org.redisson.hibernate.RedissonRegionFactory
redisson:
fallback: true
config: redisson/redisson-dev.yaml
redisson-dev.yml
:
singleServerConfig:
address: "redis://localhost:6379"
我的BaseInfoRepository
扩展了 jpa 标准CrudRepository
。 第一次调用findAll()
方法后,我可以看到 redis 中的缓存,因此将数据放入缓存中没有问题。 但是,下次调用findAll()
方法时,我可以看到休眠选择查询日志。 这意味着休眠不会从我的缓存中加载数据。 当我在我的存储库中覆盖findAll()
方法并将@QueryHints
放在它上面时,休眠开始从缓存中读取! 但我不想覆盖本机弹簧数据方法。 换句话说,我想在 spring 数据默认方法中使用休眠二级缓存而不使用 @QueryHints 。 那可能吗?
要应用二级缓存,您需要为实体定义@Cacheable
和@Cache
注释。 经过这些更改后, CrudRepository
的findById
、 save
、 delete
方法将自动使用二级缓存,无需额外提示。
但是findAll
和findAllById
方法是不同的。 他们在后台使用 JPQL 查询来加载记录。 如果我们想缓存findAll
方法的结果并避免多次查询执行,我们需要使用查询缓存。 配置查询缓存后,默认情况下还没有缓存查询。 查询需要显式标记为缓存。
根据休眠文档。
默认情况下,即使启用了查询缓存,单个查询也不会被缓存。 每个需要缓存的特定查询必须手动设置为可缓存。 这样,查询会在执行时查找现有的缓存结果或将查询结果添加到缓存中。
我们可以为所有存储库简化此限制,并避免为每个特定存储库定义提示。 我们可以在新扩展的QueryCacheCrudRepository
中扩展CrudRepository
并将所有需要的查询标记为可缓存一次
import org.springframework.data.jpa.repository.QueryHints;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.NoRepositoryBean;
import javax.annotation.Nonnull;
import javax.persistence.QueryHint;
@NoRepositoryBean
public interface QueryCacheCrudRepository<T, ID> extends CrudRepository<T, ID> {
@QueryHints({
@QueryHint(name = "org.hibernate.cacheable", value = "true")
})
Iterable<T> findAll();
@QueryHints({
@QueryHint(name = "org.hibernate.cacheable", value = "true")
})
Iterable<T> findAllById(Iterable<ID> ids);
}
然后为我们的存储库使用新的QueryCacheCrudRepository
而不是CrudRepository
。
public interface BaseInfoRepository extends QueryCacheCrudRepository<BaseInfo, Long{
BaseInfo findByName(String name);
}
使用示例:
@Transactional
public Iterable<BaseInfo> getAllBaseInfo() {
baseInfoRepository.findAll(); // call DB to load all data and put it to query cache and second-level cahce
return baseInfoRepository.findAll(); // DB is not called. Data retrived from the cahce
}
概括:
使用查询的方法必须通过提示标记为可缓存。 这是根据文档。 这个限制可以通过扩展的CrudRepository
来简化。 您不需要覆盖所有实体特定存储库中的基本方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.