类型映射

MongoDB 集合可以包含表示各种类型实例的文档。如果您存储类层次结构或有一个类型为 Object 的属性的类,此功能将非常有用。在后一种情况下,在检索对象时,必须正确读取该属性中保存的值。因此,我们需要一种机制来将类型信息与实际文档一起存储。

为了实现这一点,MappingMongoConverter 使用 MongoTypeMapper 抽象,DefaultMongoTypeMapper 是其主要实现。它的默认行为是在文档中的 _class 下存储完全限定的类名。类型提示被写入顶级文档以及每个值(如果它是复杂类型并且是声明属性类型的子类型)。以下示例(在最后显示 JSON 表示)展示了映射的工作原理

示例 1. 类型映射
class Sample {
  Contact value;
}

abstract class Contact { … }

class Person extends Contact { … }

Sample sample = new Sample();
sample.value = new Person();

mongoTemplate.save(sample);

{
  "value" : { "_class" : "com.acme.Person" },
  "_class" : "com.acme.Sample"
}

Spring Data MongoDB 将类型信息存储为实际根类的最后一个字段以及嵌套类型(因为它很复杂并且是 Contact 的子类型)。因此,如果您现在使用 mongoTemplate.findAll(Object.class, "sample"),您可以发现存储的文档是 Sample 实例。您还可以发现 value 属性实际上是 Person

自定义类型映射

如果您想避免将整个 Java 类名作为类型信息写入,而是希望使用一个键,您可以在实体类上使用 @TypeAlias 注解。如果您需要进一步自定义映射,请查看 TypeInformationMapper 接口。可以将该接口的实例配置在 DefaultMongoTypeMapper 上,而 DefaultMongoTypeMapper 又可以配置在 MappingMongoConverter 上。以下示例展示了如何为实体定义类型别名

示例 2. 为实体定义类型别名
@TypeAlias("pers")
class Person {

}

请注意,生成的文档在_class字段中包含pers作为值。

类型别名仅在映射上下文了解实际类型时才有效。所需的实体元数据是在第一次保存时确定的,或者必须通过配置的初始实体集提供。默认情况下,配置类会扫描基本包以查找潜在的候选者。

@Configuration
class AppConfig extends AbstractMongoClientConfiguration {

  @Override
  protected Set<Class<?>> getInitialEntitySet() {
    return Collections.singleton(Person.class);
  }

  // ...
}

配置自定义类型映射

以下示例展示了如何在MappingMongoConverter中配置自定义MongoTypeMapper

class CustomMongoTypeMapper extends DefaultMongoTypeMapper {
  //implement custom type mapping here
}
示例 3. 配置自定义MongoTypeMapper
Java
@Configuration
class SampleMongoConfiguration extends AbstractMongoClientConfiguration {

  @Override
  protected String getDatabaseName() {
    return "database";
  }

  @Bean
  @Override
  public MappingMongoConverter mappingMongoConverter(MongoDatabaseFactory databaseFactory,
			MongoCustomConversions customConversions, MongoMappingContext mappingContext) {
    MappingMongoConverter mmc = super.mappingMongoConverter();
    mmc.setTypeMapper(customTypeMapper());
    return mmc;
  }

  @Bean
  public MongoTypeMapper customTypeMapper() {
    return new CustomMongoTypeMapper();
  }
}
XML
<mongo:mapping-converter type-mapper-ref="customMongoTypeMapper"/>

<bean name="customMongoTypeMapper" class="com.acme.CustomMongoTypeMapper"/>

请注意,前面的示例扩展了AbstractMongoClientConfiguration类并覆盖了MappingMongoConverter的 bean 定义,我们在其中配置了自定义MongoTypeMapper