ORACLE JAPAN Server Release 6.1

 

  |  

  WebLogic Server ホーム   |     jDriver for Oracle   |   前へ   |   次へ   |   目次   |   索引   |   PDF 版

Oracle の高度な機能

 

この章では、Oracle の高度な機能について説明します。

 


大文字/小文字を区別せずにメタデータを扱う方法

WebLogic Server では、allowMixedCaseMetaData プロパティを設定できます。このプロパティをブール値 true に設定すると、このプロパティは、DatabaseMetaData メソッドの呼び出しで大文字/小文字を区別しないように、Connection オブジェクトを設定します。このプロパティを false に設定した場合、Oracle は、データベース メタデータについて大文字をデフォルトで使用します。

次のサンプル コードは、この機能を利用するためのプロパティの設定方法を示します。

Properties props = new Properties();
props.put("user", "scott");
props.put("password", "tiger");
props.put("server", "DEMO");
props.put("allowMixedCaseMetaData", "true");

Driver myDriver = (Driver)
Class.for.Name(weblogic.jdbc.oci.Driver).newInstance();

Connection conn =
myDriver.connect("jdbc:weblogic:oracle", props);

このプロパティを設定しなかった場合、WebLogic Server は Oracle のデフォルト設定を使用するので、データベース メタデータについては大文字が使用されます。

 


データ型

次の表は、Oracle データ型と Java 型との推奨マッピングを示します。この他にも、Oracle データ型を Java で表現する方法はあります。結果セットの処理中に getObject() メソッドを呼び出した場合、クエリ対象の Oracle カラムに対するデフォルトの Java データ型が返されます。

図5-1 Oracle と WebLogic Server の型の対応表

Oracle

WebLogic Server

Varchar

String

Number

Tinyint

Number

Smallint

Number

Integer

Number

Long

Number

Float

Number

Numeric

Number

Double

Long

Longvarchar

RowID

String

Date

Timestamp

Raw

(var)Binary

Long raw

Longvarbinary

Char

(var)Char

Boolean*

Number OR Varchar

MLS label

String

Blob

Blob

Clob

Clob

* PreparedStatement.setBoolean() を呼び出すと、VARCHAR 型は 1 または 0(文字列)に、NUMBER 型は 1 または 0(数字)に変換されます。

 


WebLogic Server と Oracle の NUMBER カラム

Oracle には NUMBER というカラム タイプがあります。このカラム タイプは、オプションとして NUMBER(P) および NUMBER(P,S)の形式で精度とスケールを指定できます。修飾されていない単純な NUMBER 形式でも、このカラムは、小さな整数値から非常に大きな浮動小数点までのすべての数値タイプを高い精度で保持できます。

WebLogic Server アプリケーションがこうしたカラムの値を要求すると、WebLogic Server は、カラム内の値を要求された Java 型に変換します。getInt() で 123.456 という値が要求された場合、当然、値は丸められます。

ただし、getObject() メソッドの場合は、これより若干複雑になります。WebLogic Server は、NUMBER カラムの値を同様の精度で表現する Java オブジェクトで必ず返します。つまり、値 1 は Integer として返されますが、123434567890.123456789 のような値は BigDecimal でのみ返されます。

カラムの値の最大精度を Oracle から報告するメタデータはありません。したがって、WebLogic Server は、それぞれの値に基づいて、どのような種類のオブジェクトを返すかを判断する必要があります。つまり、1 つの ResultSet が、NUMBER カラムに対して getObject() から複数の Java 型を返す場合があるということです。整数値だけのテーブルはすべて Integer として getObject() から返されることもあり、浮動小数点単位のテーブルは主に Double で返されますが、「123.00」のような値は Integer として返される場合があります。Oracle からは、NUMBER 値の「1」と「1.0000000000」を識別するための情報は提供されていません。

修飾された NUMBER カラム、つまり、特定の精度が定義されているカラムは、動作の信頼性が高くなります。Oracle のメタデータはこれらのパラメータをドライバに提供するため、WebLogic Server はテーブルの値にかかわりなく、常に特定の精度とスケールに合わせて適切な Java オブジェクトを返します。

カラム定義

getObject() の戻り値の型

NUMBER(P <= 9)

Integer

NUMBER(P <= 18)

Long

NUMBER(P = 19)

BigDecimal

NUMBER(P <=16, S 0)

Double

NUMBER(P = 17, S 0)

BigDecimal

 


Oracle の Long raw データ型の使い方

WebLogic Server では、Blob、Clob、Long、および Long raw といった Oracle のデータ型を使用する場合に備えて、2 つのプロパティを提供しています。Blob および Clob データ型は、Oracle バージョン 8 と JDBC 2.0 でサポートされているだけですが、これらのプロパティは、Oracle バージョン 7 で使用可能な Oracle の Long raw データ型に対しても適用できます。

 


Oracle リソース上の待機

注意: waitOnResources() メソッドは、Oracle 8 API 使用時にはサポートされません。

WebLogic Server のドライバは、Oracle の oopt() C 関数をサポートしています。これは、リソースが使用可能になるまでクライアントが待機できるようにする機能です。Oracle C 関数は、要求されたリソースが使用可能でない場合のオプション(ロックを待機するかどうかなど)を設定します。

開発者は、クライアントが DBMS リソースを待機するか、または直ちに例外を受け取るかを指定できます。次のコードは、サンプル コード ファイル(examples\jdbc\oracle\waiton.java)からの抜粋です。

java.util.Properties props = new java.util.Properties();
props.put("user", "scott");
props.put("password", "tiger");
props.put("server", "myserver");

Driver myDriver = (Driver)
Class.forName("weblogic.jdbc.oci.Driver").newInstance();

// この拡張機能を利用するために Connection を
// weblogic.jdbc.oci.Connection としてキャストする必要がある

Connection conn =(weblogic.jdbc.oci.Connection)
myDriver.connect("jdbc:weblogic:oracle", props);

// オブジェクトの作成後、直ちに
// waitOnResources メソッドを呼び出す

conn.waitOnResources(true);

このメソッドを使用すると、短期間ロックされる内部リソースを待つ間に、いくつかのエラー リターン コードが発生する場合があります。

この機能を使用するには、次の処理を行う必要があります。

  1. Connection オブジェクトを weblogic.jdbc.oci.Connection としてキャストします。

  2. waitOnResources() メソッドを呼び出します。

この関数については、The OCI Functions for C のセクション 4-97 に記載されています。

自動コミット

JDBC WebLogic Server のデフォルト トランザクション モードでは、自動コミットを true と仮定します。Connection オブジェクトの作成後、次の文で自動コミットを false に設定することで、プログラムの性能を改善できます。

Connection.setAutoCommit(false);

トランザクションのアイソレーション レベル

WebLogic Server は、以下のトランザクションのアイソレーション レベルをサポートしています。

Oracle DBMS はこれら 2 つのアイソレーション レベルのみをサポートしています。他の JDBC ドライバと違い、WebLogic Server は、開発者がサポートされていないアイソレーション レベルを使おうとした場合に例外を生成します。一部のドライバは、サポートされていないアイソレーション レベルを設定しようとした場合に、例外を生成することなく無視します。

READ_UNCOMMITTED トランザクション アイソレーション レベルはサポートされていません。

コードセットのサポート

JDBC と WebLogic Server は、Java 内の文字列を Unicode 文字列として扱います。Oracle DBMS は別のコードセットを使用するため、Unicode から Oracle が使用するコードセットに変換する必要があります。WebLogic Server は、Oracle の環境変数 NLS_LANG 内の値を調べて、変換に使用する JDK のコードセットを選択します。コードセットのマッピングには、 表 5-1が使用されます。NLS_LANG 変数が設定されていない場合、または JDK に認識できないコードセットに設定されていた場合、ドライバは正しいコードセットを選択できません。(NLS_LANG の正しい構文の詳細については、Oracle のドキュメントを参照してください。)

コードセットを変換する場合は、コード内で接続を確立するときに Driver.connect() メソッドを使用して、次のプロパティを WebLogic Server に渡す必要があります。

props.put("weblogic.oci.min_bind_size", 660);

このプロパティは、バインドされるバッファの最小サイズを定義します。デフォルトでは 2000 バイトで、これは最大値でもあります。コードセットを変換する場合は、このプロパティを使用して、バインド サイズを最大 2000 バイトの 1/3 の最大 660 に減らす必要があります。この理由は、Oracle コード変換では、拡張を考慮してバッファが 3 倍に拡大されるからです。

WebLogic Server では、Java コード内からコードセットを設定できます。接続プロパティの weblogic.codeset を設定すると、NLS_LANG 環境変数内の値をオーバーライドできます。たとえば、次のサンプルのように、cp863 コードセットを使用するには、Driver.connect() を呼び出す前に、Properties オブジェクトを作成し、weblogic.codeset プロパティを設定します。

java.util.Properties props = new java.util.Properties();
props.put("weblogic.codeset", "cp863");
props.put("user", "scott");
props.put("password", "tiger");

String connectUrl = "jdbc:weblogic:oracle";

Driver myDriver = (Driver)
Class.forName("weblogic.jdbc.oci.Driver").newInstance();

Connection conn =
myDriver.connect(connectUrl, props);

コードセット サポートは、JVM の種類によって異なります。特定のコードセットがサポートされているかどうかについては、使用している JDK のドキュメントをチェックしてください。

表5-1 NLS_LANG 設定と JDK コードセットのマッピング対応表

NLS_LANG

JDK codeset

al24utffss

UTF8

al32utf8

UTF8

ar8iso8859p6

ISO8859_6

cdn8pc863

Cp863

cl8iso8859p5

ISO8859_5

cl8maccyrillic

MacCyrillic

cl8mswin1251

Cp1251

ee8iso8859p2

ISO8859_2

ee8macce

MacCentralEurope

ee8maccroatian

MacCroatian

ee8mswin1250

Cp1250

ee8pc852

Cp852

el8iso8859p7

ISO8859_7

el8macgreek

MacGreek

el8mswin1253

Cp1253

el8pc737

Cp737

is8macicelandic

MacIceland

is8pc861

Cp861

iw8iso8859p8

ISO8859_8

ja16euc

EUC_JP

ja16sjis

SJIS

ko16ksc5601

EUC_KR

lt8pc772

Cp772

lt8pc774

Cp774

n8pc865

Cp865

ne8iso8859p10

ISO8859_10

nee8iso8859p4

ISO8859_4

ru8pc855

Cp855

ru8pc866

Cp866

se8iso8859p3

ISO8859_3

th8macthai

MacThai

tr8macturkish

MacTurkish

tr8pc857

Cp857

us7ascii

ASCII

us8pc437

Cp437

utf8

UTF8

we8ebcdic37

Cp1046

we8ebcdic500

Cp500

we8iso8859p1

ISO8859_1

we8iso8859p15

ISO8859_15_FDIS

we8iso8859p9

ISO8859_9

we8macroman8

MacRoman

we8pc850

Cp850

we8pc860

Cp860

zht16big5

Big5

Oracle 配列フェッチのサポート

WebLogic Server は、Oracle 配列フェッチをサポートしています。ResultSet.next() を最初に呼び出したときには、1 行を取り出すのではなく、行の配列を取得して、それをメモリに格納します。それ以降の next() に対する各呼び出しは、メモリに格納した行をそれぞれ 1 行読み取ります。この操作はメモリ内の行がなくなるまで続き、行がなくなると、next() への呼び出しはデータベースに戻ります。

配列フェッチのサイズを制御するには、プロパティ(java.util.Property)を設定します。このプロパティは weblogic.oci.cacheRows で、デフォルトで 100 に設定されています。このプロパティを 300 に設定する例を次に示します。これは、next() への呼び出しは、クライアントが取り出す 300 行につき 1 回だけデータベースをヒットすることを意味します。

Properties props = new Properties();
props.put("user", "scott");
props.put("password", "tiger");
props.put("server", "DEMO");
props.put("weblogic.oci.cacheRows", "300");

Driver myDriver = (Driver)
Class.forName("weblogic.jdbc.oci.Driver").newInstance();

Connection conn = myDriver.connect("jdbc:weblogic:oracle", props);

この JDBC 拡張機能を利用することで、クライアントの性能を改善し、データベース サーバの負荷を緩和できます。ただし、クライアントでの行のキャッシングは、クライアント リソースを必要とします。ネットワーク コンフィグレーションとアプリケーションに応じて、性能とクライアント リソースのバランスが最適になるようにアプリケーションを調整してください。

SELECT 内のカラムが LONG、BLOB、または CLOB 型の場合、WebLogic Server は、その select 文に関連付けられている ResultSet のキャッシュ サイズを一時的に 1 にリセットします。

ストアド プロシージャの使い方

この節では、Oracle に固有のストアド プロシージャのさまざまな実装について説明します。

Oracle カーソルへのパラメータのバインド

WebLogic は、ストアド プロシージャのパラメータを Oracle カーソルにバインドできるようにする JDBC の拡張機能(weblogic.jdbc.oci.CallableStatement)を作成しました。ストアド プロシージャの結果を使って、JDBC ResultSet オブジェクトを作成できます。これによって、複数の ResultSet を整理して返すことができます。ResultSet は実行時にストアド プロシージャ内で決定されます。

次に例を示します。まず、次のようにストアド プロシージャを定義します。

create or replace package
curs_types as
type EmpCurType is REF CURSOR RETURN emp%ROWTYPE;
end curs_types;
/

create or replace procedure
single_cursor(curs1 IN OUT curs_types.EmpCurType,
ctype in number) AS BEGIN
if ctype = 1 then
OPEN curs1 FOR SELECT * FROM emp;
elsif ctype = 2 then
OPEN curs1 FOR SELECT * FROM emp where sal 2000;
elsif ctype = 3 then
OPEN curs1 FOR SELECT * FROM emp where deptno = 20;
end if;
END single_cursor;
/
create or replace procedure
multi_cursor(curs1 IN OUT curs_types.EmpCurType,
curs2 IN OUT curs_types.EmpCurType,
curs3 IN OUT curs_types.EmpCurType) AS
BEGIN
OPEN curs1 FOR SELECT * FROM emp;
OPEN curs2 FOR SELECT * FROM emp where sal 2000;
OPEN curs3 FOR SELECT * FROM emp where deptno = 20;
END multi_cursor;
/

Java コード内で、ストアド プロシージャを使用して CallableStatements を作成し、出力パラメータをデータ型 java.sql.Types.OTHER で登録します。データを ResultSet 内に取り出すときに、出力パラメータのインデックスを getResultSet() メソッドの引数として使用します。

java.sql.CallableStatement cstmt = conn.prepareCall(
"BEGIN OPEN ? " +
"FOR select * from emp; END;");
cstmt.registerOutParameter(1, java.sql.Types.OTHER);

cstmt.execute();
ResultSet rs = cstmt.getResultSet(1);
printResultSet(rs);
rs.close();
cstmt.close();

java.sql.CallableStatement cstmt2 = conn.prepareCall(
"BEGIN single_cursor(?, ?); END;");
cstmt2.registerOutParameter(1, java.sql.Types.OTHER);

cstmt2.setInt(2, 1);
cstmt2.execute();
rs = cstmt2.getResultSet(1);
printResultSet(rs);

cstmt2.setInt(2, 2);
cstmt2.execute();
rs = cstmt2.getResultSet(1);}
printResultSet(rs);

cstmt2.setInt(2, 3);
cstmt2.execute();
rs = cstmt2.getResultSet(1);
printResultSet(rs);
cstmt2.close();

java.sql.CallableStatement cstmt3 = conn.prepareCall(
"BEGIN multi_cursor(?, ?, ?); END;");
cstmt3.registerOutParameter(1, java.sql.Types.OTHER);
cstmt3.registerOutParameter(2, java.sql.Types.OTHER);
cstmt3.registerOutParameter(3, java.sql.Types.OTHER);

cstmt3.execute();

ResultSet rs1 = cstmt3.getResultSet(1);
ResultSet rs2 = cstmt3.getResultSet(2);
ResultSet rs3 = cstmt3.getResultSet(3);

printResultSet() メソッドを含むこのサンプルの全コードについては、samples\examples\jdbc\oracle\ ディレクトリにあるサンプルを参照してください。

Oracle ストアド プロシージャの文字列のデフォルト サイズは 256K です。

CallableStatement の使用上の注意

CallableStatement の OUTPUT パラメータにバインドされる文字列のデフォルト長は 128 文字です。バインド パラメータに割り当てた値がこの長さを超えると、次のエラーが発生します。

ORA-6502: value or numeric error

バインド パラメータの値の長さは、明示的な長さを scale 引数を使って CallableStatement.registerOutputParameter() メソッドに渡すことによって調節できます。256 文字を超えない VARCHAR をバインドするコード サンプルを次に示します。

CallableStatement cstmt =
conn.prepareCall("BEGIN testproc(?); END;");

cstmt.registerOutputParameter(1, Types.VARCHAR, 256);
cstmt.execute();
System.out.println(cstmt.getString());
cstmt.close();

DatabaseMetaData メソッド

この節では、Oracle に固有の DatabaseMetaData メソッドの実装について説明します。

 


JDBC 拡張 SQL のサポート

JavaSoft JDBC 仕様には、SQL 拡張が含まれています。SQL 拡張は SQL Escape 構文とも呼ばれています。すべての WebLogic jDriver は拡張 SQL をサポートしています。拡張 SQL によって、DBMS 間で移植可能な共通の SQL 拡張機能にアクセスできます。

たとえば、日付から曜日を取り出す関数は、SQL 標準では定義されていません。Oracle の SQL では次のようになります。

select to_char(date_column, 'DAY') from table_with_dates

同等の関数は、Sybase や Microsoft SQL Server では次のようになります。

select datename(dw, date_column) from table_with_dates

拡張 SQL を使うと、どちらの DBMS に対しても、次のようにして曜日を取り出すことができます。

select {fn dayname(date_column)} from table_with_dates

次のサンプルは、拡張 SQL の機能のいくつかを示します。

String query =
"-- This SQL includes comments and " +
"JDBC extended SQL syntax.\n" +
"select into date_table values( \n" +
" {fn now()}, -- current time \n" +
" {d '1997-05-24'}, -- a date \n" +
" {t '10:30:29' }, -- a time \n" +
" {ts '1997-05-24 10:30:29.123'}, -- a timestamp\n" +
" '{string data with { or } will not be altered}'\n" +
"-- Also note that you can safely include" +
" { and } in comments or\n" +
"-- string data.";
Statement stmt = conn.createStatement();
stmt.executeUpdate(query);

拡張 SQL は、一般の SQL と区別するために中括弧(「{}」)で囲ってあります。コメントはダブルハイフンで始まり、改行コード(「\n」)で終わっています。コメント、SQL、および拡張 SQL を含む拡張 SQL のシーケンス全体は、二重引用符で囲み、Statement オブジェクトの execute() メソッドに渡します。CallableStatement の一部に拡張 SQL を使った例を次に示します。

CallableStatement cstmt =
conn.prepareCall("{ ? = call func_squareInt(?)}");

次のサンプルは、拡張 SQL 式をネストできるということを示しています。

select {fn dayname({fn now()})}

サポートされている拡張 SQL 関数の一覧は、DatabaseMetaData オブジェクトから取り出すことができます。次のサンプルは、JDBC ドライバがサポートしている関数のすべてをリストする方法を示しています。

DatabaseMetaData md = conn.getMetaData();
System.out.println("Numeric functions: " +
md.getNumericFunctions());
System.out.println("\nString functions: " +
md.getStringFunctions());
System.out.println("\nTime/date functions: " +
md.getTimeDateFunctions());
System.out.println("\nSystem functions: " +
md.getSystemFunctions());
conn.close();

 


Oracle 用 JDBC 2.0 の概要

WebLogic jDriver for Oracle で実装されている JDBC 2.0 の機能は以下のとおりです。

以前のバージョンで利用可能だった既存の JDBC 機能に加えて、上記の新機能も WebLogic Server で利用できるようになりました。前バージョンのドライバで使用していた既存のコードは、すべてこの新 WebLogic jDriver for Oracle でも動作します。

 


JDBC 2.0 のサポートに必要なコンフィグレーション

WebLogic Server バージョン 6.1 は JDK 1.3.1 上で動作するので、JDBC 2.0 には Java 2 環境が必要となります。サポートされているコンフィグレーションの全リストについては、「WebLogic プラットフォーム サポート」ページを参照してください。

 


BLOB と CLOB

BLOB(Binary Large Object)および CLOB(Character Large Object)データ型は、Oracle バージョン 8 のリリースで利用できるようになりました。JDBC 2.0 仕様と WebLogic Server もこれらのデータ型をサポートしています。この節では、これらのデータ型の使い方について説明します。

注意: 次の制限に注意してください。WebLogic jDriver for Oracle と組み合わせて RMI ドライバ使用する場合、BLOB と CLOB を使用することはできません。BLOB および CLOB はシリアライズできないため、WebLogic Server 6.x で使用する JDBC RMI ドライバではサポートされません。

トランザクション境界

Oracle での BLOB と CLOB は、トランザクション境界(SQL の commit または rollback 文の前に発行された文)に関しては、他のデータ型とは動作が異なります。BLOB または CLOB は、トランザクションがコミットされると直ちに非アクティブになります。AutoCommit が TRUE に設定されている場合、その接続で各コマンドが発行された後に、トランザクションはそれぞれ自動的にコミットされます。SELECT 文の場合でもコミットされます。この理由により、複数の SQL 文にまたがって BLOB または CLOB を保持する必要がある場合には、AutoCommit を false に設定しなければなりません。トランザクションを適切なタイミングで手動でコミット(またはロールバック)することが必要になります。AutoCommit を false に設定するには、次のコマンドを入力します。

conn.setAutoCommit(false); // conn は対象となる connection オブジェクト

BLOB

Oracle バージョン 8 で使用可能になった BLOB データ型を使用すると、Oracle テーブルに大きなバイナリ オブジェクトを保存したり、テーブルから取り出したりできます。BLOB は JDBC 2.0 仕様の一部として定義されていますが、仕様では、テーブル内の BLOB カラムを更新するためのメソッドが提供されていません。しかし、BEA WebLogic の BLOB の実装は、JDBC 2.0 を拡張することでこの機能を提供します。

Connection プロパティ

weblobic.oci.selectBlobChunkSize

このプロパティは、I/O ストリームへバイトや文字を送信する際に使われる内部バッファのサイズを設定します。指定したサイズに達したら、ドライバは暗黙的に flush() 処理を実行します。これにより、データは DBMS に送られます。

この値を明示的に設定することは、クライアントのメモリ使用量の制御に役立ちます。

このプロパティの値が設定されていない場合には、デフォルト値 65534 が使用されます。

このプロパティを、プロパティとして Connection オブジェクトに渡すことで設定します。たとえば、次のコードは weblobic.oci.selectBlobChunkSize を 1200 に設定します。

Properties props = new Properties();
props.put("user", "scott");
props.put("password", "tiger");
props.put("server", "DEMO" );

props.put ("weblobic.oci.selectBlobChunkSize","1200");

Driver myDriver = (Driver)
 Class.forName("weblogic.jdbc.oci.Driver").newInstance();

Connection conn =
 driver.connect("jdbc:weblogic:oracle:myServer", props);

weblogic.oci.insertBlobChunkSize

このプロパティは、ドライバが内部的に使用する入力ストリームのバッファ サイズ(バイト単位)を指定します。

BLOB チャンク機能を使用して、Oracle DBMS に Blob を挿入するには、このプロパティを正の整数に設定します。デフォルトでは、このプロパティは、BLOB チャンクを使用しないことを意味するゼロ(0)に設定されています。

Import 文

この節で説明されている BLOB 機能を使用するには、クライアント コードに以下のクラスをインポートします。

import java.sql.*;
import java.util.*;
import java.io.*;
import weblogic.jdbc.common.*;

BLOB フィールドの初期化

BLOB データ型が入った行を最初に挿入するときには、実際のデータを使ってそのフィールドを更新する前に、「空の」BLOB を持つ行を挿入する必要があります。空の BLOB を挿入するには、Oracle EMPTY_BLOB() 関数を使用します。

BLOB フィールドを初期化する手順は以下のとおりです。

  1. 1 つまたは複数のカラムを BLOB データ型として定義したテーブルを作成します。

  2. Oracle EMPTY_BLOB() 関数を使用して、空の BLOB カラムを 1 つ持つ行を 1 つ挿入します。

    stmt.execute("INSERT into myTable values (1,EMPTY_BLOB()");

  3. その BLOB カラムへの「ハンドル」を取得します。

    java.sql.Blob myBlob = null;
    Statement stmt2 = conn.createStatement();
    stmt2.execute("SELECT myBlobColumn from myTable
    where pk = 1 for update");
    ResultSet rs = stmt2.getResultSet();
    rs.next() {
    myBlob = rs.getBlob("myBlobColumn");
    // 取得した BLOB を使用して何かする
    }

  4. 以上で、BLOB にデータを書き込めるようになりました。次の節、「 BLOB へのバイナリ データの書き込み」に進みます。

BLOB へのバイナリ データの書き込み

BLOB カラムにバイナリ データを書き込む手順は以下のとおりです。

  1. 上記「 BLOB フィールドの初期化」の 手順 3. に従って、BLOB フィールドへのハンドルを取得します。

  2. バイナリ データが入る InputStream オブジェクトを作成します。

    java.io.InputStream is = // 入力ストリームを作成する

  3. BLOB データを書き込むための出力ストリームを作成します。BLOB オブジェクトを weblogic.jdbc.common.OracleBlob にキャストしなければなりません。

    java.io.OutputStream os =
    ((weblogic.jdbc.common.OracleBlob) myBlob).getBinaryOutputStream();

  4. バイナリ データが入った入力ストリームを出力ストリームに書き込みます。書き込み操作は、OutputStream オブジェクトの flush() メソッドを呼び出したときに終了します。

    byte[] inBytes = new byte[65534]; // 下記の「注意」を参照
    int numBytes = is.read(inBytes);
    while (numBytes > 0) {
    os.write(inBytes, 0, numBytes);
    numBytes = is.read(inBytes);
    }
    os.flush();

    注意: 上記コードの中の値 [65534] は、65534 というデフォルト値を持つ weblogic.oci.select.BlobChunkSize プロパティが未設定であると仮定したものです。このプロパティを設定してある場合、byte[] の値を weblogic.oci.select.BlobChunkSize property に設定した値に合わせると、データを最も効率的に扱えるようになります。このプロパティの詳細については、「 Connection プロパティ」を参照してください。

  5. クリーンアップします。

    os.close();
    pstmt.close();
    conn.close();

BLOB オブジェクトの書き込み

BLOB オブジェクトをテーブルに書き込むには、Prepared Statements を使用します。たとえば、myBlob オブジェクトをテーブル myOtherTable に書き込むコードは以下のとおりです。

PreparedStatement pstmt = conn.preparedStatement(
"UPDATE myOtherTable SET myOtherBlobColumn = ? WHERE id = 12");

pstmt.setBlob(1, myBlob);

Prepared Statement を使用した CLOB 値の更新

Prepared Statement を使用して CLOB を更新する場合、新しい値が古い値より短いと、更新の際に明示的に置換されなかった文字が CLOB に残ります。たとえば、現在の値が abcdefghij である CLOB を Prepared Statement で zxyw という値に更新すると、更新後の CLOB の値は zxywefghij になります。Prepared Statement で更新した結果を正しい値にするには、dbms_lob.trim プロシージャを使って、更新後に残っている余分な文字を削除する必要があります。dbms_lob.trim プロシージャの詳細については、Oracle のマニュアルを参照してください。

BLOB データの読み取り

getBlob() メソッドを使用して BLOB カラムを取り出してから、SQL SELECT 文の実行結果 ResultSet を使用した場合は、BLOB データへのポインタだけが返されます。バイナリ データは実際にはクライアントに転送されていません。getBinaryStream() メソッドを呼び出して初めて、データがストリーム オブジェクトに書き込まれます。

Oracle テーブルから BLOB データを読み取る手順は以下のとおりです。

  1. SELECT 文を実行します。

    stmt2.execute("SELECT myBlobColumn from myTable");

  2. その SELECT 文の実行結果を使用します。

    int STREAM_SIZE = 10;
    byte[] r = new byte[STREAM_SIZE];

    ResultSet rs = stmt2.getResultSet();
    java.sql.Blob myBlob = null;
    while (rs.next) {
    myBlob = rs.getBlob("myBlobColumn");

    java.io.InputStream readis = myBlob.getBinaryStream();

    for (int i=0 ; i < STREAM_SIZE ; i++) {
    r[i] = (byte) readis.read();
    System.out.println("output [" + i + "] = " + r[i]);
    }

  3. クリーンアップします。

    rs.close();
    stmt2.close();

注意: また、CallableStatement を使用して、ResultSet を生成することもできます。この ResultSet は、上記と同じように使用できます。詳細については、JDK ドキュメントの java.sql.CallableStatment の部分を参照してください。

その他のメソッド

さらに、java.sql.Blob インタフェースの以下のメソッドが、WebLogic Server JDBC 2.0 ドライバに実装されています。詳細については、JDK ドキュメントを参照してください。

position() メソッドは実装されていません。

CLOB

Oracle バージョン 8 で使用可能になった CLOB データ型は、Oracle テーブル内に大きな文字列を格納できます。JDBC 2.0 の仕様には CLOB カラムを直接更新する機能は含まれていないので、CLOB を挿入したり更新したりするために、BEA では getAsciiOutputStream() メソッド(ASCII データ用)と getCharacterOutputStream() メソッド(Unicode データ用)を実装しました。

コードセットのサポート

使用する Oracle Server およびクライアントのバージョンによっては、以下のプロパティのいずれかを設定する必要があります。設定するには、DBMS 接続を確立したときにそのプロパティを Connection オブジェクトに渡すように、Java クライアントのコード中に記述します。

weblogic.codeset

このプロパティを使用すると、Java コード内からコードセットを設定できます。このコードセットは、Oracle 環境変数 NLS_LANG に指定されたコードセットの値をオーバーライドします。

weblogic.oci.ncodeset

このプロパティは、Oracle サーバが使用するナショナル コードセットを設定します。このコードセットは、Oracle 環境変数 NLS_NCHAR に指定されたコードセットの値をオーバーライドします。

weblogic.oci.codeset_width

このプロパティは、使用している文字コードセットが何バイト幅のタイプなのかを WebLogic Server に知らせます。

指定できる値は次のとおりです。

0(可変幅のコードセットを使用する場合)

1(固定幅のコードセットを使用する場合。1 はデフォルト値)

2 または 3(コードセットの幅をバイト単位で指定する場合)

weblogic.oci.ncodeset_width

Oracle のナショナル コードセットのいずれかを使用している場合には、このプロパティを使用してコードセットの文字幅を指定します。

指定できる値は次のとおりです。

0(可変幅のコードセットを使用する場合)

1(固定幅のコードセットを使用する場合。1 はデフォルト値)

2 または 3(コードセットの幅をバイト単位で指定する場合)

CLOB フィールドの初期化

CLOB データ型が入った行を最初に挿入するときには、実際のデータを使ってそのフィールドを更新する前に、「空の」CLOB を持つ行を挿入する必要があります。空の CLOB を挿入するには、Oracle EMPTY_CLOB() 関数を使用します。

CLOB カラムを初期化する手順は以下のとおりです。

  1. 1 つまたは複数のカラムを CLOB データ型として定義したテーブルを作成します。

  2. Oracle EMPTY_CLOB() 関数を使用して、空の CLOB カラムを 1 つ持つ行を 1 つ挿入します。

    stmt.execute("INSERT into myTable VALUES (1,EMPTY_CLOB()");

  3. CLOB カラムのオブジェクトを取得します。

    java.sql.Clob myClob = null;
    Statement stmt2 = conn.createStatement();
    stmt2.execute("SELECT myClobColumn from myTable
    where pk = 1 for update");
    ResultSet rs = stmt2.getResultSet();
    while (rs.next) {
    myClob = rs.getClob("myClobColumn");
    }

  4. 以上で、CLOB に文字データを書き込めるようになりました。書き込むデータが ASCII フォーマットの場合は、次の節「 CLOB への ASCII データの書き込み」に進みます。書き込むデータが Unicode フォーマットの場合は、「 CLOB への Unicode データの書き込み」を参照してください。

CLOB への ASCII データの書き込み

CLOB カラムに ASCII 文字データを書き込む手順は以下のとおりです。

  1. 上記「 CLOB フィールドの初期化」の手順 3. に従って、CLOB へのハンドルを取得します。

  2. 文字データが入るオブジェクトを作成します。

    String s = // ASCII データ

  3. CLOB 文字列を書き込むための出力ストリームを作成します。CLOB オブジェクトを weblogic.jdbc.common.OracleClob にキャストしなければなりません。

    java.io.OutputStream os =
    ((weblogic.jdbc.common.OracleClob) myclob).getAsciiOutputStream();

  4. ASCII データが入った入力ストリームを出力ストリームに書き込みます。書き込み操作は、OutputStream オブジェクトの flush() メソッドを呼び出したときに終了します。

    byte[] b = s.getBytes("ASCII");

    os.write(b);
    os.flush();

  5. クリーンアップします。

    os.close();
    pstmt.close();
    conn.close();

CLOB への Unicode データの書き込み

CLOB カラムに Unicode 文字データを書き込む手順は以下のとおりです。

  1. CLOB フィールドの初期化」の手順 3 に従って、CLOB への「ハンドル」を取得します。

  2. 文字データが入るオブジェクトを作成します。

    String s = // Unicode 文字データ

  3. CLOB 文字列を書き込むための文字出力ストリームを作成します。CLOB オブジェクトを weblogic.jdbc.common.OracleClob にキャストしなければなりません。

    java.io.Writer wr =
    ((weblogic.jdbc.common.OracleClob) myclob).getCharacterOutputStream();

  4. ASCII データが入った入力ストリームを出力ストリームに書き込みます。書き込み操作は、OutputStream オブジェクトの flush() メソッドを呼び出したときに終了します。

    char[] b = s.toCharArray(); // 「s」 を文字配列に変換

    wr.write(b);
    wr.flush();

  5. クリーンアップします。

    wr.close();
    pstmt.close();
    conn.close();

CLOB オブジェクトの書き込み

CLOB オブジェクトをテーブルに書き込むには、Prepared Statements を使用します。たとえば、myClob オブジェクトをテーブル myOtherTable に書き込むコードは以下のとおりです。

PreparedStatement pstmt = conn.preparedStatement(
"UPDATE myOtherTable SET myOtherClobColumn = ? WHERE id = 12");

pstmt.setClob(1, myClob);

CLOB データの読み取り

SQL SELECT 文の実行結果を使用して CLOB カラムを取り出した場合は、CLOB データへのポインタだけが返されます。実際のデータはクライアントに転送されていません。getAsciiStream() メソッドが呼び出されて初めて、その文字データがストリームに読み込まれます。

Oracle テーブルから CLOB データを読み取る手順は以下のとおりです。

  1. SELECT 文を実行します。

    java.sql.Clob myClob = null;
    Statement stmt2 = conn.createStatement();
    stmt2.execute("SELECT myClobColumn from myTable");

  2. その SELECT 文の実行結果を使用します。

    ResultSet rs = stmt2.getResultSet();

    while (rs.next) {
    myClob = rs.getClob("myClobColumn");
    java.io.InputStream readClobis =
    myReadClob.getAsciiStream();
    char[] c = new char[26];
    for (int i=0 ; i < 26 ; i++) {
    c[i] = (char) readClobis.read();
    System.out.println("output [" + i + "] = " + c[i]);
    }
    }

  3. クリーンアップします。

    rs.close();
    stmt2.close();

注意: また、CallableStatement を使用して、ResultSet を生成することもできます。この ResultSet は、上記と同じように使用できます。詳細については、JDK ドキュメントの java.sql.CallableStatment の部分を参照してください。

その他のメソッド

さらに、java.sql.Clob インタフェースの以下のメソッドが、WebLogic Server(JDBC 2.0 ドライバ)に実装されています。

これらのメソッドの詳細については、JDK ドキュメントを参照してください。

注意: position() メソッドは実装されていません。

 


文字と ASCII ストリーム

JDBC 2.0 仕様の新しいメソッドの一部では、文字と ASCII ストリームを、以前のバージョンで実装されていたようにバイト列として扱うのではなく、文字列として扱うことができます。文字と ASCII ストリームを扱うための以下のメソッドが WebLogic Server で実装されています。

Unicode 文字ストリーム

getCharacterStream()

java.sql.ResultSet インタフェースは、Unicode ストリームを Java の java.io.Reader 型として読み込むために、このメソッドを使用します。このメソッドは、非推奨になった getUnicodeStream() メソッドに代わって採用されました。

setCharacterStream()

java.sql.PreparedStatement インタフェースは、java.io.Reader オブジェクトを書き込むためにこのメソッドを使用します。このメソッドは、非推奨になった setUnicodeStream() メソッドに代わって採用されました。

ASCII 文字ストリーム

getAsciiStream()

java.sql.ResultSet インタフェースは、ASCII ストリームを Java の java.io.InputStream 型として読み込むためにこのメソッドを使用します。

setAsciiStream()

java.sql.PreparedStatement インタフェースは、java.io.InputStream オブジェクトを書き込むためにこのメソッドを使用します。

これらのメソッドの使い方の詳細については、JDK ドキュメントを参照してください。

バッチ更新

バッチ更新は JDBC 2.0 の新しい機能で、この機能を使用すると、複数の SQL 更新文を 1 単位として DBMS に送ることができます。アプリケーションによっては、複数の更新文を個々に送るよりも性能が向上することがあります。バッチ更新機能は、Statement インタフェースで使用可能ですが、更新件数を返して結果セットを返さない SQL 文を使用することが必要となります。callableStatement または preparedStatement を使用したバッチ更新はサポートされていません。

バッチ更新で使用できる SQL 文は以下のとおりです。

バッチ更新の使い方

バッチ更新の使い方の基本的な手順を以下に示します。

  1. 第 3 章「WebLogic jDriver for Oracle の使い方」の「Oracle DBMS への接続」の説明に従って、WebLogic Server JDBC 2.0 ドライバを使用して接続を得ます(connection オブジェクトを取得します)。このサンプルでは、接続オブジェクトは conn です。

  2. createStatement() メソッドを使用して、statement オブジェクトを作成します。次に例を示します。

    Statement stmt = conn.createStatement();

  3. addBatch() メソッドを使用して、SQL 文をバッチに追加します。これらの文は、executeBatch() メソッドが呼び出されるまで、DBMS に送られません。次に例を示します。

    stmt.addBatch("INSERT INTO batchTest VALUES ('JOE', 20,35)");
    stmt.addBatch("INSERT INTO batchTest VALUES ('Bob', 30,44)");
    stmt.addBatch("INSERT INTO batchTest VALUES ('Ed', 34,22)");

  4. executeBatch() メソッドを使用して、処理のためバッチを DBMS に送ります。次に例を示します。

    stmt.executeBatch();

    文が失敗して例外が発生した場合、文は 1 行も実行されません。

バッチ処理文の消去

clearBatch() メソッドを使用すると、addBatch() メソッドを使用して作成した文の集合を消去できます。次に例を示します。

stmt.clearBatch();

更新件数

JDBC 2.0 仕様によると、executeBatch() メソッドは、各 Statement で更新された行の数が入った整数の配列を返すことになっています。しかし、Oracle DBMS はこの情報をドライバに提供していません。代わりに、Oracle DBMS は、すべての更新に対して -2 を返します。

 


新しい日付関連メソッド

以下のメソッドは、新しい署名を使用して、java.util.Calendar オブジェクトをパラメータとして取ります。java.util.Calendar を使用すると、日付の変換に使われるタイム ゾーンやロケーションの情報を指定できます。java.util.Calendar クラスの使い方の詳細については、JDK API ガイドを参照してください。

java.sql.ResultSet.getDate(int columnIndex, Calendar cal)

java.sql.Date オブジェクトを返す)

java.sql.PreparedStatement.setDate
(int parameterIndex, Date x, Calendar cal)

java.sql.CallableStatement.getDate
(int parameterIndex, Calendar cal)

java.sql.Date オブジェクトを返す)

 

back to top previous page