2015-11-07 25 views
0

我试图通过Maven Java应用程序在Neo4j中创建一些节点,并在这些节点之间创建关系。确切地说,我想创建16807节点和17210368关系。我读了一个文件,并得到row变量,它具有我必须创建的节点数,并且我还有一个list,其中包含34420736个元素(= 17210368 * 2)。我想创建一个从节点[列表元素0]到节点[元素1从列表],从节点[列表的元素2]到节点[列表元素3]等的关系。列表的最大元素也是16807。我创建了一个ArrayList<Node>来动态创建节点,因为我希望程序以不同的文件(以及不同的行值)运行。Neo4j - 无法回滚事务以创建与java的关系

这里是我的代码:

GraphDatabaseFactory dbFactory = new GraphDatabaseFactory(); 
    GraphDatabaseService graphDb = dbFactory.newEmbeddedDatabase("C:\Users\....\default.graphdb"); 

    Transaction tx = graphDb.beginTx(); 
    try { 
     final RelationshipType type2 = DynamicRelationshipType.withName("KNOW"); 

     ArrayList<Node> nodelist = new ArrayList<Node>(); 

     for (int k = 0; k < row; k++) { //row=16807 
      nodelist.add(graphDb.createNode()); 
      nodelist.get(k).setProperty("Name", "ListNode " + k); 
     }  

     int count=0; 
     for (int j = 0; j < list.size() ; j++) { //list.size()=34420736 
      nodelist.get(list.get(count)).createRelationshipTo(nodelist.get(list.get(count+1)), type2); 
      count=count+2; 
     } 

     tx.success(); 
    } 
    finally { 
     tx.close(); 
    } 
    graphDb.shutdown(); 

如果我不尝试创建关系它创建的节点和正确运行运行代码。当我添加的for循环创建realtionships它抛出我下面的错误:

Exception in thread "main" org.neo4j.graphdb.TransactionFailureException: Unable to rollback transaction 
at org.neo4j.kernel.TopLevelTransaction.close(TopLevelTransaction.java:131) 
at com.mycompany.traverse_test.traverse_main.main(traverse_main.java:138) 
Caused by: java.lang.IllegalStateException: No RelationshipState for added relationship! 
at org.neo4j.kernel.api.txstate.RelationshipChangeVisitorAdapter$1.visit(RelationshipChangeVisitorAdapter.java:132) 
at org.neo4j.kernel.api.txstate.RelationshipChangeVisitorAdapter.visitAddedRelationship(RelationshipChangeVisitorAdapter.java:83) 
at org.neo4j.kernel.api.txstate.RelationshipChangeVisitorAdapter.visitAdded(RelationshipChangeVisitorAdapter.java:106) 
at org.neo4j.kernel.api.txstate.RelationshipChangeVisitorAdapter.visitAdded(RelationshipChangeVisitorAdapter.java:47) 
at org.neo4j.kernel.impl.util.diffsets.DiffSets.accept(DiffSets.java:76) 
at org.neo4j.kernel.impl.api.state.TxState.accept(TxState.java:156) 
at org.neo4j.kernel.impl.api.KernelTransactionImplementation.rollback(KernelTransactionImplementation.java:542) 
at org.neo4j.kernel.impl.api.KernelTransactionImplementation.close(KernelTransactionImplementation.java:404) 
at org.neo4j.kernel.TopLevelTransaction.close(TopLevelTransaction.java:112) 
... 1 more 

任何想法?

+0

你应该批量更新/数据创建在100k到500k的记录大小。否则,中间交易状态将会比你的堆大并且炸毁。 –

+0

尝试捕获异常并记录它们,然后您会看到您获得了NPE或索引超出界限。通过你的finally块Neo4j试图完成tx,它处于只能回滚的状态。请回报抛出的异常。 –

+0

你使用哪个Neo4j版本? –

回答

1

由于代码中存在错误,Neo4j正试图回滚您的交易。它未能回滚的事实可能是neo4j中的一个错误,但这并不是你的主要问题。

看着你的代码,它看起来像你迭代你的list太多次。也就是说,list循环中的代码一次最多使用2个列表元素,所以您应该只循环list.size()/2次。

这里是应该修复这个错误的代码,它也做了一些其他的改进。

GraphDatabaseFactory dbFactory = new GraphDatabaseFactory(); 
GraphDatabaseService graphDb = dbFactory.newEmbeddedDatabase("C:\Users\....\default.graphdb"); 

Transaction tx = graphDb.beginTx(); 
try { 
    final RelationshipType type2 = DynamicRelationshipType.withName("KNOW"); 

    ArrayList<Node> nodelist = new ArrayList<Node>(); 

    for (int k = 0; k < row; k++) { //row=16807 
     Node node = graphDb.createNode(); 
     node.setProperty("Name", "ListNode " + k); 
     nodelist.add(node); 
    }  

    for (int j = 0; j < list.size() ; j += 2) { //list.size()=34420736 
     nodelist.get(list.get(j)).createRelationshipTo(
      nodelist.get(list.get(j+1)), type2); 
    } 

    tx.success(); 
} catch(Throwable e) { 
    e.printStackTrace(); 
    // You may want to re-throw the exception, rather than just eating it here... 
} finally { 
    tx.close(); 
} 
graphDb.shutdown(); 

[EDITED]

然而,上述代码仍然可以运行的内存,因为它试图在单个事务中创建这么多的资源(16K节点和17M关系)。

以下示例代码在多个事务中(一个用于创建节点和节点列表以及多个关系事务)执行工作。

NUM_RELS_PER_CHUNK指定要在每个事务中创建的最大关系数。必须修改createRelEndpointList()方法以填写关系端点(节点)索引列表(每个索引都是nodeList中节点的0原点位置)。

public class MyCode { 

    private static final int NODE_COUNT = 16807; 
    private static final int NUM_RELS_PER_CHUNK = 1000000; 

    public static void main(String[] args) { 
     doIt(); 
    } 

    private static void doIt() { 
     GraphDatabaseFactory dbFactory = new GraphDatabaseFactory(); 
     GraphDatabaseService graphDb = dbFactory.newEmbeddedDatabase(new File("C:\\Users\\....\\default.graphdb")); 

     try { 
      RelationshipType type = DynamicRelationshipType.withName("KNOW"); 

      List<Node> nodeList = createNodes(graphDb, NODE_COUNT); 
      List<Integer> list = createRelEndpointList(); 

      final int numRels = list.size()/2; 
      final int numChunks = (numRels + NUM_RELS_PER_CHUNK - 1)/NUM_RELS_PER_CHUNK; 

      int startRelIndex = 0, endRelIndexPlus1; 
      for (int i = numChunks; --i >= 0 && startRelIndex < numRels;) { 
       endRelIndexPlus1 = (i > 0) ? startRelIndex + NUM_RELS_PER_CHUNK : numRels; 
       createRelationships(graphDb, nodeList, list, startRelIndex, endRelIndexPlus1, type); 
       startRelIndex = endRelIndexPlus1; 
      } 
     } finally { 
      graphDb.shutdown(); 
     } 
    } 

    private static List<Node> createNodes(GraphDatabaseService graphDb, int rowCount) { 
     ArrayList<Node> nodeList = new ArrayList<Node>(rowCount); 
     Transaction tx = graphDb.beginTx(); 
     try { 
      final StringBuilder sb = new StringBuilder("ListNode "); 
      final int initLength = sb.length(); 
      for (int k = 0; k < rowCount; k++) { 
       Node node = graphDb.createNode(); 
       sb.setLength(initLength); 
       sb.append(k); 
       node.setProperty("Name", sb.toString()); 
       nodeList.add(node); 
      } 
      tx.success(); 
      System.out.println("Created nodes."); 
     } catch(Exception e) { 
      e.printStackTrace(); 
      tx.failure(); 
      return null; 
     } finally { 
      tx.close(); 
     } 
     return nodeList; 
    } 

    private static List<Integer> createRelEndpointList() { 
     final List<Integer> list = new ArrayList<Integer>(); 

     // Fill 
     // list 
     //  ... 

     return list; 
    } 

    private static void createRelationships(GraphDatabaseService graphDb, List<Node> nodeList, List<Integer> list, int startRelIndex, int endRelIndexPlus1, RelationshipType type) { 
     Transaction tx = graphDb.beginTx(); 
     try { 
      final int endPlus2 = endRelIndexPlus1 * 2; 
      for (int j = startRelIndex * 2; j < endPlus2;) { 
       Node from = nodeList.get(list.get(j++)); 
       Node to = nodeList.get(list.get(j++)); 
       from.createRelationshipTo(to, type); 
      } 
      tx.success(); 
      System.out.println("Created rels. Start: " + startRelIndex + ", count: " + (endRelIndexPlus1 - startRelIndex)); 
     } catch(Exception e) { 
      e.printStackTrace(); 
      tx.failure(); 
      // You may want to re-throw the exception, rather than just eating it here... 
     } finally { 
      tx.close(); 
     } 
    } 

} 
+0

好点,但错误依然存在。我不明白为什么Neo4j试图回滚我的交易。我的代码在哪里?这是一个非常简单的代码,除了必须创建的大量关系以外。 – lostromos

+1

如果在'try'块中抛出异常,'finally'块将调用'tx.close()'(并且不会调用'tx.success()')。关闭一个[事务](http://neo4j.com/api_docs/2.0.3/org/neo4j/graphdb/Transaction.html)而不指出它是成功的将导致回滚。如果有异常,我修改了我的答案以打印堆栈跟踪。 – cybersam

+0

我添加了'e.printStackTrace()',并且在抓取博客中调用'tx.failure()'作为Michael Hunger的建议,并打印出'java.lang.OutOfMemoryError:Java heap space'。有谁知道为什么我得到这个错误? – lostromos