2013-05-28 7 views
0

Я работаю над базой данных Neo4J, используя ее в небольшой социальной сети. Идея такова: В качестве пользователя вы подключаетесь к веб-сайту и соединяете вас с N4J db. Я попытался избежать проблемы, связанной с несколькими экземплярами db, создав ее через Singleton. Тем не менее, я думаю, что мои пользователи должны иметь возможность «подключиться» и «отключиться», поэтому я создал для этого метод, но когда я использую disconnect() для пользователя, остальные работают через исключение NullPointerException из-за того, t доступ к db больше (который, как я думал, обрабатывался Singleton).NullPointerException, доступ к базе данных Neo4J в 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 был добавлен позже, но даже без него он не работал.

Моя проблема исходит из того, что я думал, что этот тип ошибки не будет происходить с помощью Singleton, поэтому я немного застрял ...

Заранее спасибо за вашу помощь!

EDIT: метод отключения:

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

Что делает метод разъединения? Можете ли вы поделиться этим? – Luanne

ответ

3

Вы не должен вызывать остановку для каждого пользователя после того, как DB конкретизируется в первый раз, то хватит на вас для всех ваших запросов и т.д. Почему вы хотите подключиться и отключиться?

Нулевой указатель - это то, что shutdown выключает Neo4j, но ваш singleton все еще считает instanciated = true, поэтому он возвращает дескриптор графика, который на самом деле не существует. Даже без подстроенной переменной, которую вы добавили, singleton поддерживает ссылку на graphDb после ее выключения. Категорически не рекомендуется выполнять остановку, если ваше приложение не завершено.

+0

Спасибо за эти объяснения. Ну, пользователям действительно не нужно подключаться и отключать, но тогда я не вижу, где вызывать выключение, кроме метода registershutdownhook, который вызывается в очень конкретной ситуации. Дело в том, что этот веб-сайт является школьным проектом, поэтому я даю .war моему учителю, и он проверяет его, поэтому я хочу убедиться, что нет никакой проблемы с доступом к db в любом случае, потому что я не одинок в этом. – user2380462

+0

Это нормально, вы не будете закрывать его, пока ваш веб-контейнер не завершится. Вы можете добавить прослушиватель контекста сервлета и выключение вызова при вызове destroy. – Luanne

+0

Отлично, спасибо большое! – user2380462

Смежные вопросы