![]() |
![]() |
|
|
| |
WebLogic jDriver for Oracle の使い方
この節では、簡単なアプリケーションに関する基本作業について説明し、最後にサンプル コードを示します。
ローカル トランザクションと分散トランザクションの比較
WebLogic Server でトランザクションを実行する場合は、ローカル トランザクションと分散トランザクションのどちらを使うかによって、一部の基本作業が異なります。トランザクションは以下のように分けられます。
分散トランザクションの詳細については、「 分散トランザクションでの WebLogic jDriver for Oracle/XA の使い方」を参照してください。
JDBC パッケージのインポート
アプリケーションにインポートしなければならないクラスは以下のとおりです。
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 をプログラムのコンパイル後に決めることもできます。
CLASSPATH の設定
WebLogic Server に付属のドライバを使用して WebLogic Server クライアントを実行する場合は、CLASSPATH
に次のディレクトリを追加しなければなりません。
%WL_HOME%
\lib
\weblogic.jar
(%WL_HOME%
は WebLogic Server のインストール先ディレクトリです)
スタンドアロン バージョンの WebLogic Server を実行している場合は、CLASSPATH に次のパス名を指定します。
%WL_HOME%
\oci\classes
%WL_HOME%
を、WebLogic Server のインストール先ディレクトリの名前と置き換えます。
CLASSPATH
の設定と環境設定に関する問題の詳細については、『WebLogic Server アプリケーションの開発』の「開発環境の構築」を参照してください。
Oracle クライアント ライブラリのバージョン、URL、およびドライバ クラス名
使用するドライバ クラス名と URL は、以下の要素によって決まります。
また、システムのパスに正しいドライバ バージョンを指定しなければなりません。詳細については、「WebLogic jDriver for Oracle の使用環境の設定」を参照してください。
ドライバを XA モードで使用する場合 :
Oracle DBMS への接続
以下の節で説明するように、2 層接続または多層接続を使用して、アプリケーションから Oracle DBMS への接続を確立します。
2 層コンフィグレーションの WebLogic Server を使用した接続
WebLogic Server を使用して、アプリケーションから Oracle DBMS に 2 層接続するには、次の手順を実行します。接続の詳細については、 WebLogic jDriver for Oracle のインストール後の作業を参照してください。
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 を使用した接続
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) {
// 接続の取得に失敗
}
接続のサンプル
このサンプルは、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);
DataSource オブジェクトを用いた接続
DataSource オブジェクトを使用して接続することもできます。詳細については、『WebLogic JDBC プログラミング ガイド』の「DataSources の概要」を参照してください。
WebLogic JDBC を使用するためのプロパティ設定
WebLogic Server のドライバと一緒に多層環境内で WebLogic JDBC を使用する場合は、若干異なる方法で接続プロパティを設定することになります。詳細については、『WebLogic JDBC プログラミング ガイド』を参照してください。
Connection オブジェクトについて
Connection オブジェクトはアプリケーションの重要な部分です。Connection クラスは、アプリケーションで使用する多くの基本的なデータベースに対するコンストラクタを持ちます。たとえば次のサンプルでは、Connection オブジェクト conn
が何度も使われています。データベースに接続すると、アプリケーションの初期部分は終了します。
Connection オブジェクトを使った処理が終了したら、直ちにこのオブジェクトに対して close()
メソッドを呼び出す必要があります。通常は、クラスの最後で呼び出します。
自動コミットの設定
自動コミットのデフォルト設定は、次の表のとおりです。
トランザクション タイプ |
自動コミットのデフォルト設定 |
デフォルト設定の変更 |
結果 |
---|---|---|---|
ローカル トランザクション |
true |
|
デフォルト設定を false に変更するとパフォーマンスが向上することがある。 |
分散トランザクション |
false |
変更しない |
デフォルト設定を変更してはならない。true に変更すると、SQLException が発生する。 |
簡単な SQL クエリの作り方
データベース アクセスにおける最も基本的な作業は、データを検索することです。WebLogic Server を使ってデータを検索するには、次の 3 段階の手順を実行します。
ResultSet
に入れます。このサンプルでは、従業員テーブル(エイリアス名 emp
)に対して簡単なクエリを実行し、3 つのカラムのデータを表示します。また、データの検索先のテーブルに関するメタデータにアクセスして表示します。最後に Statement
を閉じます。
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();
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 つのパラメータを設定します。
sp_getmessage
への msgno 引数
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 が返されることがあります。ストアド プロシージャから返された ResultSets を、Statement.execute()
および Statement.getResultSet()
メソッドを使って処理する場合は、返された ResultSets をすべて処理してからでないと、OUT パラメータまたは戻りステータスは使用できません。
WebLogic JDBC による行キャッシング
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 ディレクトリを参照してください。
未サポートの JDBC 2.0 メソッド
WebLogic Server は JDBC 2.0 のすべてのメソッドをサポートしますが、WebLogic jDriver for Oracle では JDBC 2.0 の一部のメソッドはサポートされません。そのようなメソッドを使う必要がある場合、Oracle Thin Driver などの別の JDBC ドライバを使用してデータベースに接続できます。 表 3-2 に、WebLogic jDriver for Oracle でサポートされていない JDBC 2.0 メソッドの一覧を示します。
![]() |
![]() |
![]() |