Spring Data MongoDB无法加载@DBRef关联集合问题求助
看起来你的问题核心是实体类映射结构和MongoDB中的文档结构不匹配,导致关联的failureCauses无法正确加载。我们一步步来排查和解决:
1. 核心问题:文档结构与实体类的映射差异
先看你MongoDB里的statistics文档,failureCauses是一个对象数组,每个对象的结构是:
{ "failureCause": { "$ref" : "failureCauses", "$id" : ObjectId("..."), "$db" : "bfa_test" }, "indications" : [ { "matchingFile" : "log", "matchingString" : "ERROR:" } ] }
但你的Statistic类里直接定义了:
@DBRef private List<FailureCause> failureCauses;
这就错了——数据库里的每个元素不是直接的FailureCause引用,而是一个包含引用和额外字段(indications)的包装对象,Spring Data MongoDB无法自动识别这种嵌套结构,自然加载不出关联数据。
2. 修复步骤
步骤1:创建中间包装类
新增一个类来映射数据库中failureCauses数组的每个元素,比如FailureCauseEntry:
public class FailureCauseEntry implements Serializable { @DBRef private FailureCause failureCause; private List<Indication> indications; // 这里的Indication要和数据库结构匹配 // 生成getter、setter、构造方法 }
步骤2:修改Statistic类的映射
把Statistic里的failureCauses字段改成这个中间类的列表,同时修正类型不匹配的字段:
@Document(value = "statistics") public class Statistic implements Serializable { @Id private String id; private String projectName; private Integer buildNumber; // 注意:数据库里是Integer类型,之前定义成String会导致类型不匹配! private String master; private Long duration; private String result; private List<FailureCauseEntry> failureCauses; // 替换原来的List<FailureCause> }
步骤3:处理子类类型映射
看你failureCauses集合里的文档,indications字段有@class属性:
"indications" : [ { "@class" : "com.sonyericsson.jenkins.plugins.bfa.model.indication.BuildLogIndication", "pattern" : "Execution failed\\." } ]
所以需要让Spring Data MongoDB识别这个子类:
public class Indication implements Serializable { // 基础字段 } @TypeAlias("com.sonyericsson.jenkins.plugins.bfa.model.indication.BuildLogIndication") public class BuildLogIndication extends Indication { private String pattern; // 其他字段和getter/setter }
这样才能正确反序列化indications里的子类对象。
步骤4:验证DBRef的ID匹配
另外注意你提供的示例数据中,statistics里引用的failureCause的$id是5ddcf6f98f705f000623ec39,但failureCauses集合里的文档_id是5c99cfcfffb7870007bb351b,这两个ID不匹配,实际测试时要确保引用的ID存在于failureCauses集合中,否则DBRef加载会返回null。
3. 测试查询
修改完成后,重新调用你的findByProjectNameAndBuildNumber方法,应该就能正确加载关联的FailureCause数据,以及对应的indications字段了。
内容的提问来源于stack exchange,提问作者loknath

