Multithreading 使用Neo4j查找或创建与多线程的对比
在基于Neo4j的应用程序中,我有一个经典的查找或创建用例:我询问Neo4j是否已经有一个节点与其他节点具有特殊关系。如果没有,那么我将在同一事务中创建一个。没什么特别的。。。但是,如果我将此方法称为多线程或连接到同一数据库的n个客户机,那么,我不时会遇到一个异常,即有多个元素与我的查询匹配。这意味着在这之前有两个线程都创建了相同的“对”节点。java级别的同步不是一个选项,因为请求可以来自多个客户机/服务器 除了捕获异常并随后删除重复的节点之外,我如何解决这些问题 我使用弹簧数据Neo4j 2.3.3和Neo4j 1.9.5 我的问题是:Multithreading 使用Neo4j查找或创建与多线程的对比,multithreading,neo4j,spring-data-neo4j,Multithreading,Neo4j,Spring Data Neo4j,在基于Neo4j的应用程序中,我有一个经典的查找或创建用例:我询问Neo4j是否已经有一个节点与其他节点具有特殊关系。如果没有,那么我将在同一事务中创建一个。没什么特别的。。。但是,如果我将此方法称为多线程或连接到同一数据库的n个客户机,那么,我不时会遇到一个异常,即有多个元素与我的查询匹配。这意味着在这之前有两个线程都创建了相同的“对”节点。java级别的同步不是一个选项,因为请求可以来自多个客户机/服务器 除了捕获异常并随后删除重复的节点之外,我如何解决这些问题 我使用弹簧数据Neo4j 2
START expected=node({0}), actual=node({1}) MATCH (expected)<-[:EXPECTED]- (pair) -[:ACTUAL]->(actual) RETURN pair
你必须采取手动锁定,否则你会进入典型的比赛条件 锁定两个相关节点可能是最简单的方法 Neo4j事务上有一个锁管理API,但您也可以删除一个不存在的属性,该属性也具有写锁 我们可能不得不在某个时候公开SDN中的锁定。
如果您认为这是个好主意,请提出JIRA问题。您可能还应该分享您的实体代码和用法。感谢Micha的及时回复。这很有帮助,我试试这个。但这让我想到了另一点:正如我在上面所写的,我使用SDN,因此我无法直接访问底层节点。因此,我必须使用Neo4jTemplate查询底层节点,并使用本机neo4japi删除一个不存在的属性,以获取锁。我说得对吗?如果是这样,我还将提出一个特性请求,要求SDN能够将底层节点映射到我的实体实例,这在其他用例中也会有所帮助。
WARN [00:32.31,962] de.xxx.web.AbstractExceptionHandlers: error.NoSuchElementException
java.util.NoSuchElementException: More than one element in org.neo4j.cypher.PipeExecutionResult$$anon$1@8f0dc23. First element is '{pair=Node[20001]}' and the second element is '{pair=Node[20000]}'
at org.neo4j.helpers.collection.IteratorUtil.singleOrNull(IteratorUtil.java:122)
at org.neo4j.helpers.collection.IteratorUtil.singleOrNull(IteratorUtil.java:289)
at org.springframework.data.neo4j.conversion.QueryResultBuilder$1.singleOrNull(QueryResultBuilder.java:94)
at org.springframework.data.neo4j.repository.query.GraphRepositoryQuery.dispatchQuery(GraphRepositoryQuery.java:108)
at org.springframework.data.neo4j.repository.query.GraphRepositoryQuery.execute(GraphRepositoryQuery.java:81)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:337)
at org.springframework.aop.framework.ReflectiveMethodvocation.proceed(ReflectiveMethodvocation.java:172)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithvocation(TransactionInterceptor.java:96)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
at org.springframework.aop.framework.ReflectiveMethodvocation.proceed(ReflectiveMethodvocation.java:172)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
at org.springframework.aop.framework.ReflectiveMethodvocation.proceed(ReflectiveMethodvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at com.sun.proxy.$Proxy63.findByAttributes(Unknown Source)
at de.xxx.core_service.attribute.AttributeManagerImpl.findOrCreatePair_aroundBody32(AttributeManagerImpl.java:212)
at de.xxx.core_service.attribute.AttributeManagerImpl$AjcClosure33.run(AttributeManagerImpl.java:1)