WebLogic jDriver for Oracle のコンフィグレーションと使い方 (非推奨)
![]() |
![]() |
![]() |
![]() |
注意 : WebLogic jDriver for Oracle は非推奨となりました。将来のリリースでは削除されます。BEA では、BEA WebLogic Type 4 JDBC Oracle ドライバの使用をお勧めします。詳細については、『WebLogic Type 4 JDBC ドライバ ガイド』を参照してください。
この章では、簡単なアプリケーションに関する基本作業について説明します。この章には、コード例やサポートされていないメソッドのリストも含まれています。
WebLogic Server でトランザクションを実行する場合は、ローカル トランザクションと分散トランザクションのどちらを使うかによって、一部の基本作業が異なります。トランザクションは以下のように分けられます。
分散トランザクションの詳細については、「分散トランザクションでの WebLogic jDriver for Oracle/XA の使い方」を参照してください。
アプリケーションにインポートしなければならないクラスは以下のとおりです。
import java.sql.*;
import java.util.Properties; // 接続パラメータ設定用に Properties
// オブジェクトを使用する場合にだけ必要
import weblogic.common.*;
import javax.sql.Datasource; // 接続の取得に DataSource API を
// 使用する場合にだけ必要
import javax.naming.*; // DataSource オブジェクトのルックアップに
// JNDI を使用する場合にだけ必要
WebLogic Server ドライバは、java.sql
インタフェースを実装します。 アプリケーションを作成するには、java.sql
クラスを使用します。JDBC ドライバ クラスをインポートする必要はありませんが、代わりに、アプリケーション内でドライバをロードします。これにより、適切なドライバを実行時に選択できるようになります。接続先となる DBMS をプログラムのコンパイル後に決めることもできます。
WebLogic Server 付属のドライバを使用して WebLogic Server クライアントを実行する場合は、CLASSPATH
に次のディレクトリを追加しなければなりません。
%WL_HOME%\server\lib\weblogic.jar
使用するドライバ クラス名と URL は、以下の要素によって決まります。
また、システムのパスに正しいドライバ バージョンを指定しなければなりません。詳細については、「WebLogic jDriver for Oracle の使用環境の設定」を参照してください。
以下の節で説明するように、2 層接続または多層接続を使用して、アプリケーションから Oracle DBMS への接続を確立します。
WebLogic Server を使用して、アプリケーションから Oracle DBMS に 2 層接続するには、次の手順を実行します。接続の詳細については、「WebLogic Server ソフトウェアでの接続プールのコンフィグレーション」を参照してください。
java.sql.Driver
オブジェクトにキャストします。XA ドライバを使用している場合は Datasource API を使用します。java.sql.Driver
API は使用しません。次に例を示します。
Driver myDriver = (Driver)Class.forName
("weblogic.jdbc.oci.Driver").newInstance();
java.util.Properties
オブジェクトを作成します。このオブジェクトは、ユーザ名、パスワード、データベース名、サーバ名、およびポート番号などの情報が入った名前と値の組み合わせを格納します。次に例を示します。Properties props = new Properties();
props.put("user", "scott");
props.put("password", "secret");
props.put("server", "DEMO");
サーバ名 (上の例では DEMO
) は、Oracle クライアントのインストール先ディレクトリにある tnsnames.ora
ファイル内のエントリを参照します。サーバ名によって、ホスト名と Oracle データベースについてのその他の情報が定義されます。サーバ名を提供しなかった場合、システムは環境変数 (Oracle の場合は ORACLE_SID
) を探します。次のフォーマットに従って、サーバ名を URL に追加することもできます。
"jdbc:weblogic:oracle:DEMO"
この構文でサーバを指定する場合、server プロパティを提供する必要はありません。
PowerSoft の PowerJ などの製品で使用するために、単一の URL 内にプロパティを設定することもできます。
Driver.connect()
メソッドを呼び出すことで、JDBC の操作で不可欠となる JDBC 接続オブジェクトを作成します。このメソッドは、パラメータとしてドライバの URL と手順 2 で作成した java.util.Properties
オブジェクトを取ります。次に例を示します。
Connection conn =
myDriver.connect("jdbc:weblogic:oracle", props);
手順 1 と 3 では、JDBC ドライバを記述します。手順 1 では、ドライバの完全パッケージ名を使用します。ドットを使って区切ります。手順 3 では、URL (コロンで区切る) を使ってドライバを識別します。URL には、jdbc:weblogic:oracle
という文字列が入っていなければなりません。このほかに、サーバのホスト名やデータベース名などの情報を入れることもできます。
WebLogic Server の多層コンフィグレーションで、アプリケーションから Oracle DBMS に接続するには、次の手順を実行します。
try {
Context ctx = new InitialContext();
javax.sql.DataSource ds
= (javax.sql.DataSource) ctx.lookup ("myDataSource");
} catch (NamingException ex) {
// ルックアップに失敗
}
try {
java.sql.Connection conn = ds.getConnection();
} catch (SQLException ex) {
// 接続の取得に失敗
}
詳細については、「DataSource のコンフィグレーションと使い方」を参照してください。
このサンプルは、myDB
というデータベースに接続するために Properties オブジェクトをどのように使用するかを示します。
Properties props = new Properties();
props.put("user", "scott");
props.put("password", "secret");
props.put("db", "myDB");
Driver myDriver = (Driver)
Class.forName("weblogic.jdbc.oci.Driver").newInstance();
Connection conn =
myDriver.connect("jdbc:weblogic:oracle", props);
Connection オブジェクトはアプリケーションの重要な部分です。Connection クラスは、アプリケーションで使用する多くの基本的なデータベースに対するコンストラクタを持ちます。たとえば次のサンプルでは、Connection オブジェクト conn
が何度も使われています。データベースに接続すると、アプリケーションの初期部分は終了します。
Connection オブジェクトを使った処理が終了したら、直ちにこのオブジェクトに対して close()
メソッドを呼び出す必要があります。通常は、クラスの最後で呼び出します。
データベース アクセスにおける最も基本的な作業は、データを検索することです。WebLogic Server を使ってデータを検索するには、次の 3 段階の手順を実行します。
Statement stmt = conn.createStatement();
stmt.execute("select * from emp");
ResultSet rs = stmt.getResultSet();
while (rs.next()) {
System.out.println(rs.getString("empid") + " - " +
rs.getString("name") + " - " +
rs.getString("dept"));
}
ResultSetMetaData md = rs.getMetaData();
System.out.println("Number of columns: " +
md.getColumnCount());
for (int i = 1; i <= md.getColumnCount(); i++) {
System.out.println("Column Name: " +
md.getColumnName(i));
System.out.println("Nullable: " +
md.isNullable(i));
System.out.println("Precision: " +
md.getPrecision(i));
System.out.println("Scale: " +
md.getScale(i));
System.out.println("Size: " +
md.getColumnDisplaySize(i));
System.out.println("Column Type: " +
md.getColumnType(i));
System.out.println("Column Type Name: "+
md.getColumnTypeName(i));
System.out.println("");
}stmt.close();
この手順では、データベース テーブルのレコードの挿入、更新、および削除という、データベースに関する 3 つの一般的な作業を示します。これらの処理には、JDBC PreparedStatement を使います。まず、PreparedStatement を作成してから、それを実行し、閉じます。
PreparedStatement (JDBC Statement のサブクラス) を使用すると、同じ SQL を値を変えて何度でも実行できます。PreparedStatement では、JDBC の「?」構文を使用します。
String inssql =
"insert into emp(empid, name, dept) values (?, ?, ?)";
PreparedStatement pstmt = conn.prepareStatement(inssql);
for (int i = 0; i < 100; i++) {
pstmt.setInt(1, i);
pstmt.setString(2, "Person " + i);
pstmt.setInt(3, i);
pstmt.execute():
}
pstmt.close();
PreparedStatement を使用してレコードを更新することもできます。次のサンプルでは、カウンタ「i」の値を「dept」フィールドの現在の値に追加します。
String updsql =
"update emp set dept = dept + ? where empid = ?";
PreparedStatement pstmt2 = conn.prepareStatement(updsql);
for (int i = 0; i < 100; i++) {
pstmt2.setInt(1, i);
pstmt2.setInt(2, i);
pstmt2.execute();
}
pstmt2.close();
最後に、PreparedStatement を使用して、さきほど追加および更新されたレコードを削除します。
String delsql = "delete from emp where empid = ?";
PreparedStatement pstmt3 = conn.prepareStatement(delsql);
for (int i = 0; i < 100; i++) {
pstmt3.setInt(1, i);
pstmt3.execute();
}
pstmt3.close();
注意 : varchar2 の値を挿入または更新するときに空の文字列 (""
) を挿入しようとすると、Oracle はその値を NULL
として解釈します。値を挿入するカラムに NOT NULL
制約がある場合、データベースは「ORA-01400 : カラム名には NULL を挿入できません」エラーを送出します。
Prepared Statement の変数に値を初期設定すると、データ型は変数にバインドされます。Prepared Statement を直接アプリケーションで再利用する場合、または Statement キャッシュにキャッシュされている Prepared Statement を再利用する場合、その文では、変数の値と同じデータ型を使用する必要があります。これは Oracle OCI の制限であり、バインドされた変数の型を動的に変更することはできません。データ型がバインドされたデータ型と異なる場合、可能であれば、WebLogic jDriver はそのデータ型をバインドされたデータ型に自動的に変換します。自動変換は、JDBC 3.0 仕様の表 B-5 に示されている変換に限定されます。たとえば、このドライバは string をさまざまな別の型に変換できますが、Blob は変換できません。Blob は Blob として使用する必要があります。
JDBC 3.0 仕様は、Java Web サイトの JDBC ページからダウンロードできます。
注意 : データ型を変換すると、データが切り詰められる可能性があります。データが切り詰められるのは、バインドされたデータ型に、同じ変数に対して次に使用されるデータ型のデータが収まらない場合です。たとえば、変数を int
データ型とバインドしてから、setFloat
メソッドを使用して小数部を持つ値を更新する場合、値の小数部は、int
へ変換するときに切り詰められます。
WebLogic Server は、接続プールの接続ごとに Prepared Statement を Statement キャッシュにデフォルトでキャッシュします。Statement キャッシュ内の Prepared Statement と同一の Prepared Statement を使用する場合、アプリケーションはキャッシュされている Prepared Statement を使用します。現在のアプリケーションの変数のデータ型が、キャッシュされている Prepared Statement の変数にバインドされているデータ型と一致しない場合、上記の説明のとおり、WebLogic jDriver はデータ型をバインドされたデータ型に自動的に変換します。Statement キャッシュの詳細については、Administration Console オンライン ヘルプの「Statement キャッシュによるパフォーマンス向上」を参照してください。
WebLogic Server で使用するトランザクションのタイプによって、ストアド プロシージャとストアド関数の使い方が決まります。
まず、一連の文を実行して、ストアド プロシージャとストアド関数をデータベースから削除します。
Statement stmt = conn.createStatement();
try {stmt.execute("drop procedure proc_squareInt");}
catch (SQLException e) {//ここに例外処理をコーディング;}
try {stmt.execute("drop procedure func_squareInt");}
catch (SQLException e) {//ここに例外処理をコーディング;}
try {stmt.execute("drop procedure proc_getresults");}
catch (SQLException e) {//ここに例外処理をコーディング;}
stmt.close();
JDBC Statement を使用してストアド プロシージャまたはストアド関数を作成してから、JDBC の「?」構文で JDBC CallableStatement (Statement のサブクラス) を使用して、IN
および OUT
パラメータを設定します。
ネイティブ Oracle では SQL 文中で「?」値のバインディングをサポートしていません。代わりに、「:1
」、「:2
」等を使用します。WebLogic Server では SQL 文の中でどちらの構文を使用することもできます。
ストアド プロシージャの入力パラメータは、JDBC の IN
パラメータにマップされており、setInt()
などの CallableStatement.setXXX()
メソッドと JDBC PreparedStatement「?」構文で使われます。ストアド プロシージャの出力パラメータは、JDBC の OUT
パラメータにマップされており、CallableStatement.registerOutParameter()
メソッドと JDBC PreparedStatement「?」構文で使われます。IN
と OUT
の両方のパラメータを使って、setXXX()
と registerOutParameter()
の呼び出しが両方とも同じパラメータ番号で行われるようにしてもかまいません。
このサンプルでは、JDBC Statement を使用して Oracle ストアド プロシージャを 1 つ作成してから、そのプロシージャを CallableStatement を使用して実行しています。registerOutParameter()
メソッドを使用して、2 乗された値を入れるための出力パラメータを設定しています。
Statement stmt1 = conn.createStatement();
stmt1.execute
("CREATE OR REPLACE PROCEDURE proc_squareInt " +
"(field1 IN OUT INTEGER, field2 OUT INTEGER) IS " +
"BEGIN field2 := field1 * field1; field1 := " +
"field1 * field1; END proc_squareInt;");
stmt1.close();
// ネイティブ Oracle SQL をここにコメントアウト
// String sql = "BEGIN proc_squareInt(?, ?); END;";
// これは JDBC で指定された正しい構文
String sql = "{call proc_squareInt(?, ?)}";
CallableStatement cstmt1 = conn.prepareCall(sql);
// 出力パラメータを登録する
cstmt1.registerOutParameter(2, java.sql.Types.INTEGER);
for (int i = 0; i < 5; i++) {
cstmt1.setInt(1, i);
cstmt1.execute();
System.out.println(i + " " + cstmt1.getInt(1) + " "
+ cstmt1.getInt(2));
} cstmt1.close();
次のサンプルでは、同様のコードを使用して、整数を 2 乗するストアド関数を作成して実行します。
Statement stmt2 = conn.createStatement();
stmt2.execute("CREATE OR REPLACE FUNCTION func_squareInt " +
"(field1 IN INTEGER) RETURN INTEGER IS " +
"BEGIN return field1 * field1; " +
"END func_squareInt;");
stmt2.close();
// ネイティブ Oracle SQL をここにコメントアウト
// sql = "BEGIN ? := func_squareInt(?); END;";
// これは JDBC で指定された正しい構文
sql = "{ ? = call func_squareInt(?)}";
CallableStatement cstmt2 = conn.prepareCall(sql);
cstmt2.registerOutParameter(1, Types.INTEGER);
for (int i = 0; i < 5; i++) {
cstmt2.setInt(2, i);
cstmt2.execute();
System.out.println(i + " " + cstmt2.getInt(1) +
" " + cstmt2.getInt(2));
}
cstmt2.close();
次に、sp_getmessages
というストアド プロシージャを使用します (このストアド プロシージャのコードはこのサンプルには含まれていません)。このストアド プロシージャは、入力パラメータとしてメッセージ番号を取り、メッセージ テキストの入ったテーブルからメッセージ番号に対応するメッセージ テキストを探し、そのメッセージ テキストを出力パラメータとして ResultSet
に格納して返します。Statement.execute()
および Statement.getResult()
メソッドを使ってストアド プロシージャから返された ResultSet
をすべて処理してからでないと、OUT
パラメータと戻りステータスは使用可能になりません。
まず、CallableStatement に対する 3 つのパラメータを設定します。
String sql = "{ ? = call sp_getmessage(?, ?)}";
CallableStatement stmt = conn.prepareCall(sql);
stmt.registerOutParameter(1, java.sql.Types.INTEGER);
stmt.setInt(2, 18000); // メッセージ番号 18000
stmt.registerOutParameter(3, java.sql.Types.VARCHAR);
次に、ストアド プロシージャを実行し、戻り値をチェックして、ResultSet が空かどうかを調べます。空でない場合は、ループを使用して、その内容を取り出して表示するという処理を繰り返します。
boolean hasResultSet = stmt.execute();
while (true)
{
ResultSet rs = stmt.getResultSet();
int updateCount = stmt.getUpdateCount();
if (rs == null && updateCount == -1) // 他に結果がない場合
break;
if (rs != null) {
// 空になるまで ResultSet オブジェクトを処理する
while (rs.next()) {
System.out.println
("Get first col by id:" + rs.getString(1));
}
} else {
// 更新件数がある
System.out.println("Update count = " +
stmt.getUpdateCount());
}
stmt.getMoreResults();
}
ResultSet の処理が終了すると、OUT
パラメータと戻りステータスが使用可能になります。
int retstat = stmt.getInt(1);
String msg = stmt.getString(3);
System.out.println("sp_getmessage: status = " +
retstat + " msg = " + msg);
stmt.close();
接続を閉じる前に、データベースに対する変更をコミットするために commit()
メソッドを呼び出すと便利な場合があります。
自動コミットが true (デフォルトの JDBC トランザクション モード) に設定されている場合、各 SQL 文がそれぞれトランザクションになります。しかし、このサンプルでは、Connection を作成した後に、自動コミットを false に設定しました。このモードでは、Connection は関連する暗黙的なトランザクションを常に持っており、rollback()
または commit()
メソッドを呼び出すと、現在のトランザクションが終了し、新しいトランザクションが開始されます。close()
の前に commit()
を呼び出すと、Connection を閉じる前にすべてのトランザクションが必ず完了します。
Statement、PreparedStatement、および CallableStatement を使う作業が終了したときにこれらのオブジェクトを閉じるように、アプリケーションの最後のクリーンアップとして、Connection オブジェクトの close()
メソッドを try {}
ブロック内で必ず呼び出し、例外を捕捉して適切な処理を行います。このサンプルの最後の 2 行では、commit
を呼び出してから close
を呼び出して接続を閉じます。
conn.commit();
conn.close();
ストアド プロシージャを実行すると、複数の ResultSet が返されることがあります。ストアド プロシージャから返された ResultSet を、Statement.execute()
および Statement.getResultSet()
メソッドを使って処理する場合は、返された ResultSet をすべて処理してからでないと、OUT パラメータまたは戻りステータスは使用できません。
Oracle はクライアントに配列フェッチ機能も提供しており、jDriver for Oracle はこの機能をサポートしています。デフォルトでは、jDriver for Oracle は最大 100 行の配列を DBMS から取得します。この数字は、weblogic.oci.cacheRows
プロパティを使って変更できます。
上記のメソッドを使用すると、100 行の WebLogic JDBC クエリは、クライアントから WebLogic へ 4 つの呼び出しを実行するだけで済む上に、実際に WebLogic がデータを要求するために DBMS に送る呼び出しは 1 つだけです。詳細については、「Oracle 配列フェッチのサポート」を参照してください。
次のコードでは、JDBC アプリケーションの構造を示します。ここに示すコード例の内容は、データの検索、メタデータの表示、データの挿入、削除、および更新、さらに、ストアド プロシージャおよびストアド関数の呼び出しです。JDBC 関連の各オブジェクトに対して close()
を明示的に呼び出すだけでなく、try {}
ブロックでラップした close()
を呼び出して、Connection 自体を finally {}
ブロックで閉じています。
package examples.jdbc.oracle;
import java.sql.*;
import java.util.Properties;
import weblogic.common.*;
public class test {
static int i;
Statement stmt = null;
public static void main(String[] argv) {
try {
Properties props = new Properties();
props.put("user", "scott");
props.put("password", "tiger");
props.put("server", "DEMO");
Driver myDriver = (Driver) Class.forName
("weblogic.jdbc.oci.Driver").newInstance();
Connection conn =
myDriver.connect("jdbc:weblogic:oracle", props);
}
catch (Exception e)
e.printStackTrace();
}
try {
// これにより Oracle のパフォーマンスが向上する
// 後で commit() を明示的に呼び出す必要がある
conn.setAutoCommit(false);
stmt = conn.createStatement();
stmt.execute("select * from emp");
ResultSet rs = stmt.getResultSet();
while (rs.next()) {
System.out.println(rs.getString("empid") + " - " +
rs.getString("name") + " - " +
rs.getString("dept"));
}
ResultSetMetaData md = rs.getMetaData();
System.out.println("Number of Columns: " +
md.getColumnCount());
for (i = 1; i <= md.getColumnCount(); i++) {
System.out.println("Column Name: " +
md.getColumnName(i));
System.out.println("Nullable: " +
md.isNullable(i));
System.out.println("Precision: " +
md.getPrecision(i));
System.out.println("Scale: " +
md.getScale(i));
System.out.println("Size: " +
md.getColumnDisplaySize(i));
System.out.println("Column Type: " +
md.getColumnType(i));
System.out.println("Column Type Name: "+
md.getColumnTypeName(i));
System.out.println("");
}
rs.close();
stmt.close();
Statement stmtdrop = conn.createStatement();
try {stmtdrop.execute("drop procedure proc_squareInt");}
catch (SQLException e) {;}
try {stmtdrop.execute("drop procedure func_squareInt"); }
catch (SQLException e) {;}
try {stmtdrop.execute("drop procedure proc_getresults"); }
catch (SQLException e) {;}
stmtdrop.close();
// ストアド プロシージャを作成する
Statement stmt1 = conn.createStatement();
stmt1.execute
("CREATE OR REPLACE PROCEDURE proc_squareInt " +
"(field1 IN OUT INTEGER, " +
"field2 OUT INTEGER) IS " +
"BEGIN field2 := field1 * field1; " +
"field1 := field1 * field1; " +
"END proc_squareInt;");
stmt1.close();
CallableStatement cstmt1 =
conn.prepareCall("BEGIN proc_squareInt(?, ?); END;");
cstmt1.registerOutParameter(2, Types.INTEGER);
for (i = 0; i < 100; i++) {
cstmt1.setInt(1, i);
cstmt1.execute();
System.out.println(i + " " + cstmt1.getInt(1) +
" " + cstmt1.getInt(2));
}
cstmt1.close();
// ストアド関数を作成する
Statement stmt2 = conn.createStatement();
stmt2.execute
("CREATE OR REPLACE FUNCTION func_squareInt " +
"(field1 IN INTEGER) RETURN INTEGER IS " +
"BEGIN return field1 * field1; END func_squareInt;");
stmt2.close();
CallableStatement cstmt2 =
conn.prepareCall("BEGIN ? := func_squareInt(?); END;");
cstmt2.registerOutParameter(1, Types.INTEGER);
for (i = 0; i < 100; i++) {
cstmt2.setInt(2, i);
cstmt2.execute();
System.out.println(i + " " + cstmt2.getInt(1) +
" " + cstmt2.getInt(2));
}
cstmt2.close();
// レコードを 100 件挿入する
System.out.println("Inserting 100 records...");
String inssql =
"insert into emp(empid, name, dept) values (?, ?, ?)";
PreparedStatement pstmt = conn.prepareStatement(inssql);
for (i = 0; i < 100; i++) {
pstmt.setInt(1, i);
pstmt.setString(2, "Person " + i);
pstmt.setInt(3, i);
pstmt.execute();
}
pstmt.close();
// レコードを 100 件更新する
System.out.println("Updating 100 records...");
String updsql =
"update emp set dept = dept + ? where empid = ?";
PreparedStatement pstmt2 = conn.prepareStatement(updsql);
for (i = 0; i < 100; i++) {
pstmt2.setInt(1, i);
pstmt2.setInt(2, i);
pstmt2.execute();
}
pstmt2.close();
// レコードを 100 件削除する
System.out.println("Deleting 100 records...");
String delsql = "delete from emp where empid = ?";
PreparedStatement pstmt3 = conn.prepareStatement(delsql);
for (i = 0; i < 100; i++) {
pstmt3.setInt(1, i);
pstmt3.execute();
}
pstmt3.close();
conn.commit();
}
catch (Exception e) {
// 失敗を適切に処理する
}
finally {
try {conn.close();}
catch (Exception e) {
// 例外を捕捉して処理する
}
}
}
}
これ以外の Oracle コード例については、samples\examples\jdbc\oracle ディレクトリを参照してください。
WebLogic Server はすべての JDBC 2.0 メソッドをサポートしていますが、WebLogic jDriver for Oracle ではサポートしていない JDBC 2.0 メソッドもあります。これらのメソッドを使用する必要がある場合は、Oracle Thin ドライバなどの別の JDBC ドライバを使用してデータベースに接続することができます。表 3-2 に、WebLogic jDriver for Oracle でサポートされていない JDBC 2.0 メソッドを示します。
![]() ![]() |
![]() |
![]() |