Type Mapping

Type Mapping

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

MongoDB collections can contain documents that represent instances of a variety of types. This feature can be useful if you store a hierarchy of classes or have a class with a property of type Object.In the latter case, the values held inside that property have to be read in correctly when retrieving the object.Thus, we need a mechanism to store type information alongside the actual document.

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

To achieve that, the MappingMongoConverter uses a MongoTypeMapper abstraction with DefaultMongoTypeMapper as its main implementation.Its default behavior to store the fully qualified classname under _class inside the document.Type hints are written for top-level documents as well as for every value (if it is a complex type and a subtype of the declared property type).The following example (with a JSON representation at the end) shows how the mapping works:

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

Spring Data MongoDB stores the type information as the last field for the actual root class as well as for the nested type (because it is complex and a subtype of Contact).So, if you now use mongoTemplate.findAll(Object.class, "sample"), you can find out that the document stored is a Sample instance.You can also find out that the value property is actually a Person.

Customizing Type Mapping

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

If you want to avoid writing the entire Java class name as type information but would rather like to use a key, you can use the @TypeAlias annotation on the entity class.If you need to customize the mapping even more, have a look at the TypeInformationMapper interface.An instance of that interface can be configured at the DefaultMongoTypeMapper, which can, in turn, be configured on MappingMongoConverter.The following example shows how to define a type alias for an entity:

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

}

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

Note that the resulting document contains pers as the value in the _class Field.

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

Type aliases only work if the mapping context is aware of the actual type. The required entity metadata is determined either on first save or has to be provided via the configurations initial entity set. By default, the configuration class scans the base package for potential candidates.

@Configuration
class AppConfig extends AbstractMongoClientConfiguration {

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

  // ...
}

Configuring Custom Type Mapping

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

The following example shows how to configure a custom MongoTypeMapper in MappingMongoConverter:

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

Note that the preceding example extends the AbstractMongoClientConfiguration class and overrides the bean definition of the MappingMongoConverter where we configured our custom MongoTypeMapper.