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

EhCache 3缓存无法命中求助:使用对象作为键值时缓存失效

EhCache 3 + Spring Boot 3 缓存无法命中问题排查

问题现象

使用EhCache 3结合Spring Boot 3时,缓存始终无法命中,每次调用带@Cacheable注解的方法都会打印CacheInterceptor - No cache entry for key日志,并重新生成缓存条目,无论参数组合如何都无法匹配已有缓存。

环境与配置

  • 带@Cacheable的服务方法包含两个String类型参数和一个POJO类型LangAndMarket作为缓存键
  • 技术栈:Spring Boot 3、EhCache 3.10.8(jakarta分类器)
  • 缓存通过XML文件定义
  • 已开启ehcache和org.springframework.cache的TRACE级日志

配置类

@Configuration
@EnableCaching
public class CacheConfig {

@Autowired
private javax.cache.CacheManager cacheManager;

}

application.yml

spring:
  cache:
    jcache:
      config: classpath:ehcache.xml

ehcache.xml

...
<cache alias="cmsLabelsCache">
    <expiry>
        <ttl unit="seconds">10</ttl>
    </expiry>
    <heap unit="entries">10000</heap>
</cache>
....

服务类

@Service
public class CMSPropertiesService {

@Cacheable(value = "cmsLabelsCache", key = "{#cmsSpecificRequest, #langAndMarket, #labelKey}")
public String getLabelWithReferences(@NotNull String cmsSpecificRequest, @NotNull LangAndMarket langAndMarket, @NotNull String labelKey) {
    String label = "[" + cmsSpecificRequest 
                 + ", " + langAndMarket.toString() + ", " + labelKey + "]";
    return label;
}

LangAndMarket类

public static class LangAndMarket {

    private String lang;
    private String market;

    ... getters, setters, constructors. lang and market @NotNull

可能的原因及解决办法

  1. LangAndMarket未实现equals()和hashCode()
    Spring缓存的键匹配依赖对象的equals和hashCode方法,默认的Object实现仅比较引用地址——即使两个LangAndMarket实例的lang和market值完全相同,也会被视为不同的键。必须基于lang和market字段手动实现这两个方法:

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        LangAndMarket that = (LangAndMarket) o;
        return Objects.equals(lang, that.lang) && Objects.equals(market, that.market);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(lang, market);
    }
    
  2. 验证缓存键生成逻辑
    查看TRACE日志中CacheInterceptor打印的实际键值,确认相同参数是否生成一致的键。若键内容不一致,需检查SpEL表达式{#cmsSpecificRequest, #langAndMarket, #labelKey}是否存在解析问题。

  3. 简化CacheManager配置
    当前自定义CacheConfig仅注入了javax.cache.CacheManager,可尝试去掉该配置类,仅保留@EnableCaching注解,让Spring Boot自动加载application.yml中配置的ehcache.xml,避免手动注入引发的配置冲突。

  4. 检查键类型兼容性
    EhCache 3对缓存键的序列化有要求,确保复合键(三个参数组成的集合)能被正确识别。实现equals和hashCode是保证键一致性的基础,若仍有问题,可尝试显式指定键的序列化策略。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 03:33:10