0

我有一个在节点之间建立关系的 servlet,它在循环中这样做,它可能会在循环中创建 1-999 或更多关系。它通过将数组列表中的数据加载到 Neo4j 中来实现。当我第一次运行它时,它运行良好。第二次,如果我再次跑 5 秒,它会给出一个 java.lang.NullPointerException . 大约一分钟后,它再次运行良好。这是servlet代码

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 中进行更改时,它总是可以正常工作,例如按 Enter 输入一个空的换行符并保存,servlet 重新加载 - 然后以其他方式启动 Neo4j,它给出了异常。

4

2 回答 2

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 中。现在它工作正常......

于 2013-05-12T14:12:17.380 回答
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 中执行所有这些操作。为您的业务逻辑创建一个服务层,并为持久性创建一个数据访问层。我倾向于将服务和存储库实现都隐藏在接口后面,但是如果您永远不会更改您的实现,那实际上没有必要。

您已经创建了一个非常简单的应用程序,但它看起来已经很混乱了。在小型应用程序中保持代码干净,它将成为大型应用程序的习惯。

于 2013-05-14T15:13:32.530 回答