Обновление цели простого объектного отношения с помощью Spring Data Neo4j 4 не дает ожидаемого результата
Просто перенесли проект Spring Data Neo4j 3 в версию 4 (4.0.0.RELEASE, Neo4j 2.2.5 Community Server) и столкнулись с проблемой простой односторонней связи объектов, которая не обновляется должным образом. Это отношение НЕ использует RelationshipEntity.
С узлами A, B1 и B2 уже в хранилище данных и существующим отношением A -> B1, изменение целевого узла B B на B2 и сохранение A дает B1 <- A -> B2. Новое отношение создано, но старое отношение к B1 не удалено.
ожидаемое результирующее состояние:: фактическое результирующее состояние
A определяет отношение к B, но B не определяет отношение к A (потому что B к A может оказаться от одного до слишком многих).
...imports omitted
@NodeEntity
public class TypeA {
@GraphId
private Long id;
@Relationship(type = "TYPEB", direction = Relationship.OUTGOING)
private TypeB b;
...getters and setters omitted
}
И Б
...imports omitted
@NodeEntity
public class TypeB {
@GraphId
private Long id;
private String identifier;
public TypeB() {}
public TypeB(String identifier) {
this.identifier = identifier;
}
...getters and setters omitted
}
Отладка этого заняла много времени (несмотря на постоянные сбои в приложении), потому что казалось невозможным написать провальный интеграционный тест (работающий на реальном сервере Neo4j). На самом деле, я не смог написать неудачный тест, когда объекты A, B1 и B2 создаются во время выполнения теста. Но когда три узла и взаимосвязь уже присутствуют в хранилище данных при запуске теста (реалистичная ситуация при запуске приложения), тогда виден результат B1 <- A -> B2. Основная структура теста приведена ниже (полный код может быть предоставлен).
// Find the TypeA node
Iterable<TypeA> As = typeARepository.findAll();
TypeA a = Iterables.get(As, 0);
// Find the TypeB node using its String identifier
TypeB b1 = typeBRepository.findByIdentifier(ONE);
assertNotNull(b1);
assertEquals(ONE, b1.getIdentifier());
// check that this is the TypeB node that is related to a
assertEquals(b1.getId(), a.getB().getId());
// Find the other TypeB node using its String identifier
TypeB b2 = typeBRepository.findByIdentifier(TWO);
assertNotNull(b2);
assertEquals(TWO, b2.getIdentifier());
// now create a relationship between a and this TypeB node instead
a.setB(b2);
// and save a
TypeA savedUpdatedA = typeARepository.save(a);
Репозитории создаются программно во время выполнения теста. И использование библиотеки GraphAware RestTest для проверки подграфа хранилища данных до и после выполнения вызовов сохранения репозитория.
Окружение:
<logger name="org.neo4j.ogm" level="DEBUG" />
Можно видеть, что Cypher, отправленный на сервер Neo4j, не включает в себя вызов удаления для начального отношения A -> B1 при сохранении a, когда узлы уже присутствуют в хранилище данных. Это происходит, когда узлы создаются во время выполнения теста. Поэтому я думаю, что где-то в Neo4jSession существует проблема, из-за которой существующие отношения не помечаются для удаления, но это происходит, когда тот же сеанс использовался для создания объектов в первую очередь (в тесте).
У кого-нибудь были подобные проблемы с использованием или переходом на SDN 4? Я не могу вспомнить, чтобы увидеть это с SDN 3. Это не то, на что я смотрел очень усердно, просто казалось, что оно работает, но, очевидно, SDN 4 - это полное переписывание.
1 ответ
Я считаю, что это сейчас исправлено. Вам нужно будет использовать последнюю версию снимка OGM, 1.1.4-SNAPSHOT, а не версию 1.1.3.