Neo4j 如何保证在事务中的两个现有节点之间只创建一个新的唯一节点

Neo4j 如何保证在事务中的两个现有节点之间只创建一个新的唯一节点,neo4j,cypher,spring-data-neo4j,neo4j-ogm,Neo4j,Cypher,Spring Data Neo4j,Neo4j Ogm,我的图中有以下两个现有节点 由唯一客户编号标识的客户节点。 由唯一ISBN标识符标识的产品节点 我想在一个客户节点和一个产品节点之间创建关联。 但我想将此关联表示为一个名为许可节点的新节点,该节点将有一个到客户节点的链接和一个到产品节点的链接 此许可证节点将生成一个新的内部标识符作为随机GUID 我的应用程序中创建新的许可证节点并将其链接到其他2个节点的逻辑在一个事务中执行 if(尚未与该客户的许可证关联的产品) 使用新的随机GUID创建新的许可证节点 创建从新许可证节点到产品节点的关系 创建从

我的图中有以下两个现有节点

由唯一客户编号标识的客户节点。 由唯一ISBN标识符标识的产品节点

我想在一个客户节点和一个产品节点之间创建关联。 但我想将此关联表示为一个名为许可节点的新节点,该节点将有一个到客户节点的链接和一个到产品节点的链接

许可证节点将生成一个新的内部标识符作为随机GUID

我的应用程序中创建新的许可证节点并将其链接到其他2个节点的逻辑在一个事务中执行

if(尚未与该客户的许可证关联的产品)
使用新的随机GUID创建新的许可证节点
创建从新许可证节点到产品节点的关系
创建从客户节点到新许可证节点的关系

但是,多个请求可以使用相同的ISBN和客户号同时到达。 发生这种情况时,我有时会收到为同一客户产品节点创建的重复许可证节点。 SpringDataNeo4j中的事务似乎并没有阻止这种情况的发生

如何确保在客户节点和产品节点之间只创建一个许可证节点

SpringDataNeo4j中的事务似乎并没有阻止这种情况的发生

Neo4j已读取事务的提交隔离级别。要防止这种情况,您需要可序列化

要实现您的需求,您可以:

  • 在执行
    尚未与…关联的产品检查之前,锁定产品和客户节点。您可以使用类似这样的查询(在同一事务中)来执行此操作:

    与客户类似

  • 向许可证添加一个特殊密钥,它是产品ID和客户ID的串联-然后在该密钥上创建一个唯一的约束


您用来执行逻辑的密码查询看起来如何?感谢Bruno,我使用的是Java 1.8和Spring数据Neo4j 4.2.0,密码由框架生成。事务也被定义为注释。我将尝试一下frant.hartm在下面的回答中提出的建议。谢谢frant。我采取了第一种方法,这对我很有效。在事务开始时使用
MATCH(p:Product),其中ID(p)={ID}设置p._lock=1
,在事务结束时使用
MATCH(p:Product),其中ID(p)={ID}删除p._lock
。事务开始时的
REMOVE n._lock
也应该可以工作,并在事务结束时为您保存一个查询。是的,这也奏效了。我想我理解了,因为删除属性可以确保在节点上使用写锁
在添加、更改或删除节点或关系上的属性时,将对特定节点或关系执行写锁定。
我注意到,在进一步测试后,我现在可以重新构建一个测试,其中仅通过一次调用删除属性是不起作用的。但是,在检查之前设置属性,然后在tx代码末尾删除属性,这对我的所有测试都有效(我永远无法100%测试)。我想知道,如果Neo4j检测到您试图删除一个不存在的属性,并且在早期版本中它可能已经这样做了,那么它是否可能没有在节点上使用写锁?@DonalHurley这是什么版本的Neoj4?你能分享一下这个测试用例吗?
MATCH (n:Product) WHERE ID(n) = {id} REMOVE n._lock