基于属性的转换器
虽然基于类型的转换已经提供了影响目标存储中特定类型的转换和表示方式,但当只应对特定类型的某些值或属性进行转换时,它存在局限。基于属性的转换器允许按属性配置转换规则,既可以声明式地(通过 @ValueConverter),也可以编程式地(为特定属性注册 PropertyValueConverter)。
PropertyValueConverter 可以将给定值转换为其存储表示(写入),并再转换回来(读取),如下列所示。附加的 ValueConversionContext 提供了额外信息,例如映射元数据以及直接的 read 和 write 方法。
示例 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 Cassandra 使用一个缓存实现,可为具有默认构造函数的类型或枚举值提供服务。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));
为按名称标识的字段注册转换器。
类型安全的变体,允许注册转换器及其转换函数。该方法使用类代理来确定属性。请确保类和访问器都不是
final的,否则这种方式无法工作。
注册转换器时,不支持使用点号表示法(如 registerConverter(Person.class, "address.street", …))跨属性导航到嵌套对象。
模式推导只有在转换器是 PropertyValueConverter 类时才能从已注册的转换器推导出列类型。无法从 lambda 确定泛型,使用 lambda 时会回退到属性类型。
CassandraValueConverter 提供了一个预定义类型的 PropertyValueConverter 接口,它使用 CassandraConversionContext。
CassandraCustomConversions 配置
默认情况下,CassandraCustomConversions 可以处理声明式值转换器,具体取决于所配置的 PropertyValueConverterFactory。CassandraConverterConfigurationAdapter 可帮助您设置编程式值转换,或定义要使用的 PropertyValueConverterFactory,或注册转换器。
示例 4. 配置示例
CassandraCustomConversions conversions = CassandraCustomConversions.create(adapter -> {
adapter.registerConverter(…);
adapter.configurePropertyConversions(registrar -> {
registrar.registerConverter(Person.class, "name", String.class)
.writing((from, ctx) -> …)
.reading((from, ctx) -> …);
});
});