JDBC ドライバの使用法
この章では、アプリケーションと InterSystems IRIS 間で JDBC 接続を確立する方法と、JDBC ドライバの拡張メソッドとプロパティを使用する方法について説明します。
-
JDBC 接続の確立 — DriverManager または DataSource を使用して接続を確立および制御する方法について説明します。
-
バルク挿入のための列方向のバインディング — バッチ挿入をより速く、使いやすくする拡張メソッドについて説明します。
-
接続プーリング — 接続プーリングと監視のオプションについて説明します。
-
最適化とテストのオプション — ログ、共有メモリ、および文プーリングについての情報を提供します。
"Connecting Your Application to InterSystems IRISOpens in a new tab" にも、サンプル・コードを含め、JDBC を使用して Java アプリケーションから InterSystems IRIS サーバに接続する手順が示されています。
JDBC 接続の確立
このセクションでは、DriverManager または DataSource を使用して接続を確立および制御する方法について説明します。
-
JDBC 接続 URL の定義 — JDBC 接続を定義するパラメータの指定方法を説明します。
-
接続のための IRISDataSource の使用法 — IRISDataSource を使用してドライバをロードし、java.sql.Connection オブジェクトを作成する方法について説明します。
-
接続のための DriverManager の使用法 — DriverManager クラスを使用して接続を作成する方法について説明します。
JDBC 接続 URL の定義
java.sql.Connection URL は、アクセス先のホスト・アドレス、ポート番号、およびネームスペースに関する情報を持つ接続を提供します。InterSystems JDBC ドライバでは、オプションの URL パラメータもいくつか使用できます。
必須の URL パラメータ
最小限必要な URL 構文は以下のとおりです。
jdbc:IRIS://<host>:<port>/<namespace>
ここで、必須パラメータは以下のように定義されます。
-
host — IP アドレス、または完全修飾ドメイン名 (FQDN)。例えば、127.0.0.1 と localhost は両方ともローカル・マシンを表します。
-
port — InterSystems IRIS スーパーサーバが待ち受け状態にある TCP ポート番号。既定値は 1972 です。詳細は、"構成パラメータ・ファイル・リファレンス" の "DefaultPort" を参照してください)。
-
namespace — アクセス先の InterSystems IRIS ネームスペース。
例えば、以下の URL では、host が 127.0.0.1、port が 1972、namespace が User に指定されます。
jdbc:IRIS://127.0.0.1:1972/User
オプションの URL パラメータ
host、port、および namespace に加えて、オプションの URL パラメータをいくつか指定することもできます。完全な構文は、以下のとおりです。
jdbc:IRIS://<host>:<port>/<namespace>/<logfile>:<eventclass>:<nodelay>:<ssl>
ここで、オプションのパラメータは以下のように定義されます。
-
logfile — JDBC ログ・ファイルを指定します (“JDBC のログ” を参照してください)。
-
eventclass — この IRISDataSource オブジェクトにトランザクション・イベント・クラスを設定します。
-
nodelay — IRISDataSource オブジェクト経由で接続している場合に TCP_NODELAY オプションを設定します。このフラグを切り替えると、アプリケーションのパフォーマンスに影響する場合があります。有効な値は、true および false です。設定されていない場合、既定値として true が設定されます。
-
ssl — IRISDriver と IRISDataSource の両方で TLS を有効にします ("セキュリティ管理ガイド" の “TLS の構成” を参照)。有効な値は、true および false です。設定されていない場合、既定値として false が設定されます。
これらのオプションの URL パラメータは、他のパラメータを指定しなくても、それぞれ個別に定義できます。例えば、以下の URL は、必須のパラメータと nodelay オプションのみを設定します。
jdbc:IRIS://127.0.0.1:1972/User/::false
他の接続プロパティを指定するには、Properties オブジェクト内の DriverManager に渡します (“接続のための DriverManager の使用法” を参照してください)。
接続のための IRISDataSource の使用法
com.intersystems.jdbc.IRISDataSource を使用してドライバをロードした後、java.sql.Connection オブジェクトを作成します。これは、データベースに接続する推奨のメソッドで、InterSystems IRIS で完全にサポートされています。
以下の例では、ドライバをロードしてから IRISDataSource を使用して接続を作成し、ユーザ名およびパスワードを指定します。
try{
IRISDataSource ds = new IRISDataSource();
ds .setServerName("127.0.0.1");
ds .setPortNumber(51776);
ds .setDatabaseName("USER");
ds .setUser("_SYSTEM");
ds .setPassword("SYS");
IRISConnection connection = (IRISConnection) ds.getConnection();
}
catch (SQLException e){
System.out.println(e.getMessage());
}
catch (ClassNotFoundException e){
System.out.println(e.getMessage());
}
この例では、意図的に localhost ではなくリテラル・アドレス 127.0.0.1 を使用します。ホスト名が Ipv4 と Ipv6 で同じように解決されるシステムでは、localhost を使用する場合、Java は Ipv6 経由で接続しようとします。
IRISDataSource クラスは、接続プロパティ・アクセサの拡張セットを提供します (この例では、setUser()、setPassword() など)。アクセサの完全なリストについては、クイック・リファレンスの “IRISDataSource クラス”、およびすべての接続プロパティの詳細は、このリファレンスの後半にある “接続パラメータのオプション” を参照してください。
接続のための DriverManager の使用法
IRISDataSource を使用して接続することをお勧めしますが、DriverManager クラスを使用して接続を作成することもできます。以下のコードは、その方法の一例です。
Class.forName ("com.intersystems.jdbc.IRISDriver").newInstance();
String url="jdbc:IRIS://127.0.0.1:1972/User";
String username = "_SYSTEM";
String password = "SYS";
dbconnection = DriverManager.getConnection(url,username,password);
以下のコードに示すように、DriverManager の接続プロパティを Properties オブジェクトで指定することもできます。
String url="jdbc:IRIS://127.0.0.1:1972/User";
java.sql.Driver drv = java.sql.DriverManager.getDriver(url);
java.util.Properties props = new Properties();
props.put("user",username);
props.put("password",password);
java.sql.Connection dbconnection = drv.connect(url, props);
利用できるプロパティの詳細なリストは、このリファレンスの後半にある “接続パラメータのオプション” を参照してください。
バルク挿入のための列方向のバインディング
JDBC では、事前入力されたデータのバルク挿入は通常、addBatch() をループで呼び出すことによって実行されます。これは、データが既に配列内にあり、サーバに送信する準備ができている場合には最適ではありません。InterSystems IRIS は、ループをバイパスして、配列全体を 1 つの setObject() 呼び出しで渡すことができる拡張機能を提供します。
例えば、一般的なコードは、以下のように各項目に対して setObject() を呼び出します。
// Typical AddBatch() loop
for (int i=0;i<10000;i++){
statement.setObject(1,objOne);
statement.setObject(2,objTwo);
statement.setObject(3,objThree);
statement.addBatch();
}
statement.executeBatch();
すべての項目を 1 つの Object 配列に読み込んで、配列全体を 1 つの呼び出しで追加すれば、コードはより高速かつ単純になります。
// Adding an ArrayList named objArray with a single call
IRISPreparedStatement.setObject(objArray);
statement.addBatch();
statement.executeBatch();
列方向のバインディングでは、arraylist としてバインドされた最初のパラメータが、その arraylist のサイズ (複数存在する場合) を使用してバッチ内の行数を表すことが前提となります。arraylist としてバインドされたその他のパラメータは、同じサイズであるか、または 1 つの値のみ (ユーザ定義の既定値など) を指定している必要があります。そうでない場合、addbatch() の呼び出し時に、"列方向のパラメータ値が一致しません : #rows 行が予期されていましたが、# parameter! で見つかったのは #count だけです。" という例外がスローされます。
例えば、3 つのパラメータと 10 個の行をバインドする場合、パラメータ 1 で 10 個の値を arraylist にバインドできます。パラメータ 2 と 3 には同様に arraylist で 10 個の値を指定するか、1 つの値のみを指定する (すべての行に 1 つの既定値を指定する場合) 必要があります。すべてを入力するか、1 つのみ入力する必要があります。それ以外では例外がスローされます。
以下に、行方向のバインディングと列方向のバインディングで同じ操作を行う例を示します。
public static void bindRowWise() throws Exception {
int rowCount = cName.size();
String insert = "INSERT INTO CUSTOMER VALUES(?,?,?,?)";
try {
PreparedStatement ps = conn.prepareStatement(insert);
for (int i=0;i<rowCount;i++){
ps.setObject(1,cName.get(i));
ps.setObject(2,cAddress.get(i));
ps.setObject(3,cPhone.get(i));
ps.setObject(4,cAcctBal.get(i));
ps.addBatch();
}
ps.executeBatch();
}
catch (Exception e) {
System.out.println("\nException in RowBinding()\n"+e);
}
} // end bindRowWise()
public static void bindColumnWise() throws Exception {
String insert = "INSERT INTO CUSTOMER VALUES(?,?,?,?)";
try {
PreparedStatement ps = conn.prepareStatement(insert);
ps.setObject(1, new ArrayList<>(cName) );
ps.setObject(2, new ArrayList<>(cAddress) );
ps.setObject(3, new ArrayList<>(cPhone) );
ps.setObject(4, new ArrayList<>(cAcctBal) );
ps.addBatch();
ps.executeBatch();
catch (Exception e) {
System.out.println("\nException in bindColumnWise()\n"+e);
}
} // end bindColumnWise()
接続プーリング
IRISConnectionPoolDataSource メソッドの使用法
IRISConnectionPoolDataSource クラスは、ConnectionPoolDataSource を実装し、プールされた接続のテストと監視に役立つ一連の独自の拡張機能によってそれを拡張したものです。以下の拡張機能を使用できます。
-
getConnectionWaitTimeout() 接続プール・マネージャが、接続が利用可能になるまで待機する秒数を返します。
-
getMaxPoolSize() 許可される接続の最大数を返します。
-
getPoolCount() 接続プール内の現在のエントリ数を返します。
-
restartConnectionPool() 物理接続をすべて切断し、接続プールを空にします。
-
setMaxPoolSize() プール内で許可される接続の最大数を指定する int 値を取ります。既定値は 40 です。
-
setConnectionWaitTimeout() 接続の待機タイムアウト間隔を秒数で指定する int 値を取ります。タイムアウト時間が過ぎても利用可能な接続がない場合は、例外がスローされます。既定では 0 に設定されています。これは、接続が即時に利用可能になることを示します。プールがいっぱいである場合は例外がスローされます。
IRISConnectionPoolDataSource クラスは、IRISDataSource に実装された独自の拡張機能も継承します (クイック・リファレンスの “接続パラメータのオプション” を参照)。
InterSystems IRIS でこのクラスを使用する手順は次のとおりです。
-
必要なパッケージをインポートします。
import com.intersystems.jdbc.*; import java.sql.*;
-
IRISConnectionPoolDataSource オブジェクトをインスタンス化します。reStart() メソッドを使用して物理接続をすべて切断し、プールを空にします。setURL() (IRISDataSource から継承) を使用して、プールの接続にデータベース URL ("JDBC 接続 URL の定義" を参照) を設定します。
IRISConnectionPoolDataSource pds = new IRISConnectionPoolDataSource(); pds.restartConnectionPool(); pds.setURL("jdbc:IRIS://127.0.0.1:1972/User"); pds.setUser("_system"); pds.setPassword("SYS");
-
最初は、getPoolCount() は 0 を返します。
System.out.println(pds.getPoolCount()); //outputs 0.
-
getConnection() を使用して、プールからデータベース接続を取得します。
Connection dbConnection = pds.getConnection();
Caution:InterSystems JDBC ドライバ接続は、常に IRISDataSource の getConnection() メソッドを呼び出して取得する必要があります。このメソッドは、自動の透過的な接続プーリングを提供するために拡張されています。ConnectionPoolDataSource.getPooledConnection() メソッドは、JDBC 標準で要求されているため実装されていますが、直接呼び出してはなりません。
-
接続を切断します。getPoolCount() が 1 を返すようになります。
dbConnection.close(); System.out.println(pds.getPoolCount()); //outputs 1
最適化とテストのオプション
このセクションには、開発およびテストの際に役立つ可能性のある専用の情報が含まれています。
-
JDBC のログ — JDBC アプリケーションをテストする際にログを有効にする方法を説明します。
-
共有メモリ接続 — サーバとクライアントが同じマシン上にある場合に接続がどのように機能するかについて説明します。
-
文のプーリング — 文を初めて使用するときに、最適化された文をキャッシュに格納する方法について説明します。
JDBC のログ
アプリケーションで問題が発生した場合、ログを有効にしてアプリケーションを監視できます。アプリケーションを実行し、エラー条件をトリガしたことを確認した後、エラー・メッセージや、異常な活動のすべてのログ記録をチェックします。エラーの原因は通常、メッセージ内に表れています。
ログは、トラブルシューティングを実行する必要がある場合のみ有効にします。ログを有効にするとパフォーマンスが大幅に低下するため、通常の操作時は有効にしないでください。
InterSystems IRIS に接続するときに JDBC のログを有効にするには、JDBC 接続文字列の末尾にログ・ファイル名を追加します。接続時に、ドライバによってアプリケーションの作業ディレクトリに保存されるログ・ファイルが保存されます。
例えば、元の接続文字列が以下であるとします。
jdbc:IRIS://127.0.0.1:1972/USER
ログを有効にするには、この文字列を以下のように変更して再接続します。
jdbc:IRIS://127.0.0.1:1972/USER/myjdbc.log
このログには、InterSystems IRIS データベースから見た対話処理が記録されます。
指定されたログ・ファイルが存在する場合、既定では新しいログ・エントリがそのファイルに追加されます。既存のファイルを削除して、新しいファイルを作成するには、接頭語としてログ・ファイル名の前にプラス (+) 文字を付けます。例えば、次の文字列では、myjdbc.log を削除し (既存の場合)、同じ名前で新しいログ・ファイルを作成します。
jdbc:IRIS://127.0.0.1:1972/USER/+myjdbc.log
文のプーリング
JDBC 4.0 は、追加のインフラストラクチャである「文のプーリング」を追加しています。この機能により、最適化された文は、最初に使用されたときにキャッシュに格納されます。文のプールは、接続プールによって維持され、プールされた文を接続間で共有できます。実装の詳細は、ユーザに対して完全に透過的です。必要な機能を提供するかどうかはドライバで決まります。
InterSystems JDBC は、この概念が JDBC 仕様の一部になるかなり前から文のプーリングを実装していました。一方、InterSystems IRIS ドライバは、この仕様で推奨されているテクニックに類似したテクニックを使用しており、実際にプーリングを実装すると高度に最適化されます。ほとんどの実装と異なり、InterSystems JDBC は、3 つの別々の文プーリング・キャッシュを備えています。1 つは JDBC 仕様で定義されている文プーリングにほぼ相当しますが、その他の 2 つは InterSystems IRIS 特有の最適化です。必要に応じて、InterSystems JDBC 文プーリングは、ユーザに対して完全に透過的になります。
InterSystems JDBC の実装は、Statement メソッドである setPoolable() および isPoolable() を、当該の文をプールする必要があるかどうかのヒントとしてサポートします。InterSystems IRIS は、独自のヒューリスティックを使用して、3 つの文プールすべての適切なサイズを決定します。したがって、IRISConnectionPoolDataSource の maxStatements プロパティを設定することによる文プール・サイズの制約をサポートしません。オプションの javax.sql.StatementEventListener インタフェースは同じ理由でサポートされません (また、重要ではありません)。