You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot2.6.1调用MongoRepository.findById实例化抽象父类报错

问题描述

项目运行时抛出异常:Failed to instantiate abstract superclass 'ClassName' using public constructor with arguments - Mongodb
触发场景:

  • 业务实体定义如下:
@Document(collection = "document1")
@Getter
@ToString
public abstract class DocumentA {
   private String name;
   private String lName;

   public DocumentA(){}
}


@lombok.Getter
public class DocumentB extends DocumentA {
   private String someFields;
   public DocumentB() {}
}
  • 对应Mongo Repository接口方法定义如下,调用该findById()方法时触发异常,方法预期返回子类DocumentB的实例:
DocumentA findById(String id);
  • 相同代码在Spring Boot 2.1.5版本可正常运行,升级到2.6.1版本后开始抛出该异常。
问题根因

Spring Data MongoDB在版本迭代中调整了抽象实体的反序列化实例化逻辑:

  • Spring Boot 2.1.x对应的Spring Data MongoDB版本,反序列化时会自动扫描抽象类的所有实现子类,结合MongoDB文档中存储的_class类型元数据匹配对应子类实例化,即使方法返回值声明为抽象父类也能正常返回子类实例。
  • Spring Boot 2.6.1对应的Spring Data MongoDB版本默认开启严格类型映射校验:当方法返回值声明为抽象类时,框架会优先尝试直接实例化该声明类型,不会自动扫描子类做匹配。抽象类本身无法被实例化,就会抛出上述实例化失败的错误。
    如果历史写入MongoDB的文档未存储_class类型字段,框架无法获知文档对应的实际实现类,会直接触发该错误。
修复方案

根据业务场景选择对应方案即可:

  • 方案1(单实现类场景推荐,改造成本最低):直接修改Repository方法的返回值声明为具体实现类,避免框架尝试实例化抽象类:
DocumentB findById(String id);
  • 方案2(多子类多态场景推荐):显式配置继承映射规则,在抽象父类上指定类型元信息,强制框架根据文档存储的_class字段匹配对应实现类,单实现类场景可直接指定默认实现类:
@Document(collection = "document1")
@Getter
@ToString
// 指定默认实现类,多子类场景可配合@TypeAlias注解区分不同子类类型
@org.springframework.data.mongodb.core.mapping.DocumentType(DocumentB.class)
public abstract class DocumentA {
   private String name;
   private String lName;

   public DocumentA(){}
}
  • 方案3(兼容旧逻辑):自定义Mongo映射转换器,关闭严格类型校验,开启自动子类扫描,该方案会增加反序列化时的性能开销,非必要不推荐。

内容的提问来源于stack exchange,提问作者Neeraj Kunturkar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 23:21:34