转换
基于约定的映射
Neo4j 转换器在未提供额外映射元数据时,按照若干约定映射对象。约定如下:
-
Java 短类名按以下方式映射到主标签:类
com.bigbank.SavingsAccount映射到savingsAccount主标签。 -
转换器会使用注册其中的任何 Spring 转换器,以覆盖对象属性到节点字段和值的默认映射。
-
对象的字段用于与图中的字段相互转换。不会使用公共
JavaBean属性。 -
如果您有一个唯一的非零参构造函数,且其构造参数名与节点的顶层属性名匹配,则使用该构造函数;否则使用无参构造函数。如果存在多个非零参构造函数,将抛出异常。
我们开箱即支持广泛的转换。支持的 Cypher 类型列表请参阅官方驱动手册:类型映射。
基本类型与包装类型同样受支持。
| 领域类型 | Cypher 类型 | 直接映射到原生类型 |
|---|---|---|
java.lang.Boolean | Boolean | ✔ |
boolean[] | Boolean 列表 | ✔ |
java.lang.Long | Integer | ✔ |
long[] | Integer 列表 | ✔ |
java.lang.Double | Float | ✔ |
double[] | Float 列表 | ✔ |
java.lang.String | String | ✔ |
java.lang.String[] | String 列表 | ✔ |
byte[] | ByteArray | ✔ |
java.lang.Byte | 长度为 1 的 ByteArray | |
java.lang.Character | 长度为 1 的 String | |
char[] | 长度为 1 的 String 列表 | |
java.util.Date | 格式化为 ISO 8601 日期的字符串(yyyy-MM-dd’T’HH:mm:ss.SSSZ)。请注意 Z:SDN 会将所有 java.util.Date 实例存储为 UTC。如果您需要时区,请使用支持时区的类型(例如 ZoneDateTime),或将时区作为单独的属性存储。 | |
java.lang.Float | String | |
float[] | String 列表 | |
java.lang.Integer | Integer | |
int[] | Integer 列表 | |
java.util.Locale | 格式化为 BCP 47 语言标记的字符串 | |
java.lang.Short | Integer | |
short[] | Integer 列表 | |
java.math.BigDecimal | String | |
java.math.BigInteger | String | |
java.time.LocalDate | Date | ✔ |
java.time.OffsetTime | Time | ✔ |
java.time.LocalTime | LocalTime | ✔ |
java.time.ZonedDateTime | DateTime | ✔ |
java.time.LocalDateTime | LocalDateTime | ✔ |
java.time.OffsetDateTime | DateTime | |
java.time.Instant | DateTime | |
java.util.TimeZone | String | |
java.time.ZoneId | String | |
java.time.Period | Duration | |
java.time.Duration | Duration | |
org.neo4j.driver.types.IsoDuration | Duration | ✔ |
org.neo4j.driver.types.Point | Point | ✔ |
org.springframework.data.neo4j.types.GeographicPoint2d | CRS 4326 的点 | |
org.springframework.data.neo4j.types.GeographicPoint3d | CRS 4979 的点 | |
org.springframework.data.neo4j.types.CartesianPoint2d | CRS 7203 的点 | |
org.springframework.data.neo4j.types.CartesianPoint3d | CRS 9157 的点 | |
org.springframework.data.geo.Point | CRS 4326 的点,x/y 分别对应纬度/经度 | |
org.springframework.data.domain.Vector | 通过 setNodeVectorProperty 持久化 | |
Enum 的实例 | 字符串(枚举的名称值) | |
Enum[] 的实例 | 字符串列表(枚举的名称值) | |
java.net.URL | String | |
java.net.URI | String | |
java.util.UUID | String |
向量类型
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 转换回来的双向转换。如果您的转换器仅用于仓库中的自定义查询方法,则只需提供到 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> 类型的属性可以存储为组合属性。Map 中的所有条目都将作为属性添加到包含该属性的节点或关系上,并带有配置的前缀,或以属性名作为前缀。虽然我们开箱即用地仅为 Map 提供此功能,但您可以实现 Neo4jPersistentPropertyToMapConverter,并将其配置为 @CompositeProperty 上使用的转换器。Neo4jPersistentPropertyToMapConverter 需要知道给定类型如何分解为 Map 以及如何从 Map 组合回来。