Spring Boot使用MongoRepository查询MongoDB时嵌套id字段映射为null问题
这个问题的核心是Spring Data MongoDB的默认映射规则在处理嵌套实体类时的特殊行为:
对于没有被@Document注解标记的嵌套实体(比如你的Tag和TagCategory),框架会默认将实体中名为id的属性,映射到MongoDB子文档的_id字段——而不是你数据库里实际存储的id字段。这就导致框架在反序列化时,会去子文档里找_id字段,找不到就把id属性设为null,完全忽略了数据库中的id字段值。
你提到把数据库字段改成_id就能正常映射,也验证了这个规则:此时框架的默认映射刚好匹配数据库字段,所以值能正确读取。
根据你的需求(如果不想修改数据库结构),可以通过以下方式修复:
方案一:显式指定嵌套实体的ID映射规则
给Tag和TagCategory的id字段添加@MongoId注解,明确告诉框架这个字段对应数据库的id字段,并且类型为ObjectId:
修改后的Tag类
@Data @NoArgsConstructor @AllArgsConstructor public class Tag { @MongoId(FieldType.OBJECT_ID) @Field("id") private ObjectId id; @Field(value = "name") private List<TagName> name; @Field(value = "category") private List<TagCategory> category; }
修改后的TagCategory类
@Data @NoArgsConstructor @AllArgsConstructor public class TagCategory { @MongoId(FieldType.OBJECT_ID) @Field("id") private ObjectId id; @Field(value = "name") private List<TagCategoryName> name; }
@MongoId(FieldType.OBJECT_ID)会明确标记该字段为子文档的ID字段,同时指定类型为MongoDB的ObjectId;@Field("id")则强制绑定到数据库中的id字段,覆盖框架的默认映射规则。
方案二:修改数据库字段(已验证可行)
如果允许修改数据库结构,直接把嵌套文档中的id字段改为_id,这样框架的默认映射就能自动匹配,不需要修改实体类代码。
方案三:自定义映射转换器(进阶)
如果需要更灵活的映射逻辑,可以自定义MongoConverter来处理嵌套文档的字段映射,但这个方案相对复杂,适合有特殊需求的场景,一般前两个方案就足够解决问题。
修改实体类后,重新执行查询代码:
Article article = articleRepository.findById(new ObjectId("5e57fcdbe7dd406f374bbf59")).orElse(null); System.out.println(article);
此时嵌套的Tag.id和TagCategory.id应该能正确读取到数据库中的ObjectId值,不再是null。
内容的提问来源于stack exchange,提问作者Phuc Nguyen

