使用Ebean Redis缓存读取@ManyToMany关联时出现异常问题
看起来你遇到的问题是Ebean的Redis缓存插件在处理多对多关联数据时,因为键类型不匹配导致了解码失败。让我们一步步拆解问题并给出解决方案:
问题根源分析
从异常栈信息Expecting String keys but got type:class java.lang.Long可以看出,Ebean的Redis缓存编码类EncodePrefixKey期望接收字符串类型的缓存键,但实际传入的是实体的Long类型ID,这直接导致了解码失败。这个问题通常和版本兼容性或者缓存配置缺失有关。
具体解决方案
1. 确保Ebean核心与Redis插件版本一致
Ebean的核心库和Redis缓存插件版本必须严格对齐,否则会出现内部API不兼容的问题。你当前使用的Ebean版本是12.7.2,请检查你的依赖配置,确保ebean-redis的版本也是12.7.2:
Maven配置示例
<dependency> <groupId>io.ebean</groupId> <artifactId>ebean-redis</artifactId> <version>12.7.2</version> </dependency>
Gradle配置示例
implementation 'io.ebean:ebean-redis:12.7.2'
修改版本后,清理并重新构建项目,确保依赖完全更新。
2. 添加Redis缓存键类型配置
在你的application.properties(或ebean.properties)中添加以下配置,强制Ebean将缓存键转换为字符串类型:
# 强制Redis缓存使用字符串类型的键,适配Long类型ID ebean.cache.redis.key-as-string=true
这个配置会让Ebean在生成Redis缓存键时自动将Long类型的ID转换为字符串,解决类型不匹配的问题。
3. 临时规避方案(若上述方法无效)
如果暂时无法解决版本或配置问题,可以直接关闭该关联字段的缓存,避免触发异常。在DArticleCategory的articles字段上添加@Cache(enable = false)注解:
@ManyToMany @Cache(enable = false) private List<DArticle> articles;
同样,你也可以在DArticle的articleCategories字段上做相同配置,这样Ebean会直接从数据库加载关联数据,跳过缓存读取。
4. 升级Ebean版本(可选)
如果上述方法都无法解决问题,建议升级Ebean到更高的稳定版本(比如12.x系列的最新版本或13.x版本)。这个类型不匹配的问题可能是旧版本的已知bug,后续版本已经修复。升级时请同步更新所有Ebean相关依赖的版本。
总结
这个异常的核心是Redis缓存插件对键类型的期望与实际传入的ID类型不匹配。通过确保依赖版本一致、添加字符串键配置,或者临时关闭关联缓存,都可以解决这个问题。
内容的提问来源于stack exchange,提问作者jkohler

