Neo4j无法将事务标记为仅回滚

时间:2013-05-12 00:50:58

标签: java servlets neo4j

我有一个在节点之间建立关系的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中进行更改时,它总能正常工作 输入一个空的换行符并保存,servlet重新加载 - 然后启动Neo4j其他方式给出异常。

2 个答案:

答案 0 :(得分: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中

。现在它工作正常......

答案 1 :(得分: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中完成所有操作。为业务逻辑创建服务层,为持久性创建数据访问层。我倾向于隐藏接口后面的服务和存储库实现,但是如果你永远不会改变你的实现,那么它实际上并不是必需的。

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