我做一个查询:
jdbcTemplate.query(sqlQueryForGetNodes, new Object[]{treeId, versionId}, rs -> {
NodeType nodeType = NodeType.get(rs.getInt("NodeTypeId"));
int nodeId = rs.getInt("NodeId");
SmbpTreeSwitchCase switchCase = new SmbpTreeSwitchCase();
switchCase.setSwitchConditionType(getSwitchTypeByNodeId(nodeId));
smbpTreeNodes.add(switchCase);
});
private SwitchConditionType getSwitchTypeByNodeId(int nodeId) {
String sqlQueryForGetSwitchTypeByNodeId = "SELECT SwitchConditionTypeId FROM RE.SwitchCondition sc WHERE sc.NodeId = ?";
return jdbcTemplate.query(sqlQueryForGetSwitchTypeByNodeId, resultSet -> {
return SwitchConditionType.get(resultSet.getInt("SwitchConditionTypeId"));
}, nodeId);
}
并且在此查询中,我需要在方法 getSwitchTypeByNodeId
中子查询另一个表以用数据填充对象。
但是我得到一个错误:
org.springframework.dao.TransientDataAccessResourceException: PreparedStatementCallback; SQL [SELECT SwitchConditionTypeId FROM RE.SwitchCondition sc WHERE sc.NodeId = ?]; Before start of result set; nested exception is java.sql.SQLException: Before start of result set
我做错了什么?告诉我如何在 jdbcTemplate
中正确创建子查询?
最佳答案
我认为您对 JdbcTemplate.query
的两次调用中的两个 lambda 具有不同的类型,因此 Spring 对其进行了不同的处理。
第一个调用似乎有效,似乎使用了 the overload of the JdbcTemplate.query
method它接受一个 String
、一个 Object[]
和一个 RowCallbackHandler
并返回 void
。在这种情况下,您的 lambda 是一个 RowCallbackHandler
,它会为结果集中的每一行调用一次。 Spring 会将结果集从一行推进到下一行;对每一行做些什么完全取决于你。
但是,第二个调用似乎使用了 the overload of JdbcTemplate.query
它接受一个 String
、一个 ResultSetExtractor
和一个可变参数数组,并返回 ResultSetExtractor
返回的任何内容。当使用 ResultSetExtractor
时,Spring 只会调用一次并期望您完成所有结果集的处理。特别是,您需要检查结果集是否包含任何数据。
尝试将您的第二个 lambda 修改为如下所示:
return jdbcTemplate.query(sqlQueryForGetSwitchTypeByNodeId, resultSet -> {
if (resultSet.next()) {
return SwitchConditionType.get(resultSet.getInt("SwitchConditionTypeId"));
} else {
// SQL query returned no rows. TODO handle this somehow...
}
});
关于java - 使用嵌套在另一个 jdbcTemplate 中的 jdbcTemplate(在结果集开始之前),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48369819/