【问题标题】:Neo4j return transaction errorNeo4j 返回交易错误
【发布时间】:2015-10-06 11:06:17
【问题描述】:

我在亚马逊上安装了 neo4j。

我创建了使用 neo4j-jdbc 远程执行密码语句的客户端。

如果我在 本地 运行 neo4j-jdbc 客户端以远程处理亚马逊上的 neo4j 实例,一切都会按预期工作。

但是,当我将我的 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;
    }

}

谢谢

【问题讨论】:

  • 请分享代码示例 - 您如何使用 neo4j-jdbc。这将有助于发现问题。
  • 完成。请检查代码

标签: neo4j amazon


【解决方案1】:

您应该验证您的代码。

我看到你正在创建声明:

final PreparedStatement ps = conn.prepareStatement(getUsersStatement);

但你永远不会关闭它们。看起来TransasctionalQueryExecutor 是有状态的,如果您不关闭语句,则先前的事务元数据会泄漏到新事务中。

尝试在您的语句中使用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。这是应该牢记在心的事情。因为当您创建新语句时,它会在服务器上创建新事务并检索它的 ID。而且,当您执行查询时,它会调用具有指定事务 ID 的 API 方法。
数据库中也有事务超时。如果事务在n 秒内未使用,事务将被关闭。

【讨论】:

  • 我看不出你的代码示例的差异。它看起来一样吧?
  • try (final PreparedStatement ps = conn.prepareStatement(getUsersStatement)) { 我在那里使用try-with-resource 语法和准备好的语句。这样,当到达try 块的末尾时,语句将被关闭。
  • 在将所有内容都放在 try-with-resources 上后,我仍然遇到同样的错误,Mybe 我还有其他东西要关闭吗?我对其他并发查询使用相同的连接
  • 您不应该同时使用连接。为每个线程创建新连接。可能您应该创建连接池。我更新了关于事务端点的注释。
  • 你的意思是我应该这样做 conn = DriverManager.getConnection(connectionString, new Properties());每笔交易?因为现在我只初始化一次 conn 并在所有语句中使用它
猜你喜欢
  • 2021-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-14
  • 1970-01-01
  • 2017-07-10
  • 1970-01-01
相关资源
最近更新 更多