2

タイトルで始めたように、Java アプリケーションでユーザー データをクエリしているときに、次のメッセージが表示されます。

同時に複数の ResultSet を開こうとすると、これが発生することがわかっています。

これが私の現在のコードです:

アプリは getProject("...") を呼び出します。他の 2 つのメソッドはヘルプ用です。より多くのコードがあるため、2 つのクラスを使用しています。これは、発生する例外の一例にすぎません。

理解を深めるために変数名などを翻訳したことに注意してください。何も見逃していないことを願っています。

/* Class which reads project data */

public Project getProject(String name) {
    ResultSet result = null;
    try {
        // executing query for project data
        // SELECT * FROM Project WHERE name=name
        result = statement.executeQuery(generateSelect(tProject.tableName,
                "*", tProject.name, name));
        // if cursor can't move to first place,
        // that means that project was not found
        if (!result.first())
            return null;
        return user.usersInProject(new Project(result.getInt(1), result
                .getString(2)));
    } catch (SQLException e) {
        e.printStackTrace();
        return null;
    } catch (BadAttributeValueExpException e) {
        e.printStackTrace();
        return null;
    } finally {
        // closing the ResultSet
        try {
            if (result != null)
                result.close();
        } catch (SQLException e) {
        }
    }
}

/* End of class */

/* Class which reads user data */

public Project usersInProject(Project p) {
    ResultSet result = null;
    try {
        // executing query for users in project
        // SELECT ID_User FROM Project_User WHERE ID_Project=p.getID()
        result = statement.executeQuery(generateSelect(
                tProject_User.tableName, tProject_User.id_user,
                tProject_User.id_project, String.valueOf(p.getID())));

        ArrayList<User> alUsers = new ArrayList<User>();
        // looping through all results and adding them to array
        while (result.next()) { // here java gets ResultSet closed exception
            int id = result.getInt(1);
            if (id > 0)
                alUsers.add(getUser(id));
        }
        // if no user data was read, project from parameter is returned
        // without any new user data
        if (alUsers.size() == 0)
            return p;
        // array of users is added to the object,
        // then whole object is returned
        p.addUsers(alUsers.toArray(new User[alUsers.size()]));
        return p;
    } catch (SQLException e) {
        e.printStackTrace();
        return p;
    } finally {
        // closing the ResultSet
        try {
            if (result != null)
                result.close();
        } catch (SQLException e) {
        }
    }
}

public User getUser(int id) {
    ResultSet result = null;
    try {
        // executing query for user:
        // SELECT * FROM User WHERE ID=id
        result = statement.executeQuery(generateSelect(tUser.tableName,
                "*", tUser.id, String.valueOf(id)));
        if (!result.first())
            return null;
        // new user is constructed (ID, username, email, password)
        User usr = new user(result.getInt(1), result.getString(2),
                result.getString(3), result.getString(4));
        return usr;
    } catch (SQLException e) {
        e.printStackTrace();
        return null;
    } catch (BadAttributeValueExpException e) {
        e.printStackTrace();
        return null;
    } finally {
        // closing the ResultSet
        try {
            if (result != null)
                result.close();
        } catch (SQLException e) {
        }
    }
}

/* End of class */

両方のクラスのステートメントがコンストラクターに追加され、各クラスの構築時に connection.getStatement() が呼び出されます。

tProject と tProject_User は私の列挙型です。名前の処理を簡単にするために使用しています。generateSelect は私の方法であり、期待どおりに動作するはずです。これを使用しているのは、ほとんどのコードを書いた後で準備済みステートメントについて知ったので、そのままにしておきました。

最新の Java MySQL コネクタ (5.1.21) を使用しています。

他に何を試すべきかわかりません。アドバイスをいただければ幸いです。

4

2 に答える 2

5

@arothの答えからの引用:

ResultSetが自動的に閉じられる状況はたくさんあります。公式ドキュメントを引用するには:http: //docs.oracle.com/javase/6/docs/api/java/sql/ResultSet.html

A ResultSet object is automatically closed when the Statement object that generated 
it is closed, re-executed, or used to retrieve the next result from a sequence of 
multiple results.

ここでのコードでは、メソッドで結果セットを作成したのと同じオブジェクトを使用ResultSetしてメソッドでnewを作成しているため、メソッド内の結果セットオブジェクトが閉じられます。getUserStatementusersInProjectusersInProject

解決策: 別のステートメントオブジェクトを作成し、それを使用し getUserて結果セットを作成します。

于 2012-09-10T06:23:06.230 に答える
5

コードを見ずに、何が問題なのかを明確に言うことは実際には不可能です。ResultSetただし、が自動的に閉じられる状況が多数あることに注意してください。公式ドキュメントを引用するには:

ResultSet オブジェクトは、それを生成した Statement オブジェクトが閉じられるか、再実行されるか、複数の結果のシーケンスから次の結果を取得するために使用されると、自動的に閉じられます。

おそらく、あなたはそのようなことが起こっているのです。ResultSetまたは、実際に完了する前に、どこかを明示的に閉じています。

また、Hibernate のような ORM フレームワークの使用を検討しましたか? 一般に、そのようなものは、低レベルの JDBC API よりもはるかに快適に作業できます。

于 2012-09-09T00:24:14.667 に答える