3

我刚开始使用图形数据库,并认为最好的学习方法是 neo4j。我有一个在应用程序中运行的嵌入式 neo4j 实例(基于 JSF)。该应用程序的用例主要是让我学习使用图形数据库的概念和陷阱,并帮助确定最佳方式(即嵌入式或独立)。但是我的测试应用程序是一个非常基本的联系人应用程序,它能够定义关系(即 KNOWS、WORKS_WITH、WORKS_FOR 等)并最终能够根据这些关系提出建议(即“你可能也知道”)。

到目前为止,我已经掌握了基本的 crud 操作,并且可以添加/删除关系。我的下一步将是真正开始遍历图表(我认为)。但是我目前遇到的问题是,一旦我与服务器的会话到期,我就无法重新建立新会话,而不会收到 IllegalStateException 错误,抱怨商店当前正在使用中。我认为这是因为我从未在 neo4j 实例上调用 shutdown。所以这让我认为我处理交易的方式都是错误的,所以我希望有人能纠正我对我应该如何处理这件事的理解(或视情况而定的误解)。

以下是我的帮助类中的一些方法,这些方法用于处理 Web 客户端和 Neo4j 之间的操作:

public class NeoNodeUtils {
private GraphDatabaseService graphDb;

public NeoNodeUtils() {
    setup();
}

public void setup() {
    GraphDatabaseFactory neoFactory = new GraphDatabaseFactory();
    setGraphDb(neoFactory.newEmbeddedDatabase("Morpheus"));
    registerShutdownHook();
}

public GraphDatabaseService getGraphDb() {
    return graphDb;
}

public void setGraphDb(GraphDatabaseService graphDb) {
    this.graphDb = graphDb;
}

public Node getNode(Long id) {
    Transaction tx = getGraphDb().beginTx();
    Node node = null;
    try {
        node = getGraphDb().getNodeById(id);
        tx.success();
    } catch (Exception e) {
        tx.failure();
        e.printStackTrace();
    } finally {
        tx.finish();
        return node;
    }
}

public Node createNode() {
    Transaction tx = getGraphDb().beginTx();
    Node node = null;
    try {
        node = graphDb.createNode();
        System.out.println("new nodeId = " + node.getId());
        tx.success();
    } catch (Exception e) {
        tx.failure();
        e.printStackTrace();
    } finally {
        tx.finish();
        return node;
    }
}

public Node addNodeProperty(Node node, String propertyName, Object propertyValue) {
    Transaction tx = getGraphDb().beginTx();
    try {
        node.setProperty(propertyName, propertyValue);
        tx.success();
    } catch (Exception e) {
        tx.failure();
        e.printStackTrace();
    } finally {
        tx.finish();
        return node;
    }
}

public void shutDown() {
    graphDb.shutdown();
}

public void registerShutdownHook() {
    Runtime.getRuntime().addShutdownHook(new Thread() {
        @Override
        public void run() {
            graphDb.shutdown();
        }
    });
}
}

每个辅助方法的结构几乎都与 getNode(Long id) 和 createNode() 完全相同,当然有些有更多的逻辑,但没有什么很复杂,因为我只是想学习这个。

所以,最后我的问题是:
*这是处理这些交易的正确方法吗?或者,我应该实现某种类型的事务管理器吗?
* 另外,我应该在每笔交易后调用关机吗?
* 也许这应该在客户端会话级别而不是应用程序级别处理?

此类将保留在服务器内存中,直到服务器 (http/jvm) 重新启动(如果您熟悉 jsf、applicationScope),因此在每次事务后调用 shutdown 似乎有点过头了。

编辑:我实际上对下面哪个答案标记为已接受感到困惑,因为他们都在某种程度上回答了我的问题。因此,如果您想知道为什么答案不被接受,那就是原因。

4

3 回答 3

5

不要将 GraphDatabaseService 视为 SQLConnection 或类似的,它是一个长期存在的实例,并且开始经常停止它会消除从长期存在的此类实例中获得的许多好处,并带来大量不必要的开销。

你不需要像那样调用 tx.failure() 。一个简单的:

公共节点 createNode() {
    交易 tx = getGraphDb().beginTx();
    尝试 {
        节点节点 = graphDb.createNode();
        System.out.println("new nodeId = " + node.getId());
        tx.成功();
        返回节点;
    } 最后 {
        tx.finish();
    }
}

很好,因为只有在调用 success() 时才认为事务成功,否则将回滚。此外,根本不需要在事务中执行读取操作,因此:

公共节点getNode(长ID){
    返回 getGraphDb().getNodeById(id);
}

足够的。

于 2012-08-06T11:15:41.923 回答
3

由于 Java 7 自动关闭和 Neo4J 2.0 处理事务的方式是:

try (Transaction tx = graphDb.beginTx())
{
  ...

  tx.success();
}

因此finish不再需要显式。

于 2014-05-09T17:16:34.207 回答
1

您的事务处理似乎很好。不,您不应该在每次交易后关闭。只需通过单例获取neo4j db的句柄-从您上面提到的内容来看,该类似乎已重新实例化,这就是问题所在-它试图打开与neo4j的另一个连接,这是不允许的。

于 2012-08-04T11:13:54.940 回答