在嵌入式neo4j中处理事务的最佳方式?

在嵌入式neo4j中处理事务的最佳方式?,neo4j,Neo4j,我刚从图形数据库开始,我认为最好的学习工具是neo4j。我在应用程序中运行了一个嵌入式neo4j实例(基于JSF)。应用程序的用例主要是让我学习使用graph db的概念和窍门,并帮助确定最佳方式(即嵌入式或独立)。但我的测试应用程序是一个非常基本的联系人应用程序,能够定义关系(即知道、与之合作、为之工作等),并最终能够根据这些关系提出建议(即“你可能也知道”) 到目前为止,我已经有了基本的c.r.u.d操作,可以添加/删除关系。我的下一步将是实际开始遍历图形(我想)。但我目前遇到的问题是,一旦

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

到目前为止,我已经有了基本的c.r.u.d操作,可以添加/删除关系。我的下一步将是实际开始遍历图形(我想)。但我目前遇到的问题是,一旦我与服务器的会话过期,我就无法重新建立新会话,除非收到IllegalStateException错误,抱怨存储当前正在使用。我想这是因为我从来没有在neo4j实例上调用过shutdown。因此,这让我觉得我处理交易的方式完全是错误的,所以我希望有人能纠正我对应该如何处理这件事的理解(或误解,视情况而定)

以下是my helper类中的一些方法,这些方法用于处理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();
        }
    });
}
}
每个helper方法的结构都与getNode(Long id)和createNode()完全相同,当然有些方法的逻辑稍微多一些,但并没有什么非常复杂的地方,因为我只想学习一下

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

在服务器(http/jvm)重新启动之前(如果您熟悉jsf、applicationScope),这个类一直保存在服务器内存中,因此在每次事务之后调用shutdown似乎有点过火


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

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

不要将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(); } } 公共节点createNode(){ 事务tx=getGraphDb().beginTx(); 试一试{ Node Node=graphDb.createNode(); System.out.println(“new nodeId=“+node.getId()); 成功(); 返回节点; }最后{ tx.finish(); } } 因为只有在调用success()时事务才会被视为成功,否则将回滚。此外,读取操作根本不需要在事务中执行,因此:

public Node getNode(Long id) { return getGraphDb().getNodeById(id); } 公共节点getNode(长id){ 返回getGraphDb().getNodeById(id); }
足够了。

由于Java 7 autoclose和Neo4J 2.0,处理事务的方法是:

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

  tx.success();
}

因此,不再需要显式的
finish

感谢您的澄清,您有任何SQLConnection的示例吗?请注意,在Neo4j 2中
finish
被弃用,取而代之的是
close
,它允许使用try with resources Java 7'语句。那么,如果我们创建一组节点,它们是否可以搜索,即使我们仍然没有犯下他们?@WantIt不,除非你犯下他们,否则无法联系到他们。注意这一点,我花了两个月的时间才意识到这一点。感谢您验证我对如何实现这一点的想法。“看起来这个类被重新实例化了,这就是问题所在”是的,这就是我开始得出的结论。我认为JSF处理applicationScope的方式是,如果应用程序上没有任何活动,那么它会将applicationScope序列化到磁盘,一旦有人发出请求,就会将其反序列化并重新实例化结果。我正在寻找一种方法来解决这个问题,或者拦截这种行为。如果任务太大,那么只需安装一个neo4j服务器实例。