2013-05-12 70 views
0

我有一個使節點之間關係的servlet,它在一個循環中這樣做,它可以在循環中創建一個或多個關係 。它通過從數組列表中加載數據到 Neo4j來實現。我第一次運行它時效果很好。第二次,如果我再運行5秒鐘,它會給出java.lang.NullPointerException。大約一分鐘後,它再次運作良好。 這是servlet代碼Neo4j無法將事務標記爲僅回滾

public class InputDebtDataToNeo4j extends HttpServlet { 

static GraphDatabaseService graphDB = new GraphDatabaseFactory().newEmbeddedDatabase("C:\\Users\\Jovo\\Documents\\NetBeansProjects\\DebtSolutions\\build\\web\\NEO4J databases\\db1"); 
//Neo4jSinletonDbStart nn=new Neo4jSinletonDbStart(); 
//GraphDatabaseService graphDB =nn.getInstance(); 
    private ArrayList<InputData> l111; 

    protected void processRequest(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException { 
     response.setContentType("text/html;charset=UTF-8"); 
     PrintWriter out = response.getWriter(); 

     HttpSession session=request.getSession(true); 

     l111= (ArrayList<InputData>) session.getAttribute("hasdata"); 
     long mynodenumber; 
     mynodenumber = Long.parseLong(session.getAttribute("node_id").toString()); 
     Transaction tx = graphDB.beginTx(); 
     try { 
      Node firstNode; 
      Node secondNode;  
      for (InputData element : l111) 
      { 
       Relationship relationship = null; 
       firstNode=graphDB.getNodeById(mynodenumber); 
       secondNode=graphDB.getNodeById(element.getNodeidnumber()); 

       relationship = firstNode.createRelationshipTo(secondNode, RelTypes.OWES); 
       relationship.setProperty("amount", "'"+element.getDebtamount()+"'"); 

       out.println(relationship.getStartNode().toString()); 
       out.println(relationship.getProperty("amount")); 
       out.println(relationship.getEndNode().toString()); 
      } 

      tx.success(); 
      //response.sendRedirect("DebtSolutions.jsp"); 
     } 
     catch(Exception e) 
     { 
      tx.failure(); 
      out.println(e.toString()); 
     } 
     finally { 
      tx.finish(); 
      graphDB.shutdown();  
      out.close(); 
     } 
    } 

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code."> 
    /** 
    * Handles the HTTP 
    * <code>GET</code> method. 
    * 
    * @param request servlet request 
    * @param response servlet response 
    * @throws ServletException if a servlet-specific error occurs 
    * @throws IOException if an I/O error occurs 
    */ 
    @Override 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException { 
     processRequest(request, response); 
    } 

    /** 
    * Handles the HTTP 
    * <code>POST</code> method. 
    * 
    * @param request servlet request 
    * @param response servlet response 
    * @throws ServletException if a servlet-specific error occurs 
    * @throws IOException if an I/O error occurs 
    */ 
    @Override 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException { 
     processRequest(request, response); 
    } 

    /** 
    * Returns a short description of the servlet. 
    * 
    * @return a String containing servlet description 
    */ 
    @Override 
    public String getServletInfo() { 
     return "Short description"; 
    }// </editor-fold> 
} 

我得到的是

org.neo4j.graphdb.TransactionFailureException: Failed to mark transaction as rollback only 

我告示是當我做例如在NetBeans中改打中 一個空的換行輸入,它總是好的工作和保存,servlet重新加載 - 然後啓動Neo4j的其他方式,它給了例外。

+0

你註釋掉了你得到graphDB實例的行,是有意的嗎? – 2013-05-12 08:49:54

+0

是的,這是我認爲我可以使用靜態相同的效果 - 不要太複雜。會發生什麼情況是,當我運行代碼第一次它確實,第二次失敗,如果我等待2分鐘再次運行,它再次運作良好。如果我在代碼Netbeans中進行了一些更改,例如輸入空間進行保存,則Tomcat將重新加載它也運行的servlet。當它失敗我得到java.lang.NullPointerException和org.neo4j.graphdb.TransactionFailureException:無法將事務標記爲僅回滾 – 2013-05-12 11:53:07

+0

而我使用jdk7 for java – 2013-05-12 12:10:51

回答

1

它所涉及到的是,我需要做一個單獨的類像這樣

public class GraphDbStarter { 
    private static GraphDatabaseService graphdb=null; 

    protected GraphDbStarter() 
    {} 

// static GraphDatabaseService graphDB = new GraphDatabaseFactory().newEmbeddedDatabase("C:\\Users\\Jovo\\Documents\\NetBeansProjects\\DebtSolutions\\build\\web\\NEO4J databases\\db1"); 
    public static GraphDatabaseService getInstance() 
    { 
     if(graphdb == null) { 
     graphdb = new GraphDatabaseFactory().newEmbeddedDatabase("C:\\Users\\Jovo\\Documents\\NetBeansProjects\\DebtSolutions\\build\\web\\NEO4J databases\\db1"); 
     registerShutdownHook(graphdb); 
     } 

    return graphdb; 
    } 

    private static void registerShutdownHook(final GraphDatabaseService graphdb) 
    { 
    Runtime.getRuntime().addShutdownHook(new Thread() 
    {  

     @Override 
    public void run() 
    { 
    graphdb.shutdown(); 
    } 
    }); 
    } 
} 

創建和書亭下來數據庫,並在我的servlet使用

static GraphDatabaseService graphDB=GraphDbStarter.getInstance(); 

沒有

graphdb.shutdown(); 

在servlet中。現在它工作正常...

+0

如果你有東西要添加,請這樣做。 – 2013-05-12 14:12:53

+0

再次,當我做了一些更改和我的代碼失敗,我必須重新啓動Tomcat,使其工作正常。 – 2013-05-12 14:48:36

0

我不太喜歡弄亂單身模式。你的代碼現在非常簡單,但它可能會變得更加複雜。我傾向於用私人構造函數來解決它:

public class Database(){ 
    private static Database instance;  
    private GraphDatabaseService service; 

    private Database(){ 
     Register shutdown hook, create indices, read configuration such as Db Path, ... 
     service = whatever service you need. 
    } 

    public static Database getInstance(){ 
     if(instance == null){ 
      instance = new Database(); 
     } 
     return instance; 
    } 

    public GraphDatabaseService getService(){ 
     return service; 
    } 

另外,不要在你的Servlet/Controller中做所有這些。爲您的業務邏輯創建一個服務層,併爲持久性創建一個數據訪問層。我傾向於在接口後面隱藏服務和存儲庫實現,但如果你永遠不會改變你的實現,那實際上並不是必須的。

你已經創建了一個非常簡單的應用程序,但它已經看起來非常混亂。保持您的代碼在小型應用程序中的清潔,並且它將成爲大型應用程序的習慣。