2015-10-06 6 views
1

У меня установлен neo4j на Amazon.Ошибка транзакции Neo4j

Я создал клиент, который использует neo4j-jdbc, который удаленно выполняет инструкции cypher.

Если я запустил клиент neo4j-jdbc локально для удаленной работы с экземпляром neo4j на Amazon, все работает должным образом.

Однако когда я загрузить мой Neo4j-клиент приложение JDBC к другому экземпляру на amazon и выполнить заявления я получаю это исключение:

2015-10-06 10:59:59,609 ERROR [com.mycompany.wm.common.repo.Neo4jRepo] - <Error returning userId=33> 
java.sql.SQLException: Error executing statement 
    at org.neo4j.jdbc.internal.rest.TransactionalQueryExecutor.executeQuery(TransactionalQueryExecutor.java:224) 
    at org.neo4j.jdbc.internal.Neo4jConnection.executeQuery(Neo4jConnection.java:370) 
    at org.neo4j.jdbc.internal.Neo4jPreparedStatement.executeQuery(Neo4jPreparedStatement.java:48) 
    at com.mycompany.wm.common.repo.Neo4jRepo.getfollowUsersByProximitySensors(Neo4jRepo.java:159) 
    at com.mycompany.wm.core.dao.LocationServiceDaoImpl.getfollowUsersByProximitySensors(LocationServiceDaoImpl.java:79) 
    at com.mycompany.wm.core.service.LocationServiceImpl.getfollowUsers(LocationServiceImpl.java:38) 
    at com.mycompany.world_map_service.web.http.VertxHttpServerVerticle.getUsersLocation(VertxHttpServerVerticle.java:69) 
    at com.mycompany.world_map_service.web.http.VertxHttpServerVerticle$$Lambda$30/984195839.handle(Unknown Source) 
    at io.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:218) 
    at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:67) 
    at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:96) 
    at io.vertx.ext.web.impl.RouterImpl.accept(RouterImpl.java:61) 
    at com.mycompany.world_map_service.web.http.VertxHttpServerVerticle$$Lambda$32/1901044330.handle(Unknown Source) 
    at io.vertx.core.http.impl.ServerConnection.handleRequest(ServerConnection.java:276) 
    at io.vertx.core.http.impl.ServerConnection.processMessage(ServerConnection.java:391) 
    at io.vertx.core.http.impl.ServerConnection.handleMessage(ServerConnection.java:137) 
    at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.lambda$createConnAndHandle$24(HttpServerImpl.java:539) 
    at io.vertx.core.http.impl.HttpServerImpl$ServerHandler$$Lambda$55/521685526.run(Unknown Source) 
    at io.vertx.core.impl.ContextImpl.lambda$wrapTask$15(ContextImpl.java:312) 
    at io.vertx.core.impl.ContextImpl$$Lambda$11/1686783496.run(Unknown Source) 
    at io.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:217) 
    at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.createConnAndHandle(HttpServerImpl.java:537) 
    at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.doMessageReceived(HttpServerImpl.java:474) 
    at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.doMessageReceived(HttpServerImpl.java:425) 
    at io.vertx.core.http.impl.VertxHttpHandler.channelRead(VertxHttpHandler.java:85) 
    at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:124) 
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308) 
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294) 
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:244) 
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308) 
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294) 
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:846) 
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131) 
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511) 
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468) 
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382) 
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354) 
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:110) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: Error executing statement (404) - {"results":[],"errors":[{"code":"Neo.ClientError.Transaction.UnknownId","message":"Unrecognized transaction id. Transaction may have timed out and been rolled back."}]} 
    at org.restlet.resource.ClientResource.doError(ClientResource.java:612) 
    at org.neo4j.jdbc.internal.rest.Resources$TransactionClientResource.doError(Resources.java:283) 
    at org.restlet.resource.ClientResource.handleInbound(ClientResource.java:1202) 
    at org.restlet.resource.ClientResource.handle(ClientResource.java:1069) 
    at org.restlet.resource.ClientResource.handle(ClientResource.java:1044) 
    at org.restlet.resource.ClientResource.post(ClientResource.java:1453) 
    at org.neo4j.jdbc.internal.rest.TransactionalQueryExecutor.post(TransactionalQueryExecutor.java:98) 
    at org.neo4j.jdbc.internal.rest.TransactionalQueryExecutor.begin(TransactionalQueryExecutor.java:76) 
    at org.neo4j.jdbc.internal.rest.TransactionalQueryExecutor.executeQuery(TransactionalQueryExecutor.java:214) 
    ... 38 more 

Neo4j-код: JDBC

public class Neo4jRepo { 
.. 

@PostConstruct 
    public void init() { 
     logger.debug("Neo4jRepo, Init"); 
     try { 
      String connectionString = "jdbc:neo4j://" + NEO4J_HOST + ":" + NEO4J_PORT; 
      Class.forName("org.neo4j.jdbc.Driver"); 
      conn = DriverManager.getConnection(connectionString, new Properties()); 
     } catch (SQLException e) { 
      throw new RuntimeException(e); 
     } catch (ClassNotFoundException e) { 
      throw new RuntimeException(e); 
     } 

    } 

.. .

Эксплуатация этого метода:

public Set<UserDistanceDTO> getfollowUsers(String userIdInput, boolean includeHopes, follow_RELATIONSHIP_TYPE relationship_type) { 
     String followExpression = "follow"; 
     if (includeHopes) { 
      followExpression = "follow*1..3"; 
     } 

     String relationshipTye; 
     if (relationship_type.equals(follow_RELATIONSHIP_TYPE.OUTGOING)) { 
      relationshipTye = "->"; 

     } else if (relationship_type.equals(follow_RELATIONSHIP_TYPE.INCOMING)) { 
      relationshipTye = "<-"; 

     } else { 
      relationshipTye = "-"; 
     } 
     Set<UserDistanceDTO> userDistanceDTOs = null; 
     try { 
      userDistanceDTOs = new HashSet<>(); 

      String getUsersStatement = 
        "MATCH (user:" + LABEL_NAME + " {userId:{1}})-[r:" + followExpression + "]" + relationshipTye + "f " + 
          "WHERE f <> user " + 
          "RETURN DISTINCT (f.userId) as userId"; 
      final PreparedStatement ps = conn.prepareStatement(getUsersStatement); 
      ps.setString(1, userIdInput); 
      ResultSet rs = ps.executeQuery(); 
      while (rs.next()) { 
       userDistanceDTOs.add(new UserDistanceDTO((String) rs.getObject("userId"), 0)); 
      } 

     } catch (SQLException e) { 
      e.printStackTrace(); 
      logger.error("Error returning userId=" + userIdInput, e); 
     } 
     return userDistanceDTOs; 
    } 

} 

С благодарностью

+0

Просьба поделиться образцом кода - как вы используете neo4j-jdbc. Это поможет выявить проблему. – FylmTM

+0

сделано. пожалуйста, проверьте код – rayman

ответ

1

Вы должны подтвердить свой код.

Как я вижу, вы создаете заявление:

final PreparedStatement ps = conn.prepareStatement(getUsersStatement); 

Но вы никогда не закрывать их. Похоже, что TransasctionalQueryExecutor имеет статус stateful, и если вы не закрываете оператор, тогда метаданные предыдущей транзакции просачиваются в новую транзакцию.

Попробуйте использовать синтаксис try-with-resource с вашими утверждениями. Пример в вашем случае:

try (final PreparedStatement ps = conn.prepareStatement(getUsersStatement)) { 
    ps.setString(1, userIdInput); 
    ResultSet rs = ps.executeQuery(); 
    while (rs.next()) { 
     userDistanceDTOs.add(new UserDistanceDTO((String) rs.getObject("userId"), 0)); 
    } 
} 

Примечание: Neo4j-JDBC использует transaction Cypher HTTP endpoint. Это то, что нужно просто запомнить. Потому что, когда вы создаете новый оператор, он создает новую транзакцию на сервере, которая возвращает идентификатор. И когда вы выполняете запрос, он вызывает метод API с указанным идентификатором транзакции.
Также есть тайм-аут в базе данных для транзакции. Транзакция будет закрыта, если она не была использована для n секунд.

+0

Я не могу видеть, что ваш пример кода не учитывает .. он выглядит так же, а? – rayman

+0

'try (final PreparedStatement ps = conn.prepareStatement (getUsersStatement)) {' Я использую синтаксис 'try-with-resource' там с подготовленным оператором. Таким образом, оператор будет закрыт, когда будет достигнут конец блока 'try'. – FylmTM

+0

Ах, это здорово. о вашем наконечнике - можно было бы разработать? – rayman

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