我有一个在节点之间建立关系的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其他方式给出异常。
答案 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中完成所有操作。为业务逻辑创建服务层,为持久性创建数据访问层。我倾向于隐藏接口后面的服务和存储库实现,但是如果你永远不会改变你的实现,那么它实际上并不是必需的。
你已经创建了一个非常简单的应用程序,但它看起来已经非常混乱了。在小型应用程序中保持代码清洁,它将成为大型应用程序的习惯。