Neo4j - 无法在创建与java的关系时回滚事务

时间:2015-11-07 15:56:04

标签: java neo4j

我试图通过Maven Java Application在Neo4j中创建一些节点,并在这些节点之间创建关系。我想要创建16807个节点和17210368关系。我读取了一个文件并获取了row变量,该变量具有我必须创建的节点数,并且我还有一个list,其中有34420736个元素(= 17210368 * 2)。我想创建一个从节点[列表的元素0]到节点[列表中的元素1],从节点[列表的元素2]到节点[列表中的元素3]等的关系。此外,列表的最大元素是16807。我创建ArrayList<Node>以动态创建节点,因为我希望程序使用不同的文件(以及不同的行值)运行。

这是我的代码:

    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循环时,它会抛出以下错误:

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

任何想法??

1 个答案:

答案 0 :(得分: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();
        }
    }

}