数据库含嵌入式对象但MongoRepository返回空List问题排查
问题分析与解决方案
核心原因
你只配置了**序列化(写入数据库)的自定义逻辑(@JsonSerialize),但没有配置对应的反序列化(从数据库读取)**规则;同时final修饰的容器字段需要Spring Data MongoDB(底层依赖Jackson)能通过构造器或其他方式实例化对象,否则无法填充数据。
具体修复步骤
1. 添加反序列化注解
针对自定义序列化的字段,必须配套实现反序列化器并添加@JsonDeserialize注解,告诉框架如何将数据库中的JSON结构转换为Java对象:
修改Scenario类:
@Document("scenarios") public class Scenario { @Id private String id; @Indexed(unique = true) private String name; private String description; // 同时保留序列化注解,新增反序列化注解 @JsonSerialize(using = PlatformSerializer.class) @JsonDeserialize(contentUsing = PlatformDeserializer.class) private final List<Platform> platforms; // 为final字段添加带参数的构造器,Jackson需要通过它实例化对象 public Scenario(List<Platform> platforms) { this.platforms = platforms; } // 保留其他getter方法和必要的构造器 }
修改Platform类:
public class Platform { private final PlatformData platformData; @JsonSerialize(using = RowSerializer.class) @JsonDeserialize(contentUsing = RowDeserializer.class) private final List<Row> rows; // 带参数构造器,覆盖所有final字段 public Platform(PlatformData platformData, List<Row> rows) { this.platformData = platformData; this.rows = rows; } // 保留getter方法 }
2. 实现对应的反序列化器
你需要编写PlatformDeserializer和RowDeserializer,逻辑与你的自定义序列化器(PlatformSerializer、RowSerializer)完全对应,确保能将数据库中存储的JSON结构还原为Java对象。例如:
public class PlatformDeserializer extends JsonDeserializer<Platform> { @Override public Platform deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // 按照PlatformSerializer的输出结构,解析JSON并构建Platform对象 JsonNode node = p.getCodec().readTree(p); PlatformData platformData = p.getCodec().treeToValue(node.get("platformData"), PlatformData.class); List<Row> rows = p.getCodec().treeToValue(node.get("rows"), new TypeReference<List<Row>>() {}); return new Platform(platformData, rows); } }
3. 可选:移除自定义序列化(如果不需要)
如果你的自定义序列化只是为了处理嵌入式文档的默认转换,其实Spring Data MongoDB可以自动处理嵌入式对象的序列化/反序列化,无需自定义注解。这种情况下直接去掉@JsonSerialize和@JsonDeserialize,确保final字段有对应的构造器即可:
@Document("scenarios") public class Scenario { @Id private String id; @Indexed(unique = true) private String name; private String description; private final List<Platform> platforms; public Scenario(List<Platform> platforms) { this.platforms = platforms; } // getters }
验证逻辑
之前保存成功是因为@JsonSerialize正确将Java对象序列化为MongoDB能识别的JSON结构,但查询时框架不知道如何将JSON还原为Platform列表,再加上final字段缺少构造器导致无法实例化,最终出现platforms列表为空的情况。修复后,框架能正确完成反序列化流程,填充对应字段。
内容的提问来源于stack exchange,提问作者B Sheely
相关产品推荐
相关产品推荐

