Neo4j - Пользовательский конвертер для поля типа Список - PullRequest
0 голосов
/ 30 января 2019

Я пытаюсь написать собственный конвертер для вложенного объекта, чтобы этот объект был сохранен в виде строки в базе данных Neo4j.

Я использую аннотацию @Convert на своем поле и передаю ImageConverter.class, что является моим AttributeConverter классом.

enter image description here

enter image description here

Все работает нормально, как и ожидалось, и я могу сохранить строковое представление класса Image в Neo4j db.

Однако теперь вместо одного изображенияЯ хочу иметь List<Image> в качестве моего вложенного поля.В этом случае установка @Convert(ImageConverter.class) не работает.

Я вижу, что есть класс с именем ConverterBasedCollectionConverter, который используется, когда у меня есть поле типа List<LocalDateTime.

Однако я не смог найти никаких примеров того, как использовать этот класс в случае пользовательских преобразователей.

Пожалуйста, кто-нибудь может мне помочь с этим или есть какой-либо другой подход к использованию пользовательского преобразователя в поле типа List.

Я использую Neo4j (версия 3.4.1) и Spring-data-neo4j (5.0.10.RELEASE) в моем приложении.Я также использую OGM.

PS: я знаю, что рекомендуется хранить вложенные объекты как отдельный узел, устанавливая связь с родительским объектом.Однако мой вариант использования требует, чтобы объект был сохранен как строковое свойство, а не как отдельный узел.

С уважением,

V

Ответы [ 2 ]

0 голосов
/ 31 января 2019

Я придумала решение моей проблемы.Так что, если вам нужно другое решение вместе с решением, предоставленным @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 класс просто реализует AttributeConverter<Image, String> гдеЯ сериализую и десериализую свой объект Image в / из json.

Я выбрал этот подход, потому что у меня было поле Image в одном объекте и List<Image> в другом объекте.Поэтому, просто изменив @Convert(ListImageConverter.class) на @Convert(ImageConverter.class), я смог сохранить список, а также отдельный объект в базе данных Neo4j.

Примечание. Вы можете пропустить переопределение метода toEntityAttribute, если хотите.Это не добавляет особой ценности.Однако вы должны переопределить toGraphProperty, так как в коде Neo4j он проверяет наличие объявленного метода с именем toGraphProperty.

Надеюсь, это кому-нибудь поможет!

С уважением,

V

0 голосов
/ 31 января 2019

Это не так сложно, как я предполагал.

Учитывая класс (фрагмент)

@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);

}
...