如何让Hibernate二级缓存识别实体自定义命名的ID字段?
解决Hibernate 6中自定义ID字段查询的缓存生效问题
Hibernate的二级缓存对findById()这类原生ID查询会自动触发,但自定义的findByDisplayId()方法即使查询的是ID字段,默认不会被识别为ID查询,因此无法命中缓存。以下是几种可行的解决方式:
方式一:使用Spring缓存注解绑定缓存
在Repository的自定义方法上添加Spring的@Cacheable注解,指定对应缓存区域和缓存key,让Spring缓存抽象拦截方法调用并复用缓存:
import org.springframework.cache.annotation.Cacheable; public interface DisplayRepository extends JpaRepository<Display, Long> { @Cacheable(value = "display-cache", key = "#displayId") Optional<Display> findByDisplayId(Long displayId); }
注意:需要在Spring Boot主类上添加
@EnableCaching开启缓存功能,同时确保缓存管理器配置与Hibernate的Ehcache设置一致。
方式二:通过Hibernate查询缓存注解标记
使用自定义HQL查询,并添加Hibernate的@QueryCache注解,让Hibernate识别该查询并关联实体缓存:
import org.hibernate.annotations.QueryCache; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; public interface DisplayRepository extends JpaRepository<Display, Long> { @Query("SELECT d FROM Display d WHERE d.displayId = :displayId") @QueryCache(region = "display-cache") Optional<Display> findByDisplayId(@Param("displayId") Long displayId); }
此方式会让Hibernate优先从实体二级缓存中获取数据,同时也可缓存查询结果本身。
方式三:直接使用EntityManager的find方法
在业务代码中注入EntityManager,调用其find()方法,该方法与findById()逻辑一致,会自动触发Hibernate二级缓存:
import jakarta.persistence.EntityManager; import org.springframework.beans.factory.annotation.Autowired; // 业务类中 @Autowired private EntityManager entityManager; public Display getDisplayById(Long id) { return entityManager.find(Display.class, id); }
额外检查项
- 确认实体类上的
@Cache注解配置正确,region与Ehcache配置文件中的缓存区域名称匹配 - 验证Ehcache配置文件中已定义
display-cache区域,且缓存策略(如过期时间)符合需求
内容的提问来源于stack exchange,提问作者Slevin
相关产品推荐
相关产品推荐

