使用 Spring Data Neo4j 4 更新简单对象关系的目标不会产生预期结果
Updating the target of a simple object relationship with Spring Data Neo4j 4 does not yield the expected result
刚刚将一个 Spring Data Neo4j 3 项目迁移到版本 4(4.0.0.RELEASE,Neo4j 2.2.5 社区服务器)并遇到一个简单的单向对象关系问题没有按预期更新。此关系不使用 RelationshipEntity。
节点 A、B1 和 B2 已经在数据存储中并且存在关系 A -> B1,将 A 的 B 目标节点更改为 B2 并保存 A 会得到 B1 <- A -> B2。创建了新关系,但未删除与 B1 的旧关系。
expected resulting state::
actual resulting state
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" />
可以看出,当节点已经存在于数据存储中时,发送到 Neo4j 服务器的 Cypher 不包括对开始 A -> B1 关系的删除调用。它在测试 运行 时间创建节点时执行。所以我认为 Neo4jSession 周围存在一个问题,即现有关系没有被标记为删除 - 但是当同一个会话首先用于创建对象时(在测试中)。
有人在使用或迁移到 SDN 4 时遇到过类似问题吗?我不记得在 SDN 3 中看到过这种情况。这不是我认真研究的东西,它似乎可以工作,但显然 SDN 4 是完全重写的。
我相信这个问题现在已经解决了。您需要使用 OGM 的最新快照版本 1.1.4-SNAPSHOT,而不是 1.1.3 版本。
刚刚将一个 Spring Data Neo4j 3 项目迁移到版本 4(4.0.0.RELEASE,Neo4j 2.2.5 社区服务器)并遇到一个简单的单向对象关系问题没有按预期更新。此关系不使用 RelationshipEntity。
节点 A、B1 和 B2 已经在数据存储中并且存在关系 A -> B1,将 A 的 B 目标节点更改为 B2 并保存 A 会得到 B1 <- A -> B2。创建了新关系,但未删除与 B1 的旧关系。
expected resulting state:: actual resulting state
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" />
可以看出,当节点已经存在于数据存储中时,发送到 Neo4j 服务器的 Cypher 不包括对开始 A -> B1 关系的删除调用。它在测试 运行 时间创建节点时执行。所以我认为 Neo4jSession 周围存在一个问题,即现有关系没有被标记为删除 - 但是当同一个会话首先用于创建对象时(在测试中)。
有人在使用或迁移到 SDN 4 时遇到过类似问题吗?我不记得在 SDN 3 中看到过这种情况。这不是我认真研究的东西,它似乎可以工作,但显然 SDN 4 是完全重写的。
我相信这个问题现在已经解决了。您需要使用 OGM 的最新快照版本 1.1.4-SNAPSHOT,而不是 1.1.3 版本。