web-dev-qa-db-ja.com

Javaのデータベース接続を閉じる

私は少し混乱している、私は下から http://en.wikipedia.org/wiki/Java_Database_Connectivity を読んでいた

Connection conn = DriverManager.getConnection(
     "jdbc:somejdbcvendor:other data needed by some jdbc vendor",
     "myLogin",
     "myPassword" );

Statement stmt = conn.createStatement();
try {
    stmt.executeUpdate( "INSERT INTO MyTable( name ) VALUES ( 'my name' ) " );
} finally {
    //It's important to close the statement when you are done with it
    stmt.close();
}

Conn Connectionを閉じる必要はありませんか? conn.close()が発生しない場合、実際に何が起こっていますか?

現在、どちらのフォームも閉じないプライベートWebアプリを持っていますが、重要なのは本当にstmt、conn、またはその両方ですか?

サイトは断続的にダウンし続けますが、サーバーはそれがデータベース接続の問題だと言い続けます。

106
onaclov2000

Connectionの使用が終了したら、close()メソッドを呼び出して明示的に閉じて、接続が保持している可能性のある他のデータベースリソース(カーソル、ハンドルなど)を解放する必要があります。

実際、Javaの安全なパターンは、ResultSetStatement、およびConnectionを(この順序で)finallyブロックで閉じることです。

Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;

try {
    // Do stuff
    ...

} catch (SQLException ex) {
    // Exception handling stuff
    ...
} finally {
    if (rs != null) {
        try {
            rs.close();
        } catch (SQLException e) { /* ignored */}
    }
    if (ps != null) {
        try {
            ps.close();
        } catch (SQLException e) { /* ignored */}
    }
    if (conn != null) {
        try {
            conn.close();
        } catch (SQLException e) { /* ignored */}
    }
}

finallyブロックは、(nullチェックを回避するために)少し改善できます。

} finally {
    try { rs.close(); } catch (Exception e) { /* ignored */ }
    try { ps.close(); } catch (Exception e) { /* ignored */ }
    try { conn.close(); } catch (Exception e) { /* ignored */ }
}

ただし、これは非常に冗長なため、通常はヘルパークラスを使用してnullセーフヘルパーメソッドのオブジェクトを閉じ、finallyブロックは次のようになります。

} finally {
    DbUtils.closeQuietly(rs);
    DbUtils.closeQuietly(ps);
    DbUtils.closeQuietly(conn);
}

そして、実際には、 Apache Commons DbUtils には DbUtils クラスがあり、これを正確に実行しているので、独自に記述する必要はありません。

178
Pascal Thivent

使用後は、データベース/リソースオブジェクトを閉じることをお勧めします。 finallyブロック内の接続、結果セット、およびステートメントオブジェクトを閉じる方が適切です。

Java7までは、これらすべてのリソースをfinallyブロックを使用して閉じる必要があります。 Java 7を使用している場合、リソースを閉じるために次のようにできます。

try(Connection con = getConnection(url, username, password, "org.postgresql.Driver");
    Statement stmt = con.createStatement();
    ResultSet rs = stmt.executeQuery(sql);
) {

//statements
}catch(....){}

現在、con、stmt、rsオブジェクトはtryブロックの一部になり、Javaは使用後にこれらのリソースを自動的に閉じます。

お役に立てば幸いです。

55
Yadu Krishnan

StatementConnectionを閉じるだけで十分です。 ResultSetオブジェクトを明示的に閉じる必要はありません。

Javaのドキュメントでは、Java.sql.ResultSetについて説明しています。

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


コメントをしてくれたBalusCに感謝します:「私はそれに依存しません。いくつかのJDBCドライバーはそれで失敗します。」

13
Grigori A.

はい。結果セット、ステートメント、および接続を閉じる必要があります。接続がプールからのものである場合、接続を閉じると実際に再利用のためにプールに送り返されます。

通常、finally{}ブロックでこれを行う必要があります。これにより、例外がスローされた場合でも、これを閉じることができます。

多くのフレームワークは、このリソースの割り当て/割り当て解除の問題を処理します。例えばSpringの JdbcTemplateApache DbUtils は、結果セット/ステートメント/接続をnullであるかどうかに関係なく閉じる(および閉じるときに例外をキャッチする)メソッドを備えています。

10
Brian Agnew

はい、接続を閉じる必要があります。それ以外の場合、データベースクライアントは通常、ソケット接続と他のリソースを開いたままにします。

7
Alex Miller

実際には、try-with-resourcesブロックを使用すると、Javaがtryブロックを終了するときにすべての接続を閉じるのが最適です。

AutoClosableを実装するオブジェクトでこれを行う必要があります。

try (Connection connection = getDatabaseConnection(); Statement statement = connection.createStatement()) {
    String sqlToExecute = "SELECT * FROM persons";
    try (ResultSet resultSet = statement.execute(sqlToExecute)) {
        if (resultSet.next()) {
            System.out.println(resultSet.getString("name");
        }
    }
} catch (SQLException e) {
    System.out.println("Failed to select persons.");
}

GetDatabaseConnectionの呼び出しが完了しました。 JDBC SQL接続またはプールからの接続を取得する呼び出しに置き換えます。

4
Joe