0

我正在开发一个 Neo4J 数据库,在一个小型社交网络中使用它。这个想法是:作为用户,您连接到网站,它会将您连接到 N4J 数据库。我试图通过单例创建它来避免与数据库的多个实例相关的问题。但是,我认为我的用户必须能够“连接”和“断开连接”,所以我为此创建了方法,但是当我对用户使用 disconnect() 时,其他用户会运行 NullPointerException,因为他们可以'不再访问数据库(我认为这是由 Singleton 处理的)。

这是代码,我相信它会使事情更清楚:

我用来测试我的代码的主要内容:

public static void main(String[] args) {

        Node root;
        N4JAdmin admin = new N4JAdmin();

        Transaction tx = GraphDB.getGraphDb().beginTx();
        try {
            root = GraphDB.getGraphDb().createNode();
            root.setProperty("Nom", "aname");
            root.setProperty("Prenom", "afirstname");
            tx.success();
        } finally {
            tx.finish();
        }

        N4JUser sr = admin.addUser("Ribeiro", "Swen", 1);
        //14 more addUser, it creates nodes in the db with the 3 properties, works fine


//      The following connect() calls are commented because the errors occurs with or without them

//      sr.connect();
//      the 14 others...

        sr.addAcquaintance(cw.getUserNode());
        sr.addAcquaintance(fc.getUserNode());

        sr.disconnect();
        System.out.println("+++++++++ sr disconnected ++++++++++");

        bm.addAcquaintance(cm.getUserNode());
// and more operations...

        GraphDB.getGraphDb().shutdown();
    }

addAquaintance 代码:

 public void addAcquaintance(Node target) {
            Transaction tx = GraphDB.getGraphDb().beginTx();
            try {           
                this.userNode.createRelationshipTo(target, RelTypes.CONNAIT);
                System.out.println(this.userNode.getProperty("Nom")+" "+this.userNode.getProperty("Prenom")+" est maintenant ami avec : "+ target.getProperty("Nom")+" "+target.getProperty("Prenom"));
                tx.success();
            } finally {
                tx.finish();
            }
        }

还有 GraphDB 类,这是我的 Singleton :

public final class GraphDB {

    private static final String DB_PATH = "/Workties/database/workties.db";
    private static GraphDatabaseService graphDb;
    private static boolean instanciated = false;

    private GraphDB(){
        GraphDB.graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(DB_PATH);
        registerShutdownHook(graphDb);
        GraphDB.instanciated = true;
    }

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

    public static GraphDatabaseService getGraphDb(){
        if (!GraphDB.instanciated) {
            new GraphDB();
            System.out.println("New connection : " +GraphDB.graphDb.toString());
        }
        return GraphDB.graphDb; 
    }
}

注意:instanciated 属性是后来添加的,但即使没有它也不起作用。

我的问题来自这样一个事实,即我认为使用单例不会发生这种类型的错误,所以我有点卡住了......

在此先感谢您的帮助 !

编辑:断开方法:

public void disconnect(){
        GraphDB.getGraphDb().shutdown();
    }
4

1 回答 1

3

您不必为每个用户调用shutdown-一旦第一次实例化数据库,就足以让您完成所有查询等。为什么要连接和断开连接?

空指针是因为shutdown 会关闭Neo4j,但您的单例仍然认为instanciated=true,所以它返回一个实际上并不存在的graphDb 的句柄。即使没有您添加的实例化变量,单例在关闭后仍会保留对 graphDb 的引用。强烈建议不要关闭,除非您的应用程序正在终止。

于 2013-05-28T14:16:24.693 回答