BEA ホーム | 製品 | dev2dev | support | askBEA |
![]() |
![]() |
|
![]() |
e-docs > WebLogic Server > WebLogic jDriver for Oracle のコンフィグレーションと使い方 > WebLogic jDriver for Oracle の使い方 |
WebLogic jDriver for Oracle のコンフィグレーションと使い方
|
WebLogic jDriver for Oracle の使い方
この章では、簡単なアプリケーションに関する基本作業について説明します。この章には、コード例やサポートされていないメソッドのリストも含まれています。
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 interface を実装します。アプリケーションを作成するには、java.sql クラスを使用します。JDBC ドライバ クラスをインポートする必要はありませんが、代わりに、アプリケーション内でドライバをロードします。これにより、適切なドライバを実行時に選択できるようになります。接続先となる DBMS をプログラムのコンパイル後に決めることもできます。
WebLogic Server に付属のドライバを使用して WebLogic Server クライアントを実行する場合は、CLASSPATH に次のディレクトリを追加しなければなりません。
%WL_HOME%¥server¥lib¥weblogic.jar
CLASSPATH の設定と環境設定に関する問題の詳細については、『WebLogic Server アプリケーションの開発』の「開発環境の構築」を参照してください。
Oracle クライアント ライブラリのバージョン、URL、およびドライバ クラス名
使用するドライバ クラス名と URL は、以下の要素によって決まります。
また、システムのパスに正しいドライバ バージョンを指定しなければなりません。詳細については、「WebLogic jDriver for Oracle の使用環境の設定」を参照してください。
以下の節で説明するように、2 層接続または多層接続を使用して、アプリケーションから Oracle DBMS への接続を確立します。
WebLogic Server を使用したデータベースへの2 層コンフィグレーションによる接続
WebLogic Server を使用して、アプリケーションから Oracle DBMS に 2 層接続するには、次の手順を実行します。接続の詳細については、WebLogic Server ソフトウェアでの接続プールのコンフィグレーションを参照してください。
Driver myDriver = (Driver)Class.forName
("weblogic.jdbc.oci.Driver").newInstance();
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's PowerJ などの製品で使用するために、単一の URL 内にプロパティを設定することもできます。
Connection conn =
myDriver.connect("jdbc:weblogic:oracle", props);
手順 1 と 3 では、JDBC ドライバを記述します。手順 1 では、ドライバの完全パッケージ名を使用します。ドットを使って区切ります。手順 3 では、URL (コロンで区切ります) を使ってドライバを識別します。URL には、jdbc:weblogic:oracle という文字列が入っていなければなりません。このほかに、サーバのホスト名やデータベース名などの情報を入れてもかまいません。
多層コンフィグレーションの WebLogic Server を使用した接続
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 を作成してから、それを実行し、閉じます。
PreparedStatemen (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 を挿入できません」エラーを送出します。
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() メソッドを使ってストアド プロシージャから返された ResultSets をすべて処理してからでないと、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();
ストアド プロシージャを実行すると、複数の ResultSets が返されることがあります。ストアド プロシージャから返された ResultSets を、Statement.execute() および Statement.getResultSet() メソッドを使って処理する場合は、返された ResultSets をすべて処理してからでないと、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.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 メソッドを示します。
![]() |
![]() |
![]() |
![]() |
||
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |