このセクションでは、データベースへのアクセス時のコーディング作業を効率化する方法について説明します。
コネクションプールを使用すると、データベース接続はリクエストごとに作成され廃棄されるのではなく、いったん借用されて、再利用可能なオブジェクトのプールに戻されます。JRun には、独自のコネクションプールメカニズムが組み込まれており、デフォルトで、データソースを JMC に追加するたびに有効になります。
JRun のデータソースを使用していない場合は、独自にカスタマイズしたコネクションプールのメカニズムを実装する必要があります。
JMC 内では影響を受けないオプションの設定を使用して、JRun のデータソースを操作できます。これらのすべての設定はオプションです。次の表で、これらの設定について説明します。
コネクションプールの設定を変更するには、jrun-resources.xml ファイル内の適切なデータソースのプロパティを編集します。たとえば、次の設定により、デフォルトの skimmer-frequency
値の 420 をオーバーライドし、100 に置き換えます。
<datasource>
... <skimmer-frequency>100</skimmer-frequency> ... </datasource>
データベースにクエリを実行すると、JRun はクエリをコンパイルし、データベース接続を介してデータベースに送信します。頻繁に使用するクエリには PreparedStatement を使用できます。PreparedStatement はプリコンパイルされ、サーバに保管されています。PreparedStatement には ? を使用して変数を任意の数だけ指定できます。これらの変数は実行時にクエリに挿入されます。
次のコード例は、3 つの変数を使用して PreparedStatement を作成する方法を示しています。
String sqlstmt = "INSERT INTO SESSIONS VALUES(?,?,?)";
try { InitialContext ctx = new InitialContext(); DataSource ds = (DataSource) ctx.lookup(dsName); conn = ds.getConnection(); ps = conn.prepareStatement(sqlstmt); ps.setString(1,sid); ps.setLong(2,time); ps.setInt(3,1); rs = ps.executeQuery(); } catch (SQLException sqle) { ... } ...
PreparedStatement オブジェクトの使用方法の詳細については、Java 2 API のドキュメントを参照してください。
Connection、Statement、および ResultSet オブジェクトを使用したら、これらのオブジェクトを閉じて、要求されたリソースを解放し、使用されていない接続をプールに戻す必要があります。次の例のように finally ブロックを追加します。
... } finally { try { ps.close(); rs.close(); } catch (Exception e) { e.printStackTrace(); } }
ResultSet および Statement オブジェクトには、次のようなデータベースオペレーションの微調整に役立つ多数のメソッドが用意されています。
Statement.setMaxRows
setFetchSize
setFetchDirection
setFetchSize
および setMaxRows
メソッドは、開発者の間でもよく混同されます。これらのメソッドは ResultSet または Statement オブジェクト上で呼び出すことができます。これらのメソッドの違いを理解するには、まずデータベースがクエリの結果を返すときの動作を理解する必要があります。次のセクションでは、データベースにクエリを実行する方法、および setFetchSize
メソッドと setMaxRows
メソッドの違いについて説明します。
データベースに対してクエリを実行すると、データベースはクエリを処理し、結果データをそのキャッシュに保管します。ResultSet オブジェクトは、データベースのキャッシュ内にフェッチサイズと同数のレコードへのリファレンスを保持します。つまり、ResultSet オブジェクトはデータベースへのオープン接続にすぎず、返された行のデータは含んでいません。
JRun サーバとデータベース間の接続を確立する JDBC ドライバが、データベースキャッシュから行の一部を取得し、それを処理するクライアントサイド (JRun サーバがデータベースのクライアントに相当) に返します。ドライバは、getFetchSize
と同数の行を取得します。
クライアントがドライバによって提供された行の処理を終了したら、JDBC ドライバは次の getFetchSize
行をあらかじめフェッチし、同様の処理を続けます。
データベースがクエリから返す行の数を制限するには、次の例のように setMaxRows
を使用します。
Statement stmt = conn.createStatement();
stmt.setMaxRows(10); ResultSet rs = stmt.executeQuery("SELECT * from SESSIONS");
データベースが返す行の数を制限するには、SQL ステートメントで LIMIT
コマンドを使用することもできます。次の例は、100 行に制限された ResultSet を示しています。
rs = ps.executeQuery("SELECT * FROM tablename LIMIT 100");
JDBC ドライバがデータベースキャッシュから取得して JRun に返す行の数を設定するには、setFetchSize
を使用します。データに多くの処理を行う必要がある場合は、小さい値に設定します。
メモ: setFetchSize
メソッドは、データをフェッチする方法についてのデータベースへのヒントにすぎません。すべてのデータベースドライバでこのメソッドをサポートしているとはかぎりません。
適切な setFetchSize
を決めるには、フロントエンドでのユーザー操作と、ユーザーがクエリの結果を操作する方法について検討します。たとえば、ユーザーがユーザーインターフェイスで一回に 10 行を操作できる場合は、フェッチサイズを 10 に設定します。
setFetchDirection
の処理時に最後の行を最初に返すには、setFetchDirection メソッドを使用します。それによって、大量のデータを操作する際は特に、処理速度が速くなります。
たとえば、日付別に保管されているトランザクションの ResultSet がある場合に、直前のトランザクションを最初のフェッチで取得できます。
メモ: setFetchDirection
メソッドは、データをフェッチする方法についてのデータベースへのヒントにすぎません。すべてのデータベースドライバでこのメソッドをサポートしているとはかぎりません。
ResultSet rs = null;
Connection conn = null; String sql = "SELECT * FROM employee"; Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); rs.setFetchDirection(ResultSet.FETCH_REVERSE); rs = stmt.executeQuery(sql);
すべての JDBC ドライバが一様に動作するとはかぎりません。さまざまな負荷をかけてさまざまなデータベースで各種ドライバの動作をテストして、Web アプリケーションに最適な組み合わせを調べます。
JDBC と ODBC bridge は、絶対に必要な場合にのみ使用してください。
JDBC ドライバの詳細については、Sun の Web サイト
http://industry.java.sun.com/products/jdbc/drivers をご覧ください。
データベースにアクセスする最も速い方法は、データベース自体にまったくアクセスしないことです。可能な場合は、データベースへの呼び出しによってスタティックデータをダイナミックに取得するのではなく、キャッシュするようにしてください。サーブレットおよび JSP の init
メソッドおよび jspInit
メソッド内で、初期化時にデータベースへのアクセスを 1 つのクエリに制限します。さらに、結果をキャッシュし、残りのリクエストがそのキャッシュに入ったデータにアクセスできるようにします。詳細については、次のセクションを参照してください。