プール内のJDBC接続を閉じる


109

JDBCを使用するための標準コードセクションは...

Connection conn = getConnection(...);
Statement  stmt = conn.conn.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE,
                                                ResultSet.CONCUR_READ_ONLY);
ResultSet  rset = stmt.executeQuery (sqlQuery);

// do stuff with rset

rset.close(); stmt.close(); conn.close();

質問1:接続プールを使用する場合、最後に接続を閉じる必要がありますか?もしそうなら、プールの目的は失われていませんか?そうでない場合、Connectionの特定のインスタンスが解放され、再利用できるようになると、DataSourceはどのようにして知るのでしょうか。私はこれについて少し混乱しています、どんなポインタでも感謝します。

質問2:次の方法は標準に近いものですか?プールから接続を取得する試みのように見え、DataSourceを確立できない場合は、古い形式のDriverManagerを使用します。実行時にどの部分が実行されるのかさえわかりません。上記の質問を繰り返しますが、そのようなメソッドから出てくる接続を閉じる必要がありますか?

ありがとう、MS。

synchronized public Connection getConnection (boolean pooledConnection)
                                                        throws SQLException {
        if (pooledConnection) {
                if (ds == null) {
                        try {
                                Context envCtx = (Context)
                                        new InitialContext().lookup("java:comp/env");
                                ds = (DataSource) envCtx.lookup("jdbc/NamedInTomcat");
                                return ds.getConnection();
                        } catch (NamingException e) {
                                e.printStackTrace();
                }}
                return (ds == null) ? getConnection (false) : ds.getConnection();
        }
        return DriverManager.getConnection(
                "jdbc:mysql://"+ipaddy+":"+dbPort +"/" + dbName, uName, pWord);
}

編集:スタックトレースが表示されないため、プールされた接続を取得していると思います。

回答:


121

接続プールを使用する場合、最後に接続を閉じる必要がありますか?もしそうなら、プールの目的は失われていませんか?そうでない場合、Connectionの特定のインスタンスが解放され、再利用できるようになると、DataSourceはどのようにして知るのでしょうか。私はこれについて少し混乱しています、どんなポインタでも感謝します。

はい、確かにプールされた接続も閉じる必要があります。実際には、実際の接続のラッパーです。カバーの下で、プールへの実際の接続が解放されます。実際の接続を実際に閉じるか、または新しいgetConnection()呼び出しに再利用するかを決定するのは、プール次第です。したがって、接続プールを使用しているかどうかに関係なく、取得したブロックのブロック内のすべてのJDBCリソースを常に逆の順序で閉じる必要あります。Java 7では、これをステートメントを使用してさらに簡略化できます。finallytrytry-with-resources


次の方法は標準に近いものですか?プールから接続を取得する試みのように見え、DataSourceを確立できない場合は、古い形式のDriverManagerを使用します。実行時にどの部分が実行されるのかさえわかりません。上記の質問を繰り返しますが、そのようなメソッドから出てくる接続を閉じる必要がありますか?

例はかなり怖いです。DataSourceアプリケーション全体のDB構成クラスのコンストラクター/初期化で、アプリケーションの起動時に一度だけルックアップ/初期化する必要があります。次にgetConnection()、アプリケーションの残りのライフタイムを通じて、同じデータソースを呼び出します。同期やnullチェックの必要はありません。

以下も参照してください。


それは何をしているのですか(一度初期化してください)、そうではありませんか?dsはインスタンス変数であり、if(ds == null)...は初期化部分です。
Manidip Sengupta、2011

getメソッドのように毎回チェックを行うのgetConnection()は奇妙です。同期/ヌルチェックなしで、まったく同じクラスのc'torまたは初期化ブロックでそれを行うだけです。一度だけ呼び出されます。その他のヒントやキックオフの例については、この記事が役立つ場合があります。
BalusC

優れた記事、BalusC。私が扱っているクラスは、DTOを使用してデータレイヤーを実装しています。初期化はコンストラクタで行う必要があります。現在、このクラスには大量のメソッドがあり、それぞれローカル変数としてconn、stmt、rsetがあり、接続はtryブロック内にあり、最後に1行の呼び出しcsrClose(conn、stmt、rset)があり、すべて3閉じています(逆順)。この例で開発するDTOは、DBテーブル行のミラーイメージです。結合(および他の句)を含む複雑なSQLクエリがありますが、そのような結果のためのDAOの開発方法に関する記事はありますか?
Manidip Sengupta、2011

2
@yat:close()それらを取得/作成した場所とfinallyまったく同じtryブロックのブロックでそれらすべてを呼び出す必要があります。これは、プールされた接続であるかどうかに関係なく、完全に異なります。
BalusC

1
@iJava:そのプールは、彼が何をしているかまったく知らないアマチュアによって書かれています。それを無視して、実際のライブラリを探してください。例:ひかりCP。
BalusC 2015年

22

プールは通常、ラップされたConnectionオブジェクトを返します。ここで、close()メソッドはオーバーライドされ、通常はプールにConnectionを返します。close()の呼び出しは問題なく、おそらくまだ必要です。

close()メソッドはおそらく次のようになります。

public void close() throws SQLException {
  pool.returnConnection(this);
}

2番目の質問では、ロガーを追加して、一番下のブロックが実行されるかどうかを示すことができます。データベース接続の構成にはどちらか一方だけが必要だと思いますが。データベースアクセスにはプールのみを使用します。どちらの方法でも、接続を閉じることはリークを防ぐために非常に重要です。


私は同意します、私たちはロガーを持っています、そしてそれはここでも使用できます。オブジェクトをラップし、そのclose()メソッドをオーバーライドしながら、同じクラス名(接続)を維持する方法について少し勉強する必要があります
Manidip Sengupta

1
Calling close() is OK and probably still required.、プールが何らかの回復戦略を実装していない限り、closeを呼び出さないと接続がリークします
svarog

0

実際、接続管理の最善の方法は、どこにもコードを配置しないようにすることです。

接続を開いたり閉じたりする唯一の場所であるSQLExecutorクラスを作成します。

次に、アプリケーションの残りの部分全体が、プールから接続を取得して場所全体を管理(またはそれらを誤って管理)するのではなく、ステートメントをexecutorに送り込みます。

エグゼキュータのインスタンスはいくつでも持つことができますが、自分のために接続を開いたり閉じたりするコードを誰も作成してはなりません。

便利なことに、これにより、単一のコードセットからすべてのSQLをログに記録することもできます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.