转换
基于约定的映射
当没有提供额外的映射元数据时,Neo4j 转换器有一些用于映射对象的约定。这些约定是
-
Java 类的短名称以下列方式映射到主标签:类
com.bigbank.SavingsAccount映射到savingsAccount主标签。 -
转换器使用任何已注册的 Spring 转换器来覆盖对象属性到节点字段和值的默认映射。
-
对象的字段用于图中的字段之间的转换。不使用公共
JavaBean属性。 -
如果只有一个非零参数构造函数,并且其构造函数参数名称与节点的顶级属性名称匹配,则使用该构造函数。否则,使用零参数构造函数。如果有多个非零参数构造函数,则会抛出异常。
我们开箱即用地支持广泛的转换。请参阅官方驱动程序手册中支持的 Cypher 类型列表:类型映射。
原始类型或包装类型同样受支持。
| 领域类型 | Cypher 类型 | 直接映射到原生类型 |
|---|---|---|
|
布尔值 |
✔ |
|
布尔值列表 |
✔ |
|
整数 |
✔ |
|
整数列表 |
✔ |
|
浮点数 |
✔ |
|
浮点数列表 |
✔ |
|
字符串 |
✔ |
|
字符串列表 |
✔ |
|
字节数组 |
✔ |
|
长度为 1 的字节数组 |
|
|
长度为 1 的字符串 |
|
|
长度为 1 的字符串列表 |
|
|
格式为 ISO 8601 日期 ( |
|
|
字符串 |
|
|
字符串列表 |
|
|
整数 |
|
|
整数列表 |
|
|
格式为 BCP 47 语言标签的字符串 |
|
|
整数 |
|
|
整数列表 |
|
|
字符串 |
|
|
字符串 |
|
|
日期 |
✔ |
|
时间 |
✔ |
|
本地时间 |
✔ |
|
日期时间 |
✔ |
|
本地日期时间 |
✔ |
|
日期时间 |
|
|
日期时间 |
|
|
字符串 |
|
|
字符串 |
|
|
持续时间 |
|
|
持续时间 |
|
|
持续时间 |
✔ |
|
点 |
✔ |
|
CRS 4326 点 |
|
|
CRS 4979 点 |
|
|
CRS 7203 点 |
|
|
CRS 9157 点 |
|
|
CRS 4326 点,x/y 对应于纬度/经度 |
|
|
通过 |
|
枚举实例 |
字符串(枚举的名称值) |
|
枚举数组实例 |
字符串列表(枚举的名称值) |
|
|
字符串 |
|
|
字符串 |
|
|
字符串 |
向量类型
Spring Data 有自己的向量表示类型 org.springframework.data.domain.Vector。虽然这可以用作 float 或 double 数组的包装器,但 Spring Data Neo4j 目前只支持 double 变体。从用户角度来看,可以在属性定义上只定义 Vector 接口,并使用 double 或 float。Neo4j 会将 double 和 float 变体都存储为 64 位 Cypher FLOAT 值,这与通过 Cypher 和 Spring Data Neo4j 用于持久化属性的专用 setNodeVectorProperty 函数持久化的值一致。
Spring Data Neo4j 实体定义中只允许存在一个 Vector 属性。 |
请注意,由于浮点数的特性,持久化的 float 值与读取回的值不同。 |
自定义转换
针对给定类型的属性
如果您希望在实体中使用自己的类型或作为 @Query 注解方法的参数,您可以定义并提供自定义转换器实现。首先,您必须实现 GenericConverter 并注册您的转换器应处理的类型。对于实体属性类型转换器,您需要负责将您的类型转换到 和 从 Neo4j Java Driver Value 转换。如果您的转换器只应与仓库中的自定义查询方法一起使用,则提供到 Value 类型的单向转换就足够了。
public class MyCustomTypeConverter implements GenericConverter {
@Override
public Set<ConvertiblePair> getConvertibleTypes() {
Set<ConvertiblePair> convertiblePairs = new HashSet<>();
convertiblePairs.add(new ConvertiblePair(MyCustomType.class, Value.class));
convertiblePairs.add(new ConvertiblePair(Value.class, MyCustomType.class));
return convertiblePairs;
}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (MyCustomType.class.isAssignableFrom(sourceType.getType())) {
// convert to Neo4j Driver Value
return convertToNeo4jValue(source);
}
else {
// convert to MyCustomType
return convertToMyCustomType(source);
}
}
}
为了让 SDN 知道您的转换器,它必须在 Neo4jConversions 中注册。为此,您必须创建一个类型为 org.springframework.data.neo4j.core.convert.Neo4jConversions 的 @Bean。否则,Neo4jConversions 将在后台仅使用内部默认转换器创建。
@Bean
public Neo4jConversions neo4jConversions() {
Set<GenericConverter> additionalConverters = Collections.singleton(new MyCustomTypeConverter());
return new Neo4jConversions(additionalConverters);
}
如果您的应用程序中需要多个转换器,您可以在 Neo4jConversions 构造函数中添加任意数量的转换器。
仅针对特定属性
如果您只需要针对某些特定属性进行转换,我们提供了 @ConvertWith。这是一个可以放在实体 (@Node) 和关系属性 (@RelationshipProperties) 的属性上的注解。它通过 converter 属性定义了一个 Neo4jPersistentPropertyConverter,并通过一个可选的 Neo4jPersistentPropertyConverterFactory 来构造前者。通过 Neo4jPersistentPropertyConverter 的实现,可以处理给定类型的所有特定转换。此外,@ConvertWith 还提供了 converterRef,用于引用应用程序上下文中实现 Neo4jPersistentPropertyConverter 的任何 Spring bean。引用 bean 将优先于构造新的转换器。
我们提供了 @DateLong 和 @DateString 作为元注解,以实现与不使用原生类型的 Neo4j-OGM 方案的向后兼容性。这些是基于上述概念的元注解。
复合属性
使用 @CompositeProperty,类型为 Map<String, Object> 或 Map<? extends Enum, Object> 的属性可以存储为复合属性。地图中的所有条目都将作为属性添加到包含该属性的节点或关系中。可以配置前缀,或者以属性名称作为前缀。虽然我们只针对地图开箱即用地提供此功能,但您可以 Neo4jPersistentPropertyToMapConverter 并将其配置为 @CompositeProperty 上使用的转换器。Neo4jPersistentPropertyToMapConverter 需要知道给定类型如何分解为地图以及如何从地图中组合回来。