この章では、JDBC(Java Database Connectivity)APIの概要およびデータベースに接続してデータにアクセスする方法について説明します。
JDBC APIによって、Javaプログラムでは、ベンダーに依存しない方法でリレーショナル・データにアクセスできるため、セッションの作成、SQL文の実行、およびリレーショナル・データベースからの結果の取得を行うことができます。JDBC仕様には、X/Open SQL call level interface仕様に基づいたJava用のSQL call level interfaceが含まれています。
JDBC APIは、JDBCドライバ、接続、文および結果セットの4つの主要コンポーネントで構成されています。データベース・ベンダーは、JDBC仕様に準拠したドライバのみを提供します。(詳細は、「データベース・ドライバ」を参照してください)。接続、文および結果セットのコンポーネントは、JDBC APIパッケージ(java.sql
パッケージ)に含まれています。
JDBC APIでは、これらのコンポーネントを操作するための次のインタフェース・クラスが提供されています。
JDBC 2.0 APIには、新しい標準拡張機能パッケージjavax.sql
のみでなく、java.sql
パッケージの多くの新機能が含まれています。java.sql
パッケージの機能には、SQL3データ型、スクロール可能な結果セット、プログラムによる更新およびバッチ更新のサポートなどがあります。
JDBCの新しい標準拡張機能APIは、Enterprise JavaBeans(EJB)テクノロジの不可欠な要素です。このAPIによって、接続プーリングを使用してファイルやスプレッドシートなどのほぼすべての表形式データソースに接続する分散トランザクションを記述できます。
JDBCアプリケーションを記述する場合、必要なドライバ固有の情報は、データベースURLのみです。JDBCアプリケーションは、実行時にURL情報を取得するように構築できます。アプリケーションは、データベースURL、ユーザー名およびパスワードを使用して、最初にDriverManager
からjava.sql.Connection
をリクエストします。
ドライバのクラス名を使用してデータベース・ドライバをロードします。
接続用のJDBC URLを使用して接続を取得します。
文を作成および実行します。
結果セットを使用して結果を検索します。
接続をクローズします。
JDBCでは、指定したJDBCドライバへの標準APIコールが定義されます。JDBCドライバは、実際のデータ・インタフェース・コマンドを実行するソフトウェアです。このドライバは、低レベルのJDBC APIとみなされます。このドライバのインタフェースには、データベースのクライアント・コール、またはデータベース・サーバーによって提供されるデータベースのネットワーク・プロトコル・コマンドが使用されます。
JDBC APIコールを変換するJDBCドライバには、インタフェースのタイプに応じて、次の4つのタイプがあります。
タイプ2、ネイティブAPIドライバ: JDBC APIコールをデータベースのネイティブAPIコールに変換します。このドライバはネイティブAPIを使用するため、ベンダーに依存します。このドライバは、変換を実行するJava言語の部分および一連のネイティブAPIライブラリの2つの部分で構成されます。
タイプ3、ネットワーク・プロトコル: JDBC APIコールをDBMSに依存しないネットワーク・プロトコル・コールに変換します。データベース・サーバーで、これらのネットワーク・プロトコル・コールが特定のDBMS操作に変換されます。
タイプ4、ネイティブ・プロトコル: JDBC APIコールをDBMS固有のネットワーク・プロトコル・コールに変換します。これらのコールは、データベース・サーバーでDBMS操作に変換されます。
DriverManager
クラスJavaプログラムでは、様々なドライバを使用して、複数の異なるデータベースに対する複数の接続を作成できます。ドライバ操作を管理するために、JDBCには、java.sql.DriverManager
というドライバ・マネージャ・クラスが備えられています。このクラスによって、ドライバのロードおよび新しいデータベース接続の作成が行われます。
DriverManager
によって、使用するすべてのJDBCドライバが登録されます。登録されていないドライバに対してJavaプログラムからJDBC操作が発行されると、No Suitable Driver
例外が発生します。
ドライバを登録する場合は、次のいくつかの方法があります。
次のコードを使用してドライバを明示的に登録する方法
DriverManager.registerDriver(driver-instance)
driver-instance
は、JDBCドライバ・クラスのインスタンスです。
次のコードを使用してドライバ・クラスをロードする方法
Class.forName(driver-class)
driver-classは、JDBCドライバ・クラスです。これによって、Java仮想マシンにドライバがロードされます。各ドライバは、ロード後にDriverManager.registerDriver
メソッドを使用して暗黙的に登録されます。
たとえば、COM.ibm.db2.jdbc.app
パッケージのDB2 JDBCタイプ2ドライバを登録する場合は、次のいずれかのコードを使用できます。
DriverManager.registerDriver(new COM.ibm.db2.jdbc.app.DB2Driver());
または
Class.forName("COM.ibm.db2.jdbc.app.DB2Driver");
Oracleデータベースの場合は、次のいずれかのコードを使用できます。
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver ());
または
Class.forName("oracle.jdbc.driver.OracleDriver")
J2EEサーバーでは、JDBCドライバ構成に基づいてドライバが暗黙的にロードされるため、ドライバのロードにクライアント固有のコードは必要ありません。JNDI(Java Naming and Directory Interface)ツリーでデータソースのオブジェクトを参照できます。
DataSource
クラスJDBC 2.0仕様では、java.sql.Datasource
クラスが導入され、JDBCプログラムが完全に移植可能になりました。このバージョンでは、ベンダー固有の接続URLおよびマシンとポートへの依存性が解消されています。また、このバージョンでは、java.sql.DriverManager
、Driver
、およびDriverPropertyInfo
の各クラスの使用は推奨されていません。以前のJDBC DriverManager
機能は、データソース機能に完全に置き換えられています。ドライバ・マネージャ・クラスをクライアント・アプリケーションのランタイムに明示的にロードするのではなく、集中化されたJNDIサービス・ルックアップによってjava.sql.Datasource
オブジェクトが取得されます。Datasource
オブジェクトを使用してデータベースに接続することもできます。
データソースは、JDBC 2.0 API仕様に従って、JDBCサブコンテキストまたはその子コンテキストのいずれかの下に登録されます。JDBCコンテキスト自体は、ルート・コンテキストの下に登録されます。Datasource
オブジェクトは、データソースへのコネクション・ファクトリです。JDBC 2.0 DataSource
APIは、JBossおよびOC4Jの両方でサポートされています。
OC4Jでは、フラット・ファイルを使用して、すべてのデプロイ済アプリケーションのデータソースが構成されます。データソースは、次のディスクリプタ・ファイルに指定されています。
UNIXの場合: <ORACLE_HOME>/j2ee/home/config/data-sources.xml
NTの場合: <ORACLE_HOME>\j2ee\home\config\data-sources.xml
次に、Oracleデータベースのデータソース構成の例を示します。data-sources.xml
の各データソース(xa-location
、ejb-location
およびpooled-location
)は、一意である必要があります。
<data-source
class="com.evermind.sql.DriverManagerDataSource"
name="Oracle"
url="jdbc:oracle:thin@node2058.oracle.com:1521:orcl"
xa-location="jdbc/xa/OracleXADS"
ejb-location="jdbc/OracleDS"
pooled-location="jdbc/OraclePoolDS"
connection-driver="oracle.jdbc.driver.OracleDriver"
username="scott"
password="tiger"
schema="database-schemas/oracle.xml"
inactivity-timeout="30"
max-connections="20"
/>
表6-1に、data-sources.xml
内のすべての構成パラメータを示します。(前述の例に示されていないパラメータもあります)。
データソース・オブジェクトを取得する場合は、JNDI初期コンテキストのバインドおよびサブコンテキストjdbc/sampleDB
の参照を行います。これらを行うには、初期コンテキストjavax.naming.InitialContext
に対するハンドルを取得する必要があります。IntialContext
は、JNDIネームスペースのルート・コンテキストです。InitialContext
には、次の2つのコンストラクタがあります。
パラメータを取らないデフォルトのコンストラクタ
1つのパラメータ(java.util.Properties
またはjava.util.HashTable
)を取るコンストラクタ
OC4Jでは、パラメータを取るコンストラクタが使用されるようにコードを変更する必要があります。次に、コードの例を示します。
//JBoss Code try { java.util.Properties parms = new java.util.Properties(); parms.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.ejs.ns.jndi.CNInitialContextFactory"); javax.naming.Context ctx = new javax.naming.InitialContext(parms); javax.sql.DataSource ds = (javax.sql.DataSource)ctx.lookup("jdbc/SampleDB"); java.sql.Connection conn = ds.getConnection(); // process the results ... }
ほとんどのWebベースのリソース(サーブレット、アプリケーション・サーバーなど)は、データベース内の情報にアクセスします。リソースは、データベースへのアクセスを試行するたびに、データベースへの接続を確立し、接続の作成および維持にシステム・リソースを使用する必要があります。また、接続が不要になった場合、その接続を解放するためにもシステム・リソースを使用する必要があります。リソースのオーバーヘッドは、Webベースのアプリケーションで特に大きくなります。これは、Webユーザーが頻繁かつ大量に接続および切断を行うためです。多くの場合、ビジネス・ロジックの実行で使用されるリソースより、接続および切断で使用されるリソースの量のほうが多くなります。
接続プーリングを使用すると、接続のオーバーヘッドを多数のユーザー・リクエストに分散することによって、接続リソースの使用を抑制できます。接続プールは、一連の接続オブジェクトをキャッシュしたもので、複数のクライアントがデータベースのリソースにアクセスする必要がある場合に、それらのクライアントによって共有されます。プール内に接続を作成するためのリソースは、指定した数の接続に対して1回のみ使用されます。各クライアント・クライアントによって専用の接続の作成およびクローズにリソースが使用されるのではなく、接続はオープン状態のまま維持され、多数のクライアント・リクエストによって繰り返し使用されます。接続プーリングでは、次の方法でパフォーマンス全体が向上されます。
中間層サーバーの負荷の軽減
セッション全体の作成操作および終了操作によるリソース使用量の最小化
ソケットとファイル記述子の制限およびユーザー・ライセンス数の制限に起因するボトルネックの解消
JDBC 2.0仕様では、次の目的でJDBCデータベース接続のプールを定義できます。
リソースに対する接続の可用性を最大にするため
プール内のアイドル接続を最小にするため
孤立した接続をプールに戻し、他のサーブレットまたはアプリケーション・サーバーでの再利用を可能にするため
これらの目的を実現するには、次の手順を実行します。
接続プールの最小サイズ・プロパティを、同時にアクティブとなるユーザー・リクエストの予想最小数と同じ値に設定します。
接続プーリングのプロパティによって、ユーザー・リクエスト数の減少に合わせて、未使用の接続がプールから段階的に削除されるようになります。同様に、ユーザー・リクエスト数の増加に合わせて、新しい接続が作成されます。接続の再利用が最大になり、接続作成のオーバーヘッドが最小になるように、接続のバランスが維持されます。また、接続プーリングを使用して、同時データベース接続の数を制御することもできます。