在我的基于Neo4j的应用程序中,我有一个经典的查找或创建用例:我问neo4j是否已经有一个与其他节点有特殊关系的节点。如果没有,那么我将在同一个交易中创建一个。没有什么特别的......但是如果我把这个方法称为多线程(或者n-clients连接到同一个数据库),那么,我不时会得到一个异常,它说我的查询中有多个元素匹配。这意味着在两个时刻之前有两个线程创建了相同的“对”节点。 java级别的同步不是一个选项(因为请求可以来自多个客户端/服务器)。
如何解决此类问题,除了捕获异常并在之后删除重复的节点?
我使用的是Spring Data Neo4j 2.3.3和Neo4j 1.9.5。
这是我的问题:
START expected=node({0}), actual=node({1}) MATCH (expected)<-[:EXPECTED]- (pair) -[:ACTUAL]->(actual) RETURN pair
顺便说一下。在这种情况下抛出的异常是NoSuchElementException
,至少对我来说这有点令人困惑。
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)
答案 0 :(得分:0)
你必须手动锁定,否则你会遇到典型的竞争条件。
通过锁定有问题的节点可能最容易。
Neo4j Transaction上有一个锁管理API,但你也可以删除一个也存在写锁的不存在的属性。
我们可能必须在某些时候在SDN中公开锁定。 如果您认为这是一个好主意,请提出JIRA问题。