You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Data JPA默认方法无需@QueryHints使用Hibernate二级缓存

问题场景

在Spring Boot应用中使用Spring Data JPA,为部分实体启用Hibernate二级缓存,应用采用Redis作为缓存服务,使用支持Spring Boot集成的Redisson作为缓存实现,现有配置如下:

实体类配置:

@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()时,Hibernate仍输出select查询日志,未从缓存加载数据
  • 手动重写Repository中findAll()方法并添加@QueryHints注解后,Hibernate可正常从缓存读取数据

需求:不使用@QueryHints注解、不重写Spring Data提供的原生默认方法,让默认Repository方法直接使用Hibernate二级缓存,确认该需求是否可实现,以及具体配置方式。

实现方案

该需求完全可以实现。

缓存不命中的核心原因:Hibernate二级缓存分为实体实例缓存和查询结果缓存两部分,实体类上的@Cacheable注解仅开启了按主键查询的实体实例缓存,而findAll()这类全量、条件查询走查询结果缓存通道,Spring Data JPA默认生成的查询不会自动携带「查询结果可缓存」标记,因此即使缓存中已有数据,Hibernate仍会执行SQL查库。手动添加@QueryHints本质是给对应查询加上org.hibernate.cacheable = true的标记,触发查询缓存命中。

无需重写方法、无需逐个加注解,通过以下配置即可实现全局生效:

  • 若使用Spring Boot 2.7及以上版本(对应Spring Data JPA 2.7+、Hibernate 5.6+),直接在原有application.yml的JPA配置下新增全局配置即可:
spring:
  jpa:
    properties:
      hibernate:
        # 原有缓存配置全部保留,新增以下配置
        jpa:
          query:
            cacheable: true

该配置是Hibernate提供的原生全局开关,开启后所有框架自动生成的JPA查询(包括Repository默认的findAll()、findAll(Example)、条件查询等方法)都会默认标记为可缓存,直接命中查询缓存,无需额外注解。

  • 若使用版本低于2.7,无上述全局配置项,可通过自定义全局Repository扩展实现:
    • 自定义JpaRepositoryFactoryBean子类,重写Repository创建逻辑,给所有查询方法默认追加缓存查询提示
    • 在启动类的@EnableJpaRepositories注解中指定自定义的repositoryFactoryBeanClass,全局生效后所有Repository的默认方法都会自动携带缓存提示,无需逐个重写。

补充说明:全局开启查询缓存后,建议给不同业务实体的缓存区域设置合理的过期时间、最大容量,避免冷数据长期占用Redis内存;实体类上的@Cacheable、@Cache注解需要保留,这是实体缓存正常生效的基础。

内容的提问来源于stack exchange,提问作者hamed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 12:27:13