在嵌入式neo4j中处理事务的最佳方法是什么?

时间:2012-08-03 15:10:51

标签: neo4j

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

到目前为止,我已经有了基本的c.r.u.d操作,可以添加/删除关系。我的下一步将是实际开始遍历图表(我认为)。但我目前遇到的问题是,一旦我与服务器的会话到期,我无法重新建立新会话而不会收到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似乎有点过分。

编辑:我实际上已经撕掉了下面的答案标记为已被接受,因为他们都在某种程度上回答了我的问题。所以,如果你想知道为什么没有接受答案,那就是原因。

3 个答案:

答案 0 :(得分:5)

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

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

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

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

public Node getNode(Long id) {
    return getGraphDb().getNodeById(id);
}

够了。

答案 1 :(得分:3)

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

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

  tx.success();
}

因此,不再需要明确的finish

答案 2 :(得分:1)

您的交易处理似乎很好。不,你不应该在每次交易后关机。 通过单例获取neo4j数据库的句柄 - 从上面提到的内容来看,看起来这个类被重新实例化了,这就是问题 - 它试图打开另一个与neo4j的连接而且这是不允许的。