基于属性的转换器
在 基于类型的转换 已经提供了影响目标存储中特定类型的转换和表示的方法,但当仅考虑特定类型的某些值或属性进行转换时,它存在局限性。基于属性的转换器允许在每个属性的基础上配置转换规则,可以通过声明性方式(使用 @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,通常使用 PropertyValueConverterFactory 来提供实际的转换器,从 CustomConversions#getPropertyValueConverter(…) 获取 PropertyValueConverter 实例。根据您的应用需求,您可以链式调用或装饰多个 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) -> …);
});
});