如何在并行执行多个Neo4j CRUD操作时修复随机NPE和“Neo.ClientError.Statement.EntityNotFound”?

时间:2015-11-10 11:31:15

标签: java spring neo4j junit4 spring-data-neo4j-4

我正在使用Spring数据neo4j - 4并验证我的服务层的行为,我运行了多个Junit测试,这些测试在各种neo4j节点上执行域(CRUD)操作,还创建和删除关系。这些操作和测试不是相互依赖的。偶尔我会针对不同的测试得到这个错误。

org.neo4j.ogm.session.result.ResultProcessingException: "errors"[{"code":"Neo.ClientError.Statement.EntityNotFound","message":"Node with id 24213"}]}
[error]     at      org.neo4j.ogm.session.response.JsonResponse.parseErrors(JsonResponse.java:165)
[error]     at org.neo4j.ogm.session.response.JsonResponse.next(JsonResponse.java:101)
[error]     at org.neo4j.ogm.session.response.JsonResponse.next(JsonResponse.java:30)
[error]     at org.neo4j.ogm.session.response.GraphRowModelResponse.next(GraphRowModelResponse.java:52)
[error]     at org.neo4j.ogm.session.response.GraphRowModelResponse.next(GraphRowModelResponse.java:32)
[error]     at org.neo4j.ogm.session.response.SessionResponseHandler.loadByProperty(SessionResponseHandler.java:55)
[error]     at org.neo4j.ogm.session.delegates.LoadByTypeDelegate.loadAll(LoadByTypeDelegate.java:81)
[error]     at org.neo4j.ogm.session.delegates.LoadByTypeDelegate.loadAll(LoadByTypeDelegate.java:109)
[error]     at org.neo4j.ogm.session.Neo4jSession.loadAll(Neo4jSession.java:158

有趣的是,随机测试场景正在发生这种情况。我已经确保我为不同的测试和设置使用不同的新会话。服务类创建自己的会话。但这似乎都没有帮助。

这是驱动程序或弹簧层或neo4j本身的问题吗?任何建议,可能有助于解决问题?

NPE:

    <failure message="Error mapping GraphModel to instance of com.mylivn.neo4j.domain.User"         type="org.neo4j.ogm.metadata.MappingException">org.neo4j.ogm.metadata.MappingException: Error mapping GraphModel to instance of com.mylivn.neo4j.domain.User
at          org.neo4j.ogm.mapper.GraphEntityMapper.mapEntities(GraphEntityMapper.java:97)
at org.neo4j.ogm.mapper.GraphEntityMapper.map(GraphEntityMapper.java:69)
at org.neo4j.ogm.session.response.SessionResponseHandler.loadByProperty(SessionResponseHandler.java:60)
at org.neo4j.ogm.session.delegates.LoadByTypeDelegate.loadAll(LoadByTypeDelegate.java:81)
at org.neo4j.ogm.session.delegates.LoadByTypeDelegate.loadAll(LoadByTypeDelegate.java:109)
at org.neo4j.ogm.session.Neo4jSession.loadAll(Neo4jSession.java:158)
at com.mylivn.neo4j.services.utils.Neo4jHelper.getByUuid(Neo4jHelper.scala:39
Caused by: java.lang.NullPointerException
at org.neo4j.ogm.entityaccess.DefaultEntityAccessStrategy.getPropertyWriter(DefaultEntityAccessStrategy.java:77)
at org.neo4j.ogm.entityaccess.DefaultEntityAccessStrategy.getPropertyWriter(DefaultEntityAccessStrategy.java:47)
at org.neo4j.ogm.mapper.GraphEntityMapper.writeProperty(GraphEntityMapper.java:145)
at org.neo4j.ogm.mapper.GraphEntityMapper.setProperties(GraphEntityMapper.java:138)
at org.neo4j.ogm.mapper.GraphEntityMapper.createRelationshipEntity(GraphEntityMapper.java:272)
at org.neo4j.ogm.mapper.GraphEntityMapper.mapRelationshipEntity(GraphEntityMapper.java:233)
at org.neo4j.ogm.mapper.GraphEntityMapper.mapRelationships(GraphEntityMapper.java:197)
at org.neo4j.ogm.mapper.GraphEntityMapper.mapEntities(GraphEntityMapper.java:95)
... 79 more

NPE失败更令人费解。当我查看代码时,如果请求进入一个线程,除非另一个线程从propertyWriterCache中删除该条目,它应该不会失败。 这似乎不是线程安全的,但我没有看到任何代码从propertyWriterCache中删除条目

引发NPE的代码

@Override
public EntityAccess getPropertyWriter(final ClassInfo classInfo, String propertyName) {
if(!propertyWriterCache.containsKey(classInfo))
{ propertyWriterCache.put(classInfo,new HashMap<String, EntityAccess>()); }
if(propertyWriterCache.get(classInfo).containsKey(propertyName))
{ //*line77* return propertyWriterCache.get(classInfo).get(propertyName); }
MethodInfo setterInfo = classInfo.propertySetter(propertyName);
EntityAccess propertyWriter = determinePropertyAccessor(classInfo, propertyName, setterInfo, new AccessorFactory<EntityAccess>() {
@Override
public EntityAccess makeMethodAccessor(MethodInfo methodInfo)
{ return new MethodWriter(classInfo, methodInfo); }
@Override
public EntityAccess makeFieldAccessor(FieldInfo fieldInfo)
{ return new FieldWriter(classInfo, fieldInfo); }
});
propertyWriterCache.get(classInfo).put(propertyName, propertyWriter);
return propertyWriter;
}

1 个答案:

答案 0 :(得分:0)

我在使用Session.save()经常保存一个NodeEntity时遇到了同样的问题。我认为根本原因是当调用Session.save()时, NodeEntity的相关修改对象(涉及Relationship,RelationshipEntity和path)将再次保存。因此,当具有多个并行运行的场景时,会导致数据异步。

最后,我用保存的RelationshipEntity替换了保存修改后的NodeEntity。这暂时解决了问题。希望能帮到你。

注意:这不是最佳解决方案。