【问题标题】:Default implementation mapping for object without "_class" attribute in spring-data-mongodbspring-data-mongodb 中没有“_class”属性的对象的默认实现映射
【发布时间】:2020-11-17 15:34:18
【问题描述】:

我有下一个问题:在项目开始时,我只有一个类的实现:

class Wrapper {
    private Child child;
}

class Child { ... }

当 mongodb 序列化此类时,它从未为 child 对象设置 _class 属性。 现在我需要制作下一个类结构:

class Wrapper {
    private Child child;
}

abstract class Child { ... }

class ChildA extends Child { ... }

class ChildB extends Child { ... }

显然,然后我尝试反序列化旧文档,它会抛出异常,因为它无法实例化抽象类。

问题是:有没有办法指定对象反序列化的默认实现?例如,如果 _class 属性不像 Jackson 库中的 this 参数那样存在,我想将 child 字段反序列化到 Child1 类中?

【问题讨论】:

    标签: mongodb spring-data spring-data-mongodb


    【解决方案1】:

    这可能不是最佳解决方案,因为我确实怀疑有办法控制 mongo 反序列化。但是,如果您想避免深入挖掘,可以使用Mongo lifecycle events 之一。特别是,onAfterLoad 是在从数据库中读取文档之后,但在它被转换为 java 对象之前调度的。

    因此,使用该事件,您可以检查传入的 json,甚至在它被转换之前对其进行更改...这是您的情况的示例:

    @Component
    public class WrapperRepositoryListener extends AbstractMongoEventListener<Wrapper> {
    
        @Override
        public void onAfterLoad(AfterLoadEvent<Wrapper> event) {
            Document doc = event.getDocument();
            Document child = (Document)doc.get("child");        
            if (!child.containsKey("_class")) {   
                child.put("_class", "ChildA");
            }
        }
    }
    

    或者,(虽然我知道这不是你问的问题),根据你有多少数据,你可以编写一个 mongodb 脚本,简单地更新所有现有记录以具有 _class 字段:

    db.wrappers.update(
        { 
            "child" : { $exists : true},
            "child._class" : { $exists : false }
        }, 
        {
            $set:{
                "child._class" : "ChildA"
            }
        },    
        { 
            multi: true, 
            upsert: false    
        }
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-18
      • 1970-01-01
      • 1970-01-01
      • 2013-01-16
      相关资源
      最近更新 更多