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

Spring Data JPA中Hibernate查询缓存失效问题求助

Hibernate二级缓存&查询缓存未生效问题排查与解决

问题现象

使用Spring Boot Starter Data JPA 2.6.4配置Hibernate二级缓存和查询缓存后,每次调用getByEventCode方法仍会执行SQL语句,缓存未生效。

核心问题与修复方案

1. 实体类扫描范围缺失

在NotificationDataSourceConfig的notificationEntityManagerFactory方法中,setPackagesToScan仅指定了MessageEntity的包,未包含Events实体所在的包,导致Hibernate无法识别Events类上的@Cacheable等缓存注解。

修复代码:

@Primary
@Bean(name="notificationEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean notificationEntityManagerFactory() {
    LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
    em.setDataSource(getDataSource());
    // 同时扫描所有通知模块实体类所在包
    em.setPackagesToScan(
        "com.dhre.realconnect.notificationService.notificationEntities"
    );

    JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    em.setJpaVendorAdapter(vendorAdapter);
    em.setJpaProperties(additionalProperties());
    return em;
}

2. 手动EntityManagerFactory未加载缓存配置

自定义LocalContainerEntityManagerFactoryBean时,additionalProperties方法仅设置了基础Hibernate属性,没有加载application.properties中配置的缓存相关属性,导致Hibernate缓存配置未生效。

修复代码:

// 新增缓存配置属性注入
@Value("${spring.jpa.properties.hibernate.cache.region.factory_class}")
private String cacheRegionFactory;
@Value("${spring.jpa.properties.javax.persistence.sharedCache.mode}")
private String sharedCacheMode;
@Value("${spring.jpa.properties.hibernate.cache.use_second_level_cache}")
private String useSecondLevelCache;
@Value("${spring.jpa.properties.hibernate.cache.use_query_cache}")
private String useQueryCache;

Properties additionalProperties() {
    Properties properties = new Properties();
    properties.setProperty("hibernate.show_sql", hibernateShowSql);
    // 修正拼写错误:原hibernate.properties.dialect改为hibernate.dialect
    properties.setProperty("hibernate.dialect", hibernateDialect);
    // 添加缓存配置
    properties.setProperty("hibernate.cache.region.factory_class", cacheRegionFactory);
    properties.setProperty("javax.persistence.sharedCache.mode", sharedCacheMode);
    properties.setProperty("hibernate.cache.use_second_level_cache", useSecondLevelCache);
    properties.setProperty("hibernate.cache.use_query_cache", useQueryCache);

    return properties;
}

3. 原生SQL查询缓存的局限性

Hibernate对原生SQL查询的查询缓存支持有限,即使添加了@QueryHint(CACHEABLE=true),也可能无法正常触发缓存。建议改用JPQL查询,更兼容Hibernate的缓存机制。

修复Repository代码:

@Repository
public interface EventRepository extends JpaRepository<Events, Integer>{

    // 替换原生SQL为JPQL查询
    @Query("SELECT e FROM Events e WHERE e.eventCode = :eventCode")
    @QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
    Optional<Events> getByEventCode(String eventCode);

}

4. 依赖版本兼容性问题

Spring Boot 2.6.4默认依赖的Hibernate版本是5.6.7.Final,当前手动指定的hibernate-ehcache版本为5.6.5.Final,版本不一致可能导致缓存组件兼容性问题。建议移除手动版本号,由Spring Boot依赖管理自动匹配。

修复pom.xml:

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-ehcache</artifactId>
   <!-- 移除手动指定的版本,依赖Spring Boot自动管理 -->
</dependency>

验证步骤

  1. 启动应用后,第一次调用getByEventCode,控制台会打印SQL语句。
  2. 第二次调用相同参数的getByEventCode,控制台不再打印SQL,说明查询缓存生效。
  3. 可开启缓存日志进一步验证,在application.properties中添加:
    logging.level.org.hibernate.cache=DEBUG
    
    日志中出现Cache hit: region=...字样,证明缓存命中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 01:55:16