类型转换

基于约定的映射

当未提供额外的映射元数据时,Neo4j 转换器有一些对象映射约定。约定如下:

  • Java 类短名称以以下方式映射到主标签:类 com.bigbank.SavingsAccount 映射到 savingsAccount 主标签。

  • 转换器使用在其上注册的任何 Spring Converter 来覆盖对象属性到节点字段和值的默认映射。

  • 对象的字段用于与图中的字段相互转换。不使用公共的 JavaBean 属性。

  • 如果您有一个非零参数构造函数,且其参数名称与节点的顶级属性名称匹配,则使用该构造函数。否则,使用零参数构造函数。如果存在多个非零参数构造函数,则会抛出异常。

我们开箱即用地支持广泛的类型转换。支持的 Cypher 类型列表请参阅官方驱动手册:类型映射

原始类型或包装类型也同样支持。

领域类型 Cypher 类型 直接映射到原生类型

java.lang.Boolean

Boolean

boolean[]

布尔型列表

java.lang.Long

Integer

long[]

整型列表

java.lang.Double

Float

double[]

浮点型列表

java.lang.String

String

java.lang.String[]

字符串列表

byte[]

ByteArray

java.lang.Byte

长度为 1 的 ByteArray

java.lang.Character

长度为 1 的 String

char[]

长度为 1 的字符串列表

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[]

字符串列表

java.lang.Integer

Integer

int[]

整型列表

java.util.Locale

格式化为 BCP 47 语言标签的字符串

java.lang.Short

Integer

short[]

整型列表

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 的 Point

org.springframework.data.neo4j.types.GeographicPoint3d

CRS 4979 的 Point

org.springframework.data.neo4j.types.CartesianPoint2d

CRS 7203 的 Point

org.springframework.data.neo4j.types.CartesianPoint3d

CRS 9157 的 Point

org.springframework.data.geo.Point

CRS 4326 的 Point,其中 x/y 对应于 lat/long

Enum 实例

String(枚举的名称值)

Enum[] 实例

字符串列表(枚举的名称值)

java.net.URL

String

java.net.URI

String

java.util.UUID

String

自定义类型转换

针对给定类型的属性

如果您希望在实体中使用自己的类型或将其作为 @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> 的属性可以作为复合属性存储。map 中的所有条目将作为属性添加到包含该属性的节点或关系中。可以带配置的前缀,或使用属性名称作为前缀。虽然我们开箱即用只为 map 提供了此功能,但您可以实现 Neo4jPersistentPropertyToMapConverter 并将其配置为在 @CompositeProperty 上使用的转换器。Neo4jPersistentPropertyToMapConverter 需要知道如何将给定类型分解成 map,以及如何从 map 重新组合。