结果集未打开,在一种情况下有效,另一种情况下无效
Posted
技术标签:
【中文标题】结果集未打开,在一种情况下有效,另一种情况下无效【英文标题】:resultSet not open, works in one case another case not 【发布时间】:2015-07-31 22:14:50 【问题描述】:为什么如果我使用 queryFromDb() 从 db 类查询数据库,当它第二次尝试执行 rs.next() 时会得到“ResultSet not open”,而如果我尝试使用 queryFromMain 一切正常?
public class Db
private String protocol = "jdbc:derby:";
private ResultSet resultSet = null;
private Connection connection = null;
private Statement statement;
public Db()
try
Properties props = new Properties();
props.put("user", "user");
props.put("password", "password");
String dbName = "database";
connection = DriverManager.getConnection(protocol + dbName , props);
catch(SQLException sqle)
printSQLException(sqle);
public ResultSet returnValue(String query)
try
statement = connection.createStatement();
resultSet = statement.executeQuery(query);
catch(SQLException sqle)
printSQLException(sqle);
return resultSet;
public void queryFromDb()
try
statement = connection.createStatement();
ResultSet rs = statement.executeQuery("SELECT * FROM clsbck ORDER BY id");
while(rs.next())
System.out.println(rs.getString(2));
String str = "INSERT INTO cls rck VALUES 2";
[...]
statement.execute(str);
catch (SQLException e)
printSQLException(e);
public class Main
private static Db db;
public static void main(String[] args)
db = new Db();
public static void queryFromMain()
ResultSet rs = db.returnValue("SELECT * FROM clsbck ORDER BY id");
try
while(rs.next())
String str = "INSERT INTO cls rck VALUES 2";
[...]
db.addValue(str);
catch (SQLException e)
printSQLException(e);
【问题讨论】:
【参考方案1】:每个Statement
应该只打开一个ResultSet
;在queryFromDb
中,您将在statement.executeQuery
中打开一个,并且(隐式)在statement.execute(str)
的循环中打开另一个。来自documentation:
默认情况下,每个 Statement 对象只能同时打开一个 ResultSet 对象。因此,如果一个 ResultSet 对象的读取与另一个 ResultSet 对象的读取交错,则每个对象都必须由不同的 Statement 对象生成。 Statement 接口中的所有执行方法都会隐式关闭一个语句的当前 ResultSet 对象,如果存在打开的对象。
您可以通过执行以下操作来修复该方法:
public void queryFromDb()
Statement queryStatement = null;
PreparedStatement insertStatement = null;
try
queryStatement = connection.createStatement();
insertStatement = connection.prepareStatement(
"INSERT INTO cls rck VALUES 2");
ResultSet rs = queryStatement
.executeQuery("SELECT * FROM clsbck ORDER BY id");
while (rs.next())
System.out.println(rs.getString(2));
// [...]
insertStatement.executeUpdate();
rs.close();
catch (SQLException e)
printSQLException(e);
finally
if (queryStatement != null)
queryStatement.close();
if (insertStatement != null)
insertStatement.close();
您不应在代码中使用全局(方法范围的)Statement
对象;相反,在本地声明它们。对于循环内发生的 SQL INSERT
,您应该使用 PreparedStatement
,它在循环外部准备并在内部执行(如果您想用绑定占位符 (?
) 替换查询中的值更改要在每次迭代中插入的值)。
最后,记得在使用后关闭你的资源(ResultSet
s 和Statement
s)。如果您使用的是 Java 7 或更高版本,最流畅的方法是使用 try-with-resources statement。
【讨论】:
【参考方案2】:这可能是因为您在 while
循环记录集中重用了对象 statement
被重置。
【讨论】:
同意,您可能想要创建一个用于插入的新语句。以上是关于结果集未打开,在一种情况下有效,另一种情况下无效的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI 在一种情况下而不是另一种情况下查看层次结构警告
为啥在一种情况下会收到带有字符串文字的不推荐使用的转换警告,而在另一种情况下却没有?
如何在一种情况下推送视图控制器,但在另一种情况下以模态方式呈现它?