我在Neo4J上切齿。我试图了解在Graph DB上实现多个同时更改的正确方法是什么。
在开始之前,让我澄清一下,由于几个原因,我必须在Java / Scala应用程序中使用Neo4J作为嵌入式数据库,而不是作为我可以抛出REST调用的远程服务器。此外,我必须使用Cypher构建命令并使用Neo4J的Java API执行:exectureQuery
所以,这里有一段代码来举例说明我要做的事情:
val db = new TestGraphDatabaseFactory().newImpermanentDatabase()
val query1 =
"""
|Create (d: Dish {name:"Fish Curry",from:"India"}),
|(t: Table {no: 1}),
|(d)-[r:ORDERED_FROM]->(t)
""".stripMargin
val query2 =
"""
|Match (d:Dish {name: "Fish Curry"}),
|(t: Table {no: 1}),
|(d)-[r:ORDERED_FROM]->(t)
|Delete r
""".stripMargin
val query3 =
"""
|Match (d:Dish {name: "Fish Curry"}), (t: Table {no: 1})
|Create (d)-[r:SERVED_AT]->(t)
""".stripMargin
假设我在一家餐馆塑造一个典型的夜晚。我从菜单中选择一个特定的菜肴并下订单。此时, query1 被触发。创建节点和关系。
val v1 = db.execute(query1).resultAsString()
// ... I consume 'v1' appropriately
经过一段时间后,菜已准备就绪并送达。现在,为了反映发生了什么,要触发以下命令:
val v2 = db.execute(query2).resultAsString
val v3 = db.execute(query3).resultAsString
详细说明(无论如何这对所有Neo4J专家来说都是显而易见的),我正在切断碟子和桌子之间 ORDERED_FROM 的关系,并通过 SERVED_AT <的关系将它们绑在一起/ em>的
我有两个问题:
因为我通过两个单独的Cypher查询进行了2次更新,所以我可能在交易保证上缺失。在删除旧关系和添加新关系之间, dish 容易受到另一个正交更新(可能是另一个执行线程)。如果这种理解是正确的,那么我必须做些什么来阻止它?
在上面的示例中, Dish 节点的属性是硬编码的。但是,在实践中,这些将是变量,它们的值在运行时分配。因此,在执行查询{2,3}时,可能找不到 Dish 或 Table 。处理这个问题的正确方法是什么?如果我正确理解API,可能不会抛出任何异常。
我搜索了各种博客和其他网站以找到答案,但我没有。所以,如果我正在寻找的答案已经存在,请指出这一点。
感谢任何帮助。
答案 0 :(得分:0)
您必须在查询执行之外启动事务。否则,Cypher将为一个查询启动隐式tx。
try (Transaction tx= db.beginTx()) {
db.execute(query1,params).close();
db.execute(query1,params).close();
tx.success();
}
请注意,这会使用try-with-resource,否则您必须手动调用tx.close()
。