如何完全自定义 Spring 数据 MongoDB 将类型信息写入文档的方式?

How to completely customize the way that type information gets written to a document by Spring Data MongoDB?

是否可以像在 Doctrine(PHP) 或 Jackson 库中那样对每个多态集合使用不同的类型属性(而不是 _class)?当前的解决方案允许在文档字段中存储类型信息。默认情况下,它是一个完整的 class 名称,存储在名为 _class.

的字段中

我们可以轻松更改它以保存一些自定义字符串(别名)而不是完整的 class 名称,并将默认鉴别器字段名称从 _class 更改为其他名称。

在我的情况下,我正在处理遗留数据库,而遗留应用程序仍在使用中。遗留应用程序使用 Doctrine (PHP) ODM 作为数据层。 Doctrine 允许通过注释定义鉴别器字段名称(SpringData 中的_class),并且每个集合不同

在 Spring 中,当我将 typeKey 传递给 DefaultMongoTypeMapper 时,它用于 所有集合 .

谢谢。

// MyCustomMongoTypeMapper.java
// ...

@SuppressWarnings("unchecked")
@Override
public <T> TypeInformation<? extends T> readType(DBObject source, TypeInformation<T> basicType) {

    Assert.notNull(basicType);
    Class<?> documentsTargetType = null;

    Class<? super T> parent = basicType.getType();
    while (parent != null && parent != java.lang.Object.class) {
        final String discriminatorKey = getDiscriminatorKey(parent); //fetch key from annotation
        if (null == discriminatorKey) {
            parent = parent.getSuperclass();
        } else {
            accessor.setKey(discriminatorKey);
            return super.readType(source, basicType);
        }
    }
    accessor.resetKey();
    return super.readType(source, basicType);
}

应该为您工作的是完全交换 MappingMongoConverter 使用的 MongoTypeMapper 实例。正如您所发现的,已经可用的实现采用了一个通用字段名称,并采用了另一种策略来编写完全限定的 class 名称或别名等。

但是,您应该能够自己编写并特别关注以下方法:

  • void writeType(TypeInformation<?> type, DBObject dbObject) — 您基本上获得了类型并完全控制将其放入 DBObject 的位置和方式。
  • <T> TypeInformation<? extends T> readType(DBObject source, TypeInformation<T> defaultType);——你得到了在阅读端声明的类型(即通常是层次结构中最常见的类型),并基于它必须从给定的源文档中查找类型。我想这恰恰与另一种方法中要实现的相反。

最后一点,我强烈建议不要对不同的集合使用不同的类型字段名称,因为在阅读方面,您可能 运行 到 Object 声明的地方 属性 而且您基本上不知道在文档中的何处寻找。