Type Mapping

Type Mapping

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

为了实现这一点,MappingMongoConverter 使用 MongoTypeMapper 抽象,其主要实现是 DefaultMongoTypeMapper。其默认行为是将完全限定类名存储在文档中的 _class 下。类型提示是针对顶级文档以及针对每个值(如果它是一个复杂类型且是已声明的属性类型的子类型)编写的。以下示例(末尾带有 JSON 表示)显示了映射是如何工作的:

Example 1. Type mapping
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 数据 MongoDB 将类型信息存储为实际根类的最后一个字段以及嵌套类型(因为它很复杂并且是 Contact 的子类型)。因此,如果您现在使用 mongoTemplate.findAll(Object.class, "sample"),您可以发现存储的文档是 Sample 实例。您还可以发现值属性实际上是一个 Person

Customizing Type Mapping

如果您不想将整个 Java 类名写为类型信息,而是想使用键,则可以在实体类上使用 @TypeAlias 注释。如果您需要进一步自定义映射,请查看 TypeInformationMapper 接口。该接口的一个实例可以在 DefaultMongoTypeMapper 中配置,后者又可以在 MappingMongoConverter 中配置。以下示例说明如何定义实体的类型别名:

Example 2. Defining a type alias for an Entity
@TypeAlias("pers")
class Person {

}

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

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

@Configuration
class AppConfig extends AbstractMongoClientConfiguration {

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

  // ...
}

Configuring Custom Type Mapping

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

class CustomMongoTypeMapper extends DefaultMongoTypeMapper {
  //implement custom type mapping here
}
Example 3. Configuring a custom 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