使用Spring数据Neo4j 4更新简单对象关系的目标不会产生预期的结果

使用Spring数据Neo4j 4更新简单对象关系的目标不会产生预期的结果,neo4j,spring-data-neo4j,spring-data-neo4j-4,Neo4j,Spring Data Neo4j,Spring Data Neo4j 4,刚刚将SpringDataNeo4J3项目迁移到版本4(4.0.0.RELEASE,Neo4J2.2.5社区服务器),遇到了一个简单的单向对象关系没有按预期更新的问题。此关系不使用关系实体 当节点A、B1和B2已经在数据存储中并且存在关系A->B1时,将A的B目标节点更改为B2并保存A将得到B1 B2。已创建新关系,但未删除与B1的旧关系 :: A定义了与B的关系,但B没有定义与A的关系(因为B到A可能最终是一对多) B 调试这个过程花费了很长时间(尽管应用程序中出现了一致的故障),因为似乎不

刚刚将SpringDataNeo4J3项目迁移到版本4(4.0.0.RELEASE,Neo4J2.2.5社区服务器),遇到了一个简单的单向对象关系没有按预期更新的问题。此关系不使用关系实体

当节点A、B1和B2已经在数据存储中并且存在关系A->B1时,将A的B目标节点更改为B2并保存A将得到B1 B2。已创建新关系,但未删除与B1的旧关系

::

A定义了与B的关系,但B没有定义与A的关系(因为B到A可能最终是一对多)

B

调试这个过程花费了很长时间(尽管应用程序中出现了一致的故障),因为似乎不可能编写失败的集成测试(针对真正的Neo4j服务器运行)。事实上,当在测试运行时创建对象a、B1和B2时,我无法编写失败的测试。但是,当测试运行时(运行应用程序时的实际情况)数据存储中已经存在三个节点和关系时,就会看到B1 B2结果。测试的基本结构如下(可以提供完整的代码)

//查找TypeA节点
Iterable As=typeARepository.findAll();
TypeA a=Iterables.get(As,0);
//使用其字符串标识符查找TypeB节点
TypeB b1=typeBRepository.findByIdentifier(一个);
assertNotNull(b1);
assertEquals(一个,b1.getIdentifier());
//检查这是否是与a相关的TypeB节点
assertEquals(b1.getId(),a.getB().getId());
//使用其字符串标识符查找另一个TypeB节点
TypeB b2=typeBRepository.findByIdentifier(两个);
assertNotNull(b2);
assertEquals(两个,b2.getIdentifier());
//现在在a和这个TypeB节点之间创建一个关系
a、 setB(b2);
//并保存一个
TypeA savedUpdatedA=typeARepository.save(a);
存储库是在测试运行时以编程方式创建的。在运行存储库保存调用之前和之后,使用GraphAware RestTest库验证数据存储子图

设置:

<logger name="org.neo4j.ogm" level="DEBUG" />

可以看出,发送到Neo4j服务器的密码不包括删除调用,用于在数据存储中已经存在节点时,在保存时启动->B1关系。当在测试运行时创建节点时,会执行此操作。因此,我认为在Neo4jSession的某个地方存在一个问题,即现有的关系没有标记为删除——但这是在同一个会话最初用于创建对象时(在测试中)


是否有人在使用或迁移到SDN 4时遇到过类似问题?我不记得在SDN 3上看到过这一点。这并不是我一直在努力研究的东西,它只是看起来很有效,但显然SDN4是一个完全的重写。

我相信这已经被修复了。您需要使用OGM的最新快照版本1.1.4-snapshot,而不是1.1.3版本

这似乎是一个bug。我为此提出了一张罚单:文斯,谢谢你这么快回复我,发现了错误并提出了问题。您的测试用例与我的相似,但要优雅得多!!np:)现在应该可以修复了,请看下面的答案。我们遇到了一些似乎与Neo4jSession如何管理/缓存关系有关的问题,其中大多数问题我们无法在测试中重现(使用InProcessServer),而且它们也无法在真正的Neo4jServer中一致重现。例如,在某一点上,服务器会进入这样的状态:对节点进行任何更改都会恢复第二个节点以前添加/删除的所有关系,但重新启动服务器可以解决此问题。这些问题似乎更可能发生在并发情况下。这里有一个问题,OGM似乎会缓存已删除的关系,直到服务器重新启动:Vince,这是一个很好的周转时间!签出该快照,我的测试现在通过-创建了新关系,删除了旧关系。再次感谢你。
...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

}
// 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);
<logger name="org.neo4j.ogm" level="DEBUG" />