Neo4j - 类型列表字段的自定义转换器
Neo4j - Custom converter for field of type List
我正在尝试为嵌套对象编写自定义转换器,以便该对象在 Neo4j 数据库中保存为字符串。
我在我的字段上使用 @Convert
注释并传递 ImageConverter.class
这是我的 AttributeConverter
class.
一切正常,我可以在 Neo4j 数据库中保存 Image
class 的字符串表示。
但是,现在我想要 List<Image>
作为我的嵌套字段,而不是单个图像。在这种情况下,输入 @Convert(ImageConverter.class)
不起作用。
我看到有一个名为 ConverterBasedCollectionConverter
的 class,当我有一个 List<LocalDateTime
.
类型的字段时,它会被使用
但是,我找不到任何关于如何在自定义转换器的情况下使用此 class 的示例。
任何人都可以帮我解决这个问题,或者是否有任何其他方法可以在 List
.
类型的字段上使用自定义转换器
我在我的应用程序中使用 Neo4j(版本 3.4.1)和 Spring-data-neo4j(5.0.10.RELEASE)。我也在用OGM
PS:我知道建议将嵌套对象存储为与父对象建立关系的单独节点。但是,我的用例要求将对象存储为字符串 属性 而不是单独的节点。
此致,
V
这并不像我想象的那么难。
给定一个 class(片段)
@NodeEntity
public class Actor {
@Id @GeneratedValue
private Long id;
@Convert(MyImageListConverter.class)
public List<MyImage> images = new ArrayList<>();
// ....
}
MyImage
尽可能简单
public class MyImage {
public String blob;
public MyImage(String blob) {
this.blob = blob;
}
public static MyImage of(String value) {
return new MyImage(value);
}
}
和转换器
public class MyImageListConverter implements AttributeConverter<List<MyImage>, String[]> {
@Override
public String[] toGraphProperty(List<MyImage> value) {
if (value == null) {
return null;
}
String[] values = new String[(value.size())];
int i = 0;
for (MyImage image : value) {
values[i++] = image.blob;
}
return values;
}
@Override
public List<MyImage> toEntityAttribute(String[] values) {
List<MyImage> images = new ArrayList<>(values.length);
for (String value : values) {
images.add(MyImage.of(value));
}
return images;
}
}
将在保存时打印以下调试输出,我认为这是您想要的:
UNWIND {rows} as row CREATE (n:Actor) SET n=row.props RETURN row.nodeRef as ref, ID(n) as id, {type} as type with params {type=node, rows=[{nodeRef=-1, props={images=[blobb], name=Jeff}}]}
尤其是图像部分。
这样的测试方法
@Test
public void test() {
Actor jeff = new Actor("Jeff");
String blobValue = "blobb";
jeff.images.add(new MyImage(blobValue));
session.save(jeff);
session.clear();
Actor loadedActor = session.load(Actor.class, jeff.getId());
assertThat(loadedActor.images.get(0).blob).isEqualTo(blobValue);
}
我找到了解决问题的方法。所以,如果你想要另一个解决方案以及@meistermeier 提供的解决方案,你可以使用下面的代码。
public class ListImageConverter extends ConverterBasedCollectionConverter<Image, String>{
public ListImageConverter() {
super(List.class, new ImageConverter());
}
@Override
public String[] toGraphProperty(Collection<Image> values) {
Object[] graphProperties = super.toGraphProperty(values);
String[] stringArray = Arrays.stream(graphProperties).toArray(String[]::new);
return stringArray;
}
@Override
public Collection<Image> toEntityAttribute(String[] values) {
return super.toEntityAttribute(values);
}
}
ImageConverter
class 只是实现了 AttributeConverter<Image, String>
我在其中序列化和反序列化我的图像对象 to/from json.
我选择采用这种方法,因为我在一个对象中有 Image
字段,在另一个对象中有 List<Image>
字段。因此,只需将 @Convert(ListImageConverter.class)
更改为 @Convert(ImageConverter.class)
,我就能够在 Neo4j 数据库中保存列表和单个对象。
注意:您可以根据需要跳过重写 toEntityAttribute
方法。它没有增加太多价值。
但是,您必须覆盖 toGraphProperty
,因为在 Neo4j 代码中,它会检查是否存在名称为 toGraphProperty
.
的已声明方法
希望这对某人有所帮助!
此致,
V
我正在尝试为嵌套对象编写自定义转换器,以便该对象在 Neo4j 数据库中保存为字符串。
我在我的字段上使用 @Convert
注释并传递 ImageConverter.class
这是我的 AttributeConverter
class.
一切正常,我可以在 Neo4j 数据库中保存 Image
class 的字符串表示。
但是,现在我想要 List<Image>
作为我的嵌套字段,而不是单个图像。在这种情况下,输入 @Convert(ImageConverter.class)
不起作用。
我看到有一个名为 ConverterBasedCollectionConverter
的 class,当我有一个 List<LocalDateTime
.
但是,我找不到任何关于如何在自定义转换器的情况下使用此 class 的示例。
任何人都可以帮我解决这个问题,或者是否有任何其他方法可以在 List
.
我在我的应用程序中使用 Neo4j(版本 3.4.1)和 Spring-data-neo4j(5.0.10.RELEASE)。我也在用OGM
PS:我知道建议将嵌套对象存储为与父对象建立关系的单独节点。但是,我的用例要求将对象存储为字符串 属性 而不是单独的节点。
此致,
V
这并不像我想象的那么难。
给定一个 class(片段)
@NodeEntity
public class Actor {
@Id @GeneratedValue
private Long id;
@Convert(MyImageListConverter.class)
public List<MyImage> images = new ArrayList<>();
// ....
}
MyImage
尽可能简单
public class MyImage {
public String blob;
public MyImage(String blob) {
this.blob = blob;
}
public static MyImage of(String value) {
return new MyImage(value);
}
}
和转换器
public class MyImageListConverter implements AttributeConverter<List<MyImage>, String[]> {
@Override
public String[] toGraphProperty(List<MyImage> value) {
if (value == null) {
return null;
}
String[] values = new String[(value.size())];
int i = 0;
for (MyImage image : value) {
values[i++] = image.blob;
}
return values;
}
@Override
public List<MyImage> toEntityAttribute(String[] values) {
List<MyImage> images = new ArrayList<>(values.length);
for (String value : values) {
images.add(MyImage.of(value));
}
return images;
}
}
将在保存时打印以下调试输出,我认为这是您想要的:
UNWIND {rows} as row CREATE (n:Actor) SET n=row.props RETURN row.nodeRef as ref, ID(n) as id, {type} as type with params {type=node, rows=[{nodeRef=-1, props={images=[blobb], name=Jeff}}]}
尤其是图像部分。
这样的测试方法
@Test
public void test() {
Actor jeff = new Actor("Jeff");
String blobValue = "blobb";
jeff.images.add(new MyImage(blobValue));
session.save(jeff);
session.clear();
Actor loadedActor = session.load(Actor.class, jeff.getId());
assertThat(loadedActor.images.get(0).blob).isEqualTo(blobValue);
}
我找到了解决问题的方法。所以,如果你想要另一个解决方案以及@meistermeier 提供的解决方案,你可以使用下面的代码。
public class ListImageConverter extends ConverterBasedCollectionConverter<Image, String>{
public ListImageConverter() {
super(List.class, new ImageConverter());
}
@Override
public String[] toGraphProperty(Collection<Image> values) {
Object[] graphProperties = super.toGraphProperty(values);
String[] stringArray = Arrays.stream(graphProperties).toArray(String[]::new);
return stringArray;
}
@Override
public Collection<Image> toEntityAttribute(String[] values) {
return super.toEntityAttribute(values);
}
}
ImageConverter
class 只是实现了 AttributeConverter<Image, String>
我在其中序列化和反序列化我的图像对象 to/from json.
我选择采用这种方法,因为我在一个对象中有 Image
字段,在另一个对象中有 List<Image>
字段。因此,只需将 @Convert(ListImageConverter.class)
更改为 @Convert(ImageConverter.class)
,我就能够在 Neo4j 数据库中保存列表和单个对象。
注意:您可以根据需要跳过重写 toEntityAttribute
方法。它没有增加太多价值。
但是,您必须覆盖 toGraphProperty
,因为在 Neo4j 代码中,它会检查是否存在名称为 toGraphProperty
.
希望这对某人有所帮助!
此致,
V