在 Neo4j 中查询不存在的标签时,MyBatis 映射器从不 returns

MyBatis mapper never returns when querying for inexisting label in Neo4j

我有这个非常简单的 Spring Boot 2 应用程序和 MyBatis Spring Boot starter:

@Slf4j
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Autowired
    UserMapper userMapper;

    @Bean
    public CommandLineRunner commandLineRunner() {
        return (args -> {
            final List<User> users = userMapper.getUsers();
            log.info("users: {}", users);
        });
    }

    @Bean
    @ConfigurationProperties(prefix="app.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

}

当我在 Neo4j 数据库中有一个用户时,它工作得很好。但是,如果它们不存在,则对 getUsers 的调用永远不会 returns,没有超时,没有任何事情发生,就像应用程序永远卡住一样。 知道为什么会发生这种情况吗?

编辑: 显然它在 MyBatis 的 DefaultResultSetHandler class 中循环。

  private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
    ResultSet rs = stmt.getResultSet();
    while (rs == null) {
      // move forward to get the first resultset in case the driver
      // doesn't return the resultset as the first result (HSQLDB 2.1)
      if (stmt.getMoreResults()) {
        rs = stmt.getResultSet();
      } else {
        if (stmt.getUpdateCount() == -1) {
          // no more results. Must be no resultset
          break;
        }
      }
    }
    return rs != null ? new ResultSetWrapper(rs, configuration) : null;
  }

ResultSet 为空,因为没有用户。 但是 Neo4jInvocationHandler 中的 stmt.getMoreResults() returns 为真:

@Override public boolean getMoreResults() throws SQLException {
        this.checkClosed();
        return !(this.currentResultSet == null && this.currentUpdateCount == -1);
    }

currentUpdateCount 为 0,因为在 BoltNeo4jPreparedStatement 中:

@Override public boolean execute() throws SQLException {
        StatementResult result = executeInternal();

        boolean hasResultSet = hasResultSet(result);
        if (hasResultSet) {
            this.currentResultSet = BoltNeo4jResultSet.newInstance(this.hasDebug(), this, result, this.resultSetParams);
            this.currentUpdateCount = -1;
        } else {
            this.currentResultSet = null;
            try {
                SummaryCounters stats = result.consume().counters();
                this.currentUpdateCount = stats.nodesCreated() + stats.nodesDeleted() + stats.relationshipsCreated() + stats.relationshipsDeleted();
            } catch (Exception e) {
                throw new SQLException(e);
            }
        }
        return hasResultSet;
    }

我认为 getMoreResults 实现需要更新。
也许在 MyBatis PreparedStatementHandler 中他们应该检查 execute() 方法的返回值。

此问题现已在 neo4j-jdbc 3.3.1 中得到修复。参见 https://github.com/neo4j-contrib/neo4j-jdbc/issues/137