Property Converters

虽然 type-based conversion已经提供了一些方法来影响目标存储中某些类型转换和表示,但是当仅考虑某个类型中的特定值或属性时,它有其局限性。基于属性的转换程序允许以按属性为基础的方式配置转换规则,无论是以声明方式(通过 @ValueConverter)还是以编程方式(通过用特定的属性注册 PropertyValueConverter)。

While type-based conversion already offers ways to influence the conversion and representation of certain types within the target store, it has limitations when only certain values or properties of a particular type should be considered for conversion. Property-based converters allow configuring conversion rules on a per-property basis, either declaratively (via @ValueConverter) or programmatically (by registering a PropertyValueConverter for a specific property).

PropertyValueConverter 可将给定值转换为其存储表示(写)并转换回来(读),如下列表所示。附加的 ValueConversionContext 提供附加信息,如映射元数据以及直接的 readwrite 方法。

A PropertyValueConverter can transform a given value into its store representation (write) and back (read) as the following listing shows. The additional ValueConversionContext provides additional information, such as mapping metadata and direct read and write methods. .A simple PropertyValueConverter

class ReversingValueConverter implements PropertyValueConverter<String, String, ValueConversionContext> {

  @Override
  public String read(String value, ValueConversionContext context) {
    return reverse(value);
  }

  @Override
  public String write(String value, ValueConversionContext context) {
    return reverse(value);
  }
}

可以通过委托给 PropertyValueConversionsCustomConversions#getPropertyValueConverter(…) 获得 PropertyValueConverter 实例,通常通过使用 PropertyValueConverterFactory 来提供实际转换器。根据应用程序的需求,可以链接或装饰 PropertyValueConverterFactory 的多个实例——例如,应用缓存。默认情况下,Spring Data Mongo DB 使用一种缓存实现,该实现可服务于具有默认构造函数或枚举值的类型。可通过 PropertyValueConverterFactory 中的工厂方法获得一组预定义的工厂。可以使用 PropertyValueConverterFactory.beanFactoryAware(…)ApplicationContext 获取 PropertyValueConverter 实例。

You can obtain PropertyValueConverter instances from CustomConversions#getPropertyValueConverter(…) by delegating to PropertyValueConversions, typically by using a PropertyValueConverterFactory to provide the actual converter. Depending on your application’s needs, you can chain or decorate multiple instances of PropertyValueConverterFactory — for example, to apply caching. By default, Spring Data MongoDB uses a caching implementation that can serve types with a default constructor or enum values. A set of predefined factories is available through the factory methods in PropertyValueConverterFactory. You can use PropertyValueConverterFactory.beanFactoryAware(…) to obtain a PropertyValueConverter instance from an ApplicationContext.

可以通过 ConverterConfiguration 更改默认行为。

You can change the default behavior through ConverterConfiguration.

Declarative Value Converter

PropertyValueConverter 最直接的用法是使用 @ValueConverter 注释注释属性,该注释定义转换器类型:

The most straight forward usage of a PropertyValueConverter is by annotating properties with the @ValueConverter annotation that defines the converter type:

Example 1. Declarative PropertyValueConverter
class Person {

  @ValueConverter(ReversingValueConverter.class)
  String ssn;
}

Programmatic Value Converter Registration

以编程方式注册使用 PropertyValueConverterRegistrar 为实体模型中的属性注册 PropertyValueConverter 实例,如下例所示。声明性注册和以编程方式注册之间的区别在于,以编程方式注册完全发生在实体模型之外。如果无法或不想对实体模型进行注释,则这种方法非常有用。

Programmatic registration registers PropertyValueConverter instances for properties within an entity model by using a PropertyValueConverterRegistrar, as the following example shows. The difference between declarative registration and programmatic registration is that programmatic registration happens entirely outside of the entity model. Such an approach is useful if you cannot or do not want to annotate the entity model.

Example 2. Programmatic PropertyValueConverter registration
PropertyValueConverterRegistrar registrar = new PropertyValueConverterRegistrar();

registrar.registerConverter(Address.class, "street", new PropertyValueConverter() { … }); 1

// type safe registration
registrar.registerConverter(Person.class, Person::getSsn())                               2
  .writing(value -> encrypt(value))
  .reading(value -> decrypt(value));
1 Register a converter for the field identified by its name.
2 Type safe variant that allows to register a converter and its conversion functions. This method uses class proxies to determine the property. Make sure that neither the class nor the accessors are final as otherwise this approach doesn’t work.

在注册转换器时,支持点表示法(如 registerConverter(Person.class, "address.street", …))用于在属性中导航到子文档。

Dot notation (such as registerConverter(Person.class, "address.street", …)) for nagivating across properties into subdocuments is not supported when registering converters.

MongoValueConverter 提供了一个使用 MongoConversionContext 的预类型 PropertyValueConverter 接口。

MongoValueConverter offers a pre-typed PropertyValueConverter interface that uses MongoConversionContext.

MongoCustomConversions configuration

默认情况下,MongoCustomConversions 可以处理声明性值转换器,具体取决于已配置的 PropertyValueConverterFactoryMongoConverterConfigurationAdapter 有助于设置以编程方式的值转换或定义要使用的 PropertyValueConverterFactory

By default, MongoCustomConversions can handle declarative value converters, depending on the configured PropertyValueConverterFactory. MongoConverterConfigurationAdapter helps to set up programmatic value conversions or define the PropertyValueConverterFactory to be used.

Example 3. Configuration Sample
MongoCustomConversions.create(configurationAdapter -> {

    SimplePropertyValueConversions valueConversions = new SimplePropertyValueConversions();
    valueConversions.setConverterFactory(…);
    valueConversions.setValueConverterRegistry(new PropertyValueConverterRegistrar()
        .registerConverter(…)
        .buildRegistry());

    configurationAdapter.setPropertyValueConversions(valueConversions);
});