我正在尝试从 Spring Boot 2.3.12 升级到 2.7.15,但遇到了一些问题。
在 2.3.12 中,我有一个 Neo4j 节点,其具有以下属性并带有
@Properties
注释:
@Properties(prefix = "params")
var params: MutableMap<String, Any?>
在 2.7.17 中,注释
@Properties
已替换为 @CompositeProperty
@CompositeProperty(prefix = "params")
var params: MutableMap<String, Any?>
只要值很简单,这就有效。我的问题是我在地图中有值,即地图。
这在 2.3.12 中运行良好,因为属性存储在数据库中,如下所示:
params.key1: "Some string"
params.key2.mapKey1: "Some other string 1"
params.key2.mapKey2: "Some other string 2"
在 2.7.17 中,如果我尝试将地图作为值放入地图中,则会收到以下错误消息:
Property values can only be of primitive types or arrays thereof. Encountered: Map{}.; Error code 'Neo.ClientError.Statement.TypeError'
我是否遗漏了什么,或者此功能已被删除?
是的。我可能可以更改我的数据库模型或替换 Neo4j,但我已经有很多数据,而且我真的不想迁移。
谢谢
正如您已经体验过的那样,现有的 Spring Data Neo4j 版本在类型方面更加严格。 我对 Kotlin 类型处理没有那么丰富的经验,但完成这项工作的一般方法是为您的预期类型提供一个转换器。 但由于这是
Any
,因此您不想转换的属性也可能会触发此转换器。
我只是从你给出的例子中抽象出来。
@CompositeProperty(prefix = "params")
var params: MutableMap<String, CustomType?>
转换器定义:
public static class CustomTypeConverter implements GenericConverter {
@Override
public Set<ConvertiblePair> getConvertibleTypes() {
Set<ConvertiblePair> convertiblePairs = new HashSet<>();
convertiblePairs.add(new ConvertiblePair(Value.class, CustomType.class));
convertiblePairs.add(new ConvertiblePair(CustomType.class, Value.class));
return convertiblePairs;
}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (StringValue.class.isAssignableFrom(sourceType.getType())) {
return CustomType.of(((StringValue) source).asString());
} else {
return Values.value(((CustomType) source).getValue());
}
}
}
并将其注册为:
@Override
public Neo4jConversions neo4jConversions() {
return new Neo4jConversions(Collections.singleton(new CustomTypeConverter()));
}
也可以对属性显式执行此操作,但这还需要映射
Map
。
另一方面,您可以保留 Any
类型。
更多内容可以在参考中找到:https://docs.spring.io/spring-data/neo4j/reference/appendix/conversions.html#custom.conversions