属性转换器

尽管 基于类型的转换 已提供影响目标存储中特定类型转换和表示的方法,但当仅考虑特定类型的特定值或属性进行转换时,它存在局限性。基于属性的转换器允许按属性逐个配置转换规则,无论是声明式(通过 @ValueConverter)还是以编程方式(通过为特定属性注册 PropertyValueConverter)。

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

示例 1. 一个简单的 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);
  }
}

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

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

声明式值转换器

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

示例 2. 声明式 PropertyValueConverter
class Person {

  @ValueConverter(ReversingValueConverter.class)
  String ssn;
}

编程式值转换器注册

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

示例 3. 编程式 PropertyValueConverter 注册
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 为由其名称标识的字段注册一个转换器。
2 类型安全变体,允许注册一个转换器及其转换函数。此方法使用类代理来确定属性。确保类和访问器都不是 final,否则此方法不起作用。
在注册转换器时,不支持点表示法(例如 registerConverter(Person.class, "address.street", …))用于在属性之间导航到子文档。
MongoValueConverter 提供了一个预类型的 PropertyValueConverter 接口,它使用 MongoConversionContext。

MongoCustomConversions 配置

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

示例 4. 配置示例
MongoCustomConversions.create(configurationAdapter -> {

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

    configurationAdapter.setPropertyValueConversions(valueConversions);
});