Spring Boot使用@Cacheable缓存JPA实体到Redis的生产方案咨询
问题根因
你自定义配置的RedisTemplate不会被Spring Cache默认的RedisCacheManager复用,默认的RedisCacheManager内部还是使用JDK序列化规则,要求缓存对象必须实现Serializable接口,这就是你修改RedisTemplate序列化器后仍然报错的核心原因。
两种方案对比及生产选型
方案1:JPA实体实现Serializable接口
- 优点:改造成本极低,仅需要给实体类添加一行实现代码即可,不需要额外配置调整
- 缺点:
- JDK序列化结果体积大,序列化/反序列化性能远低于JSON序列化
- 序列化结果为二进制内容,在Redis中直接查看可读性极差,排查缓存相关问题非常不便
- 实体类字段变更后极易出现反序列化兼容问题
- 适用场景:仅内部测试、临时Demo等对缓存性能、可观测性要求极低的场景可以使用,生产环境不推荐。
方案2:自定义RedisCacheManager并关联到@Cacheable
这是生产环境的首选方案,具体实施步骤如下:
- 在RedisConfig配置类中自定义
RedisCacheManager,指定序列化规则,示例代码:
@Bean public RedisCacheManager redisCacheManager(LettuceConnectionFactory lettuceConnectionFactory) { RedisSerializer<String> stringSerializer = new StringRedisSerializer(); GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer(); RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringSerializer)) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer)) // 按需配置全局缓存过期时间 .entryTtl(Duration.ofHours(1)) .disableCachingNullValues(); return RedisCacheManager.builder(lettuceConnectionFactory) .cacheDefaults(config) .build(); }
- 两种使用方式可选:
- 全局生效:将自定义的
RedisCacheManager设为默认Bean,Spring Cache会自动复用,不需要在每个@Cacheable注解上单独指定 - 局部指定:如果项目存在多套缓存管理器,在对应方法上添加
@Cacheable(value = "search", key = "#code", cacheManager = "redisCacheManager")即可
- 全局生效:将自定义的
- 优点:
- 序列化结果为JSON格式,在Redis中直接可读,排查问题非常方便
- 序列化/反序列化性能更高,缓存内容体积更小,能节省Redis内存和网络开销
- 字段变更兼容性更好,不需要实体类实现
Serializable接口,和JPA实体适配性更高
- 注意点:如果实体类包含嵌套复杂类型、枚举等特殊结构,需要提前在Jackson中做好对应的序列化配置,避免反序列化异常。
生产最终推荐
优先选择方案2,自定义RedisCacheManager使用JSON序列化,仅当项目体量极小、缓存使用量非常低,且不需要排查缓存内容的特殊场景下,才会选择方案1。
内容的提问来源于stack exchange,提问作者Hide
相关产品推荐
相关产品推荐

