13

Java で JDBC を使用する場合、一般的に受け入れられているデータベースのクエリ方法は、接続を取得し、その接続からステートメントを作成し、そのステートメントからクエリを実行することです。

// load driver
Connection con = DriverManager.getConnection(..);
Statement stmt = con.createStatement();
ResultSet result = stmt.executeQuery("SELECT..");
// ...

ただし、同じデータベースへの 2 番目のクエリを処理する方法がわかりません。

  1. 同じオブジェクトに対して別のクエリを安全に実行できるかStatement、または別のクエリを実行するためにオブジェクトから別のステートメントを作成する必要があるConnectionか?

  2. 同じStatementオブジェクトを複数のクエリに使用できる場合、Statementクラスの目的は何ですか (メソッドが存在する方が意味があるためConnection.executeQuery())?

4

6 に答える 6

8

Statementはい、オブジェクトを再利用できますが、既に開いている結果セットを閉じるResultSetことによって返されたオブジェクト。executeQuery

説明については、 javadocを参照してください。

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

したがって、次のことが起こります。

// load driver
Connection con = DriverManager.getConnection(..);
Statement stmt = con.createStatement();
ResultSet result = stmt.executeQuery("select ..");
// do something with result ... or not
ResultSet result2 = stmt.executeQuery("select ...");
// result is now closed, you cannot read from it anymore
// do something with result2
stmt.close(); // will close the resultset bound to it

たとえば、jTDS プロジェクトで Statement のオープン ソース実装を見つけることができます。Statement.executeQuery() メソッドで、すでに開いているすべての結果セットinitialize()閉じる呼び出しを確認できます。

protected void initialize() throws SQLException {
    updateCount = -1;
    resultQueue.clear();
    genKeyResultSet = null;
    tds.clearResponseQueue();
    // FIXME Should old exceptions found now be thrown instead of lost?
    messages.exceptions = null;
    messages.clearWarnings();
    closeAllResultSets();
}
于 2012-10-18T20:54:10.600 に答える
4

プログラムによって、複数のクエリに対して同じ接続と同じステートメントを再利用し、最後にステートメントと接続を閉じることができます。

ただし、これは良い方法ではありません。アプリケーションのパフォーマンスは、データベースへのアクセス方法に大きく左右されます。理想的には、各接続が開いている時間をできるだけ短くする必要があります。次に、接続をプールする必要があります。それによって、各クエリを のブロックで囲みます{open connection, create a prepared statement, run query, close statement, close connection}。これは、ほとんどの SQL テンプレートが実装されている方法でもあります。同時実行性が許せば、スレッド プールを使用して、このような複数のクエリを同時に起動できます。

于 2012-10-18T21:03:16.250 に答える
2

I have one thing to add should you use Connection and Statement in a threaded environment. My experience shows that stmt.executeQuery(..) is save to use in a parallel environment but with the consequence that each query is serialized and thus processed sequencially, not yielding any speed-ups. So it es better to use a new Connection (not Statement) for every thread.

For a standard sequential environment my experience has shown that reusing Statements is no problem at all and ResultSets need not be closed manually.

于 2012-10-18T21:28:56.937 に答える
1

通常、1 つのクエリに対して 1 つのステートメントです。その必要はないかもしれませんが、実際のアプリケーションを作成するときは、同じ手順を何度も繰り返したくありません。これは DRY の原則に反するものであり、アプリケーションが大きくなるにつれてより複雑になります。

そのような低レベルの (反復的な) 処理を処理するオブジェクトを作成し、クエリを提供して db にアクセスするためのさまざまな方法を提供することをお勧めします。

于 2012-10-18T21:19:34.347 に答える
1

新しいステートメントを作成することについて心配する必要はありません。ただし、データベース接続を開くとリソースが大量に消費される可能性があり、接続を開いたり閉じたりするとパフォーマンスに影響します。

何らかの自己管理方法で接続を残すことは、通常、かなり悪いことです。

接続プーリングの使用を検討する必要があります。通常は close コマンドを発行しますが、その接続をプールに戻すだけです。新しい接続を要求すると、以前に返された接続が再利用されます。

1 つの接続に対して異なるステートメントが必要な場合があります。ステートメントは実装であり、インターフェースです。必要なものに応じて、 CallableStatmentを使用したい場合があります。一部のロジックは、必要に応じて再利用できます。

于 2012-10-18T21:24:51.350 に答える
1

オブジェクト指向プログラミングにクラスの概念があるのはそのためです。クラスは、そのインスタンスが状態と動作を持つことを可能にする構成メンバーを定義します。Hereステートメントは、SQLステートメントに関連するすべてを扱います。バッチクエリなどのように実行できる機能は他にもたくさんあります。

于 2012-10-18T20:55:08.180 に答える