Neo4j Java 驱动程序 - 无法访问此结果的记录

问题描述

我正在使用 neo4j java 驱动程序并尝试执行 Cyphers。我遇到了一个异常。我在网上搜索了很长时间。但是没有用。请帮助或尝试提供一些如何实现这一目标的想法。

1.这是我添加的驱动程序:

        <dependency>
            <groupId>org.neo4j.driver</groupId>
            <artifactId>neo4j-java-driver-spring-boot-starter</artifactId>
            <version>4.1.1.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.neo4j/neo4j-ogm-core -->
        <dependency>
            <groupId>org.neo4j</groupId>
            <artifactId>neo4j-ogm-core</artifactId>
            <version>3.2.20</version>
        </dependency>

2.功能

     public Result readCyphers(String cypher) {

        Result result = null;

        Driver driver = null;
        Session session = null;

        try {
            //driver
            driver = GraphDatabase.driver(uri,AuthTokens.basic(username,password));
            //session
            session = driver.session();

            //run
            result = session.run(cypher);

        } catch (Exception e) {
            throw e;
        } finally {
            session.close();
            driver.close();
        }

        return result;
    }

3.调用函数

  @Test
    void readCypherstest() {

        String cypher = "MATCH(N:WechatDepartment) \n" +
                "WHERE N.departmentId = 117 \n" +
                "RETURN ID(N) as id,N.departmentId as departmentId,N.name as name,N.order as order,N.enable as enable";
        Result result = readCyphers(cypher);

        //There is an exception here
        System.out.println("result.list().size():" + result.list().size());
    }

4.异常:

org.neo4j.driver.exceptions.ResultConsumedException: Cannot access records on this result any more as the result has already been consumed or the query runner where the result is created has already been closed.

提前致谢

解决方法

(如果只打算使用驱动,则不需要Neo4j OGM)

会话关闭后,您将无法访问驱动程序的 Result 实例。 您应该在会话打开时迭代记录并返回您想要的结果,例如:

    public <T> List<T> readCyphers(String cypher,Function<Record,T> mapper) {
        try (Driver driver = GraphDatabase.driver(uri,AuthTokens.basic(username,password));
             Session session = driver.session()) {

            Result result = session.run(cypher);
            return result.list(mapper);
        }
    }

但是请注意,您不应在每次要运行查询时都创建一个 Driver 实例,因此应在此之前创建驱动程序,例如:

class CypherExecutor implements AutoCloseable {

    private final Driver driver;

    public CypherExecutor(String uri,String username,String password) {
        this.driver = GraphDatabase.driver(uri,password))
    }

    public <T> List<T> readCyphers(String cypher,T> mapper) {
        try (Session session = driver.session()) {
            Result result = session.run(cypher);
            return result.list(mapper);
        }
    }

    @Override
    public void close() throws Exception {
        driver.close();
    }
}

CypherExecutor 最好仅在应用程序停止时关闭(通过 try-with-resources 块)。

此外,transaction functions 更健壮(面对集群机器故障、领导者重新选举等),应该被使用,因此 readCyphers 应该是(假设只读查询):

    public <T> List<T> readCyphers(String cypher,T> mapper) {
        try (Session session = driver.session()) {
            return session.readTransaction(tx -> tx.run(cypher).list(mapper));
        }
    }

最后一点,这种抽象并没有带来太多好处,因此您可以直接在代码库中使用 Driver API,而不是使用这种间接方式。

完整代码,带导入:

import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.Record;
import org.neo4j.driver.Session;

import java.util.List;
import java.util.function.Function;

class CypherExecutor implements AutoCloseable {

    private final Driver driver;

    public CypherExecutor(String username,String password,String uri) {
        this.driver = GraphDatabase.driver(uri,T> mapper) {
        try (Session session = driver.session()) {
            return session.readTransaction(tx -> tx.run(cypher).list(mapper));
        }
    }

    @Override
    public void close() throws Exception {
        driver.close();
    }
}