resultSet没有打开,在一种情况下工作另一种情况不是

时间:2015-07-31 22:14:51

标签: java sql jdbc derby resultset

为什么我使用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);
        }   
    }
}

2 个答案:

答案 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,它在循环外部准备并在内部执行(使用绑定占位符替换查询中的值(? })如果你想改变每次迭代时要插入的值。)

最后,请务必在使用后关闭资源(ResultSetStatement s)。如果您使用的是Java 7或更高版本,最流畅的方法是使用try-with-resources statement

答案 1 :(得分:0)

有可能因为您正在重用statement循环记录集中的对象while而重置。