1. ホーム
  2. java

[解決済み] java.sql.SQLException を取得しました。ResultSet が終了した後の操作は許可されません。

2022-01-28 14:48:46

質問

以下のコードを実行すると、例外が発生します。同じ接続オブジェクトで新しいステートメントを準備しているからだと思います。プリペアド・ステートメントを作成し、かつrs2を使用できるようにするには、どのように書き直せばよいのでしょうか?同じDBに接続する場合でも、新しい接続オブジェクトを作成しなければならないのでしょうか?

    try 
    {
        //Get some stuff
        String name = "";
        String sql = "SELECT `name` FROM `user` WHERE `id` = " + userId + " LIMIT 1;";
        ResultSet rs = statement.executeQuery(sql);
        if(rs.next())
        {
            name = rs.getString("name");
        }

        String sql2 = "SELECT `id` FROM  `profiles` WHERE `id` =" + profId + ";";
        ResultSet rs2 = statement.executeQuery(sql2);
        String updateSql = "INSERT INTO `blah`............"; 
        PreparedStatement pst = (PreparedStatement)connection.prepareStatement(updateSql);    

        while(rs2.next()) 
        { 
            int id = rs2.getInt("id");
            int stuff = getStuff(id);

            pst.setInt(1, stuff);
            pst.addBatch();

        }

        pst.executeBatch();

    } 
    catch (Exception e) 
    {
        e.printStackTrace();
    }

private int getStuff(int id)
{

    try
    {   

            String sql = "SELECT ......;";
            ResultSet rs = statement.executeQuery(sql);

            if(rs.next())
            {
                return rs.getInt("something");

            }
            return -1;
    }//code continues

解決方法は?

でのデータ取得方法に問題があります。 getStuff() . にアクセスするたびに getStuff() を取得し、新しい ResultSet が、閉じない。

の期待に反しています。 Statement クラス(こちら - http://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html ):

デフォルトでは、1つのStatementオブジェクトに対して、1つのResultSetオブジェクトしか同時に開くことができません。したがって、ある ResultSet オブジェクトの読み取りと別の ResultSet オブジェクトの読み取りが混在する場合、それぞれは異なる Statement オブジェクトによって生成されたものである必要があります。Statementインターフェイスのすべての実行メソッドは、開いているResultSetオブジェクトが存在する場合、暗黙のうちにStatementの現在のResultSetオブジェクトを閉じます。

さらに事態を悪化させるのは rs を呼び出しコードから削除します。これはまた statement フィールドがありますが、閉じられてはいません。

結論:複数の ResultSet 同じ Statement オブジェクトが同時に開かれる。