为什么我使用queryFromDb()从db类查询数据库我得到" ResultSet未打开"当它试图第二次做rs.next()时,如果我尝试使用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);
}
}
}
答案 0 :(得分:3)
每ResultSet
只能打开一个Statement
;在queryFromDb
中,您在statement.executeQuery
中打开一个,并且(隐式地)在statement.execute(str)
中的循环中打开另一个。来自documentation:
默认情况下,每个Statement对象只能同时打开一个ResultSet对象。因此,如果读取一个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
和Statement
s)。如果您使用的是Java 7或更高版本,最流畅的方法是使用try-with-resources statement。
答案 1 :(得分:0)
有可能因为您正在重用statement
循环记录集中的对象while
而重置。