在 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。
我有这个非常简单的 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。