この章では、Oracle Database内でJavaメソッドをコールする方法の概要および例を示します。内容は次のとおりです。
Javaアプリケーションのタイプによって、クライアントがJavaメソッドをコールする方法が決まります。次の項では、Javaメソッドのコールに使用できる各Java Application Programming Interface(API)について説明します。
Javaストアド・プロシージャは、PL/SQLストアド・プロシージャと同じ方法で実行できます。Oracle Databaseでは、通常、JavaはPL/SQLインタフェースを介して起動します。
Javaストアド・プロシージャをコールするには、コール仕様を使用して公開する必要があります。次の例は、文字列を戻す簡単なJavaストアド・プロシージャを作成、解決、ロードおよび公開する方法を示しています。
クラスHello
を次のように定義します。
public class Hello { public static String world() { return "Hello world"; } }
ファイルをHello.java
ファイルとして保存します。
クライアント・システムで、標準Javaコンパイラを使用して、次のようにクラスをコンパイルします。
javac Hello.java
CLASSPATH
は、特に、シェル・スクリプトまたはMakeファイルの作成時にはjavac
コマンドを使用してコマンドラインで指定することをお薦めします。Javaコンパイラによって、Javaバイナリ・ファイル(この例の場合はHello.class
)が生成されます。
このJavaコードの実行場所を決定する必要があります。クライアント・システムでHello.class
を実行すると、Hello.class
の実行に必要なすべてのサポートされるコア・クラスがCLASSPATH
で検索されます。この結果、次のいずれかで依存クラスが検索されます。
1つ以上のディレクトリ内の個々のファイル。このディレクトリはCLASSPATH
で指定されます。
.jar
または.zip
ファイル内。このファイルを含むディレクトリはCLASSPATH
で指定されます。
この例の場合、サーバーでJavaスキーマ・オブジェクトとしてデータベースに格納される、Hello.class
をサーバーにロードします。world()
メソッドをコールすると、Oracle JVMでは、リゾルバを使用して、String
などの必要なサポート・クラスを検索します。この場合、Oracle JVMでは、デフォルトのリゾルバを使用します。デフォルトのリゾルバは、最初に現行スキーマ内、次にPUBLIC
内でクラスを検索します。java.lang
パッケージなど、すべてのコア・クラス・ライブラリはPUBLIC
内にあります。別のリゾルバを指定する必要がある場合があります。loadjava
ツールの使用時に解決を強制的に実行すると、実行時以前に問題をトレースできます。
loadjava
ツールを使用して、サーバー上にクラスをロードします。ユーザー名とパスワードを指定する必要があります。loadjava
ツールを次のように実行します。
loadjava -user HR Hello.class
Password: password
Java static
メソッドをSQLコールでコールするには、コール仕様を使用してメソッドを公開する必要があります。コール仕様では、メソッドで使用する引数およびメソッドで戻されるSQL型が定義されます。
SQL*Plusでは、次のようにデータベースに接続し、Hello.world()
に対するトップレベルのコール仕様を定義します。
sqlplus HR
Enter password: password
connected
SQL> CREATE OR REPLACE FUNCTION helloworld RETURN VARCHAR2 AS
2 LANGUAGE JAVA NAME 'Hello.world () return java.lang.String';
3 /
Function created.
ストアド・プロシージャを次のようにコールします。
SQL> VARIABLE myString VARCHAR2(20); SQL> CALL helloworld() INTO :myString; Call completed. SQL> PRINT myString; MYSTRING --------------------------------------- Hello world SQL>
call helloworld() into :myString
文によって、Oracle Databaseでトップレベルのコールが実行されます。SQLおよびPL/SQLでは、作成言語がJava、PL/SQLまたは他の言語のいずれであるかによってストアド・プロシージャが区別されることはありません。コール仕様は、言語間コールを一貫した方法で結び付ける手段です。コール仕様は、トリガーまたはSQLコールやPL/SQLコールでコールされるエントリ・ポイントのみに必要です。さらに、JDeveloperを使用してコール仕様を自動的に作成することもできます。
Javaネイティブ・インタフェース(JNI)は、Javaネイティブ・メソッドの作成、およびJVMのネイティブ・アプリケーションへの埋込みを行うための標準プログラミング・インタフェースです。JNIの主要目的は、プラットフォーム固有のネイティブ・ライブラリを使用するJavaアプリケーションのバイナリ互換性を提供することです。
Oracle Databaseでは、JavaアプリケーションにおけるJNIの使用はサポートされていません。JNIを使用する場合、アプリケーションが100パーセントPure Javaではないため、ネイティブ・メソッドをプラットフォーム間で移植する必要があります。ネイティブ・メソッドを使用すると、サーバーのクラッシュ、セキュリティ違反およびデータ破損などの問題が発生する可能性があります。
SQLJおよびJava Database Connectivity(JDBC)APIは、Javaクライアントから使用できます。この2つのAPIにより、指定したユーザー名とパスワードを使用してデータベース上でセッションが確立され、データベースに対するSQL問合せが実行されます。次の表に、APIとその説明を示します。
API | 説明 |
---|---|
JDBC | 比較的複雑または動的なSQL問合せの場合に、このAPIを使用します。JDBCでは、セッションの確立、問合せの作成などをユーザーが実行する必要があります。 |
SQLJ | 簡単で静的および動的なSQL問合せの場合に、このAPIを使用します。SQLJは、通常、既知の列名を持つ既知の表に対して実行されます。 |
この項の内容は、次のとおりです。
JDBCは業界標準のAPIであり、SQL文をJavaメソッドの引数として埋め込むことができます。JDBCはX/OpenのSQL Call Level Interface(CLI)に基づき、SQL92標準のエントリ・レベルに準拠しています。オラクル社などの各ベンダーは、標準のjava.sql
パッケージのインタフェースを実装することによって、独自のJDBC実装を作成しています。Oracleには、これらの標準インタフェースを実装する次のJDBCドライバが用意されています。
JDBC Thinドライバ。クライアント側のアプリケーションまたはアプレットに使用でき、Oracleクライアントのインストールを必要としない100パーセントPure Javaのソリューションです。
JDBC OCIドライバ。クライアント側のアプリケーションに使用するドライバで、Oracleクライアントのインストールが必要です。
サーバー側JDBCドライバ。Oracle Databaseに埋め込まれています。
JDBCを使用する場合は、次のタスクを順番に実行します。
接続ハンドルを取得します。
目的のSQL操作に使用する文オブジェクトを作成します。
SQL操作にバインドするローカル変数を代入します。
操作を実行します。
オプションで結果セットを取得します。
多くのアプリケーションではこの方法で十分ですが、複雑な文の場合は作業が煩雑になります。動的なSQL操作の場合は、実行時まで操作内容がわからないため、JDBCを使用する必要があります。ただし、典型的なアプリケーションでは、このSQL操作はあまり採用されていません。
関連項目: 『Oracle Database JDBC開発者ガイド』 |
SQLJには、1回の手順で静的なSQL操作をJavaソース・コードに直接埋め込む業界標準の方法が用意されているため、JDBCのような複数の手順は不要です。Oracle SQLJは、米国規格協会(ANSI)規格X3H2-98-320に準拠しています。
SQLJは、標準のSQLJプログラミング構文をサポートするプリコンパイラであるトランスレータとランタイム・コンポーネントで構成されています。SQLJソース・コードを.sqlj
ファイルに作成した後、トランスレータを使用して処理します。トランスレータでは、SQLJソース・コードが標準Javaソース・コードに変換され、SQL操作がSQLJランタイム・コールに変換されます。Oracle DatabaseのSQLJ実装では、トランスレータがJavaコンパイラをコールして、Javaソース・コードをコンパイルします。SQLJアプリケーションを実行すると、SQLJランタイムがJDBCをコールして、データベースと通信します。
また、SQLJを使用すると、実行時前にSQL文のエラーを捕捉できます。JDBCコードは、Pure Javaであるため、直接コンパイルされます。コンパイラでは、SQLエラーを検出できません。これに対して、SQLJコードの変換時に、トランスレータでは、埋め込まれているSQL文のセマンティクスおよび構文を解析するため、SQLエラーが開発時に捕捉され、アプリケーションの実行時にエンド・ユーザーによってエラーが捕捉されることはありません。
関連項目: 『Oracle Database SQLJ開発者ガイド』 |
次は、単純な操作を実行するJDBCコードとSQLJコードの例です。
// Assume you already have a JDBC Connection object conn // Define Java variables String name; int id=37115; float salary=20000; // Set up JDBC prepared statement. PreparedStatement pstmt = conn.prepareStatement ("SELECT first_name FROM employees WHERE employee_id=? AND salary>?"); pstmt.setInt(1, id); pstmt.setFloat(2, salary); // Execute query; retrieve name and assign it to Java variable. ResultSet rs = pstmt.executeQuery(); while (rs.next()) { name=rs.getString(1); System.out.println("Name is: " + name); } // Close result set and statement objects. rs.close() pstmt.close();
JDBC接続conn
がすでに確立されていると仮定しています。次の手順を実行する必要があります。
Javaの変数name
、id
およびsalary
を定義します。
PreparedStatement
インスタンスを作成します。
SQL文内の値を動的に設定する必要がある場合はいつでも、プリコンパイルされたSQL文を使用できます。異なる変数値を設定して、同じプリコンパイルされたSQL文を繰返し使用できます。プリコンパイルされたSQL文中の疑問符(?)は、Java変数用のプレースホルダです。前述の例では、これらの変数には、pstmt.setInt()
およびpstmt.setFloat()
メソッドを使用して値が割り当てられます。最初の「?」は、int
変数id
を参照し、値は37115
に設定されます。2番目の「?」は、float
変数salary
を参照し、値は20000
に設定されます。
問合せを実行し、データをResultSet
オブジェクトに戻します。
ResultSet
オブジェクトから目的のデータを取り出し、表示します。この場合は、first_name
列です。この例では1行のみですが、通常結果セットには複数行のデータが含まれます。
SQLJ:
String name; int id=37115; float salary=20000; #sql {SELECT first_name INTO :name FROM employees WHERE employee_id=:id AND salary>:salary}; System.out.println("Name is: " + name);
SQLJでは、SQL文を直接Javaコードに埋め込めることに加え、バインド式とも呼ばれる、SQL文で直接使用できるJavaホスト式をサポートしています。最も単純なホスト式は、この例のような単純な変数です。ただし、比較的複雑な式も使用できます。ホスト式の前には、コロン(:)を置きます。この例で使用されているJavaホスト式は、name
、id
およびsalary
です。SQLJではホスト式をサポートしているため、単一行のデータのみを戻す場合は、結果セットなどは不要です。
注意: SQLJ文は宣言も含めすべて、#sql トークンで始まります。 |
この項では、単純なSQLJプログラムの完全な例を示します。
import java.sql.*;
import sqlj.runtime.ref.DefaultContext;
import oracle.sqlj.runtime.Oracle;
#sql iterator MyIter (String first_name, int employee_id, float salary);
public class MyExample
{
public static void main (String args[]) throws SQLException
{
Oracle.connect("jdbc:oracle:thin:@localhost:5521:orcl", "HR", "<password>");
#sql { INSERT INTO employees (first_name, employee_id, salary) VALUES ('SMITH', 32, 20000) };
MyIter iter;
#sql iter={ SELECT first_name, employee_id, salary FROM employees };
while (iter.next())
{
System.out.println(iter.first_name()+" "+iter.employee_id()+" "+iter.salary());
}
}
}
この例では、次の手順を実行します。
イテレータを宣言します。
SQLJでは、イテレータと呼ばれる強い型指定のJDBC結果セットが使用されます。イテレータには、特定のデータ型に使用される特定数の列があります。この例のように、イテレータを使用する前に、イテレータの型を定義する必要があります。
#sql ITERATOR MyIter (String first_name, int employee_id, float salary);
この宣言によって、SQLJではイテレータ・クラス、MyIter
が作成されます。MyIter
型のイテレータでは、Java String
にマップされる最初の列の結果、Java int
にマップされる2番目の列の結果、およびJava float
にマップされる3番目の列の結果を格納できます。この定義では、3つの列にfirst_name
、employee_id
およびsalary
という名前が付けられ、データベース内の参照表の列名と照合されます。MyIter
は、名前付きイテレータです。
データベースに接続します。
Oracle.connect("jdbc:oracle:thin:@localhost:5521:orcl","HR", "<password>");
SQLJには、Oracle
クラスがあり、そのconnect()
メソッドを使用して次の重要なタスクが実行されます。
データベースにアクセスするためにSQLJが使用するOracle JDBCドライバ(この場合は、JDBC Thinドライバ)を登録します。
指定のURLにある指定したスキーマ(この場合は、指定されたパスワードを持つユーザーHR
)のデータベース接続をオープンします。この場合は、URLはホストlocalhost
、ポート5521
およびSID orcl
を指し示しています。
この接続をSQLJ文のデフォルト接続として確立します。JDBC文では接続オブジェクトを明示的に指定する必要がありますが、SQLJ文ではデフォルト接続を暗黙的に使用するか、または必要に応じて別の接続を指定できます。
SQL文を処理します。次の操作が実行されます。
行をemployees
表に挿入します。
#sql {INSERT INTO employees (first_name, employee_id, salary) VALUES ('SMITH', 32, 20000)};
次のイテレータがインスタンス化および移入されます。
MyIter iter; #sql iter={SELECT first_name, employee_id, salary FROM employees};
イテレータ内に移入されたデータにアクセスします。
while (iter.next()) { System.out.println(iter.first_name()+" "+iter.employee_id()+" "+iter.salary()); }
next()
メソッドはすべてのイテレータに共通で、JDBC結果セットのnext()
メソッドと同じ役割を果し、残りの行がある場合はtrue
を戻し、次の行のデータに移動します。列名と名前が一致するイテレータのアクセッサ・メソッドをコールすることで、各行のデータにアクセスできます。これは、すべての名前付きイテレータの特性です。この例では、メソッドfirst_name()
、employee_id()
およびsalary()
を使用してデータにアクセスします。
SQLJでは、結果セットではなく、イテレータのような強い型指定を使用します。これによって、変換時にSQL命令をデータベースに照合してチェックできます。たとえば、SQLJでは、データベースに接続し、問合せ対象のデータベース表と照合して各自のイテレータをチェックできます。トランスレータでは、これらの一致が確認されるため、変換時にSQLエラーを捕捉でき、確認されない場合、エラーはアプリケーションの実行時まで捕捉されません。さらに、スキーマを後で変更した場合、トランスレータを再実行することによって、変更内容がアプリケーションに影響を与えるかどうかを確認できます。
Oracle JDeveloperなどの統合開発環境(IDE)では、作成時に、SQLJプログラムを変換、コンパイルおよびカスタマイズできます。Oracle JDeveloperは、Microsoft社のWindowsに対応したJavaプログラミング用のビジュアル開発環境です。IDEを使用しない場合は、フロントエンドのSQLJユーティリティsqlj
を使用します。このユーティリティは次のように実行できます。
%sqlj MyExample.sqlj
SQLJトランスレータでは、SQL操作の構文とセマンティクスがチェックされます。オンライン・チェックを使用して、操作をデータベースに照合してチェックできます。これを行う場合は、トランスレータ・オプションの設定に、サンプル・データベース・スキーマを指定する必要があります。スキーマのデータは、プログラムで最終的に実行されるスキーマのデータと同一である必要はありません。ただし、表には対応する名前とデータ型を持つ列が含まれている必要があります。次の例のように、ユーザー・オプションを使用してオンライン・チェックを使用可能にし、スキーマのユーザー名、パスワードおよびURLを指定します。
%sqlj -user=HR@jdbc:oracle:thin:@localhost:5521:orcl MyExample.sqlj
Password: password
クライアント上では多くのSQLJアプリケーションが実行されます。ただし、SQLJは、通常サーバー上で実行するSQL集中型のストアド・プロシージャのプログラミングに優れた効果を発揮します。
クライアント側SQLJプログラムとサーバー側SQLJプログラムの作成に違いはほとんどありません。SQLJランタイム・パッケージはサーバー上で自動的に使用できます。ただし、次の点も考慮する必要もあります。
サーバー上でコードを実行する場合、明示的なデータベース接続はありません。暗黙的な接続が1つあるのみです。通常の接続コードは必要ありません。既存のクライアント側アプリケーションを移植する場合、接続コードは無視されるため、コードを削除する必要はありません。
サーバー側JDBC内部ドライバは、自動コミット機能をサポートしていません。トランザクションの手動コミットおよびロールバックには、SQLJ構文を使用します。
サーバーでのデフォルトの出力デバイスは、ユーザー・スクリーンではなくトレース・ファイルです。デプロイされているサーバー・アプリケーションのSystem.out
には書き込むことがないため、通常、これは開発時のみの問題です。
サーバーでSQLJプログラムを実行し、クライアント上にコードが作成されている場合は、次の2つのオプションがあります。
クライアント上のSQLJソース・コードを変換し、Javaのクラスやリソースなどの個々のコンポーネントをサーバー上にロードします。この場合、最初にクラスやリソースを.jar
ファイルにまとめてから、サーバー上にロードすると簡単です。
埋め込まれているトランスレータで変換するSQLJソース・コードをサーバー上にロードします。
いずれの場合も、loadjava
ツールを使用してサーバーにファイル(複数可)をロードします。
既存のSQLJクライアント側アプリケーションを変換してサーバー上で実行するには、そのアプリケーションがクライアント上で変換された後、次の手順を実行します。
アプリケーション・コンポーネント用の.jar
ファイルを作成します。
loadjava
ツールを使用して、.jar
ファイルをサーバーにロードします。
サーバーでアプリケーション用のSQLラッパーを作成します。たとえば、前述のMyExample
アプリケーションをサーバー上で実行するには、次の文を実行します。
CREATE OR REPLACE PROCEDURE sqlj_myexample AS LANGUAGE JAVA NAME `MyExample.main(java.lang.String[])';
これで、他のストアド・プロシージャと同様に、sqlj_myexample
を実行できます。
Oracle JDBCドライバはすべて、Oracle SQLおよびPL/SQLとシームレスに通信し、また、SQLJとPL/SQLが相互に運用されることに注意してください。PL/SQLストアド・プロシージャを再作成せずに、SQLJを使用して開始できます。Oracle SQLJには、PL/SQLストアド・プロシージャをコールするための構文が含まれており、SQLJ文に無名PL/SQLブロックを埋め込むこともできます。
Oracle JVMへのコマンドライン・インタフェースは、JDKまたはJREのシェル・コマンドの使用方法と似ています。次のことが可能です。
標準の-classpath
構文を使用して、ロードするクラスの検索場所を示します。
標準の-D
構文を使用して、システム・プロパティを設定します。
このインタフェースは、文字列(VARCHAR2
)引数を取り、この引数をコマンドライン入力として解析するPL/SQLファンクションです。形式が適切であれば、Oracle JVMで指定のJavaメソッドを実行します。これを実行するために、PL/SQLのパッケージDBMS_JAVA
には次のファンクションが用意されています。
runjava
このファンクションは、唯一の引数としてJavaコマンドラインを取り、Oracle JVMでこれを実行します。戻り値は、正常に実行された場合はNULL、それ以外はエラー・メッセージになります。コマンドラインの形式は、JDKのシェル・コマンドと同じです。次のようになります。
[option switches] name_of_class_to_execute [arg1 arg2 ... argn]
オプションのスイッチ-classpath、-D、-Xbootclasspath
および-jar
を使用できます。このファンクションは、現在のコマンドを実行する前に、以前にJavaを使用したときからセッションに残っているJavaの状態をすべて消去するという点で、runjava_in_current_session
ファンクションと異なります。特に、クラスを初期化するときに引数-classpath
および-D
から導出された静的変数の値が、現在のコマンドラインでのこれらのスイッチの値を確実に反映するために必要です。
FUNCTION runjava(cmdline VARCHAR2) RETURN VARCHAR2;
runjava_in_current_session
このファンクションは、現在のコマンドラインを実行する前に、以前にJavaを使用したときからセッションに残っているJavaの状態を消去しない点を除き、runjava
ファンクションと同じです。
FUNCTION runjava_in_current_session(cmdline VARCHAR2) RETURN VARCHAR2;
構文
コマンドラインの構文の形式は次のとおりです。
[-options] classname [arguments...] [-options] -jar jarfile [arguments...]
オプション
-classpath -D -Xbootclasspath -Xbootclasspath/a -Xbootclasspath/p -cp
注意: 最初の形式では、引数を指定したclassnameで特定されるクラスのmainメソッドが実行されます。2番目の形式では、JARで識別されるJARファイルのマニフェストでMain-Class 属性によって特定されるクラスのmainメソッドが実行されます。これは、JDK/JREの構文解釈法と似ています。 |
引数の概要
表3-1は、コマンドライン引数の一覧です。
表3-1 コマンドライン引数の概要
引数 | 説明 |
---|---|
classpath |
ディレクトリ、JARアーカイブおよびZIPアーカイブのコロン(:)で区切られたリスト(Windowsシステムの場合はセミコロンで区切られたリスト)を受け入れて、クラス・ファイルを検索します。通常、 |
D |
既存のJavaセッションの状態がない場合、システム・プロパティの値を設定します。コマンドライン・インタフェースのデフォルトの動作、つまり |
Xbootclasspath |
ディレクトリ、JARアーカイブおよびZIPアーカイブのコロン(:)で区切られたリスト(Windowsシステムの場合はセミコロンで区切られたリスト)を受け入れます。このオプションは、ブートストラップ・クラスおよびリソースの検索パスの設定に使用します。 |
|
ディレクトリ、JARアーカイブおよびZIPアーカイブのコロン(:)で区切られたリスト(Windowsシステムの場合はセミコロンで区切られたリスト)を受け入れます。ブートストラップ・クラスのパスの最後に付加されます。 |
|
ディレクトリ、JARアーカイブおよびZIPアーカイブのコロン(:)で区切られたリスト(Windowsシステムの場合はセミコロンで区切られたリスト)を受け入れます。ブートストラップ・クラスのパスの前に付加されます。 |
|
|
注意: create java system で作成されたシステム・クラスは、-Xbootclasspath オプションを使用して検出されるファイルやフォルダを使用する前に必ず使用されます。 |
Oracle Database 10gでは、以前はサーバー側JavaコードをコールするネイティブなJavaインタフェースとして知られていたクライアント側スタブが導入されました。これは、簡略化されたアプリケーション統合です。クライアント側および中間層のJavaアプリケーションは、PL/SQLラッパーを定義しないでデータベース内のJavaを直接コールできます。クライアント側スタブでは、サーバー側Javaクラスのリフレクション機能が使用されます。
以前のリリースでは、データベース・クライアントからJavaストアド・プロシージャおよびファンクションをコールするには、関連するPL/SQLラッパーをJava Database Connectivity(JDBC)でコールする必要がありました。各ラッパーは、SQLシグネチャおよびJava実装とともに手動で公開する必要がありました。この方法には次のデメリットがあります。
シグネチャで許可されるJava型は、相当する型がSQLにある場合のみでした。
Javaで発行された例外が正しく戻されません。
JPublisherの-java
オプションは、これらのデメリットを回避するための機能を提供します。関連付けられたPL/SQLラッパーに対するJDBCコールの不具合を解決するために、-java
オプションでは、static
Javaメソッドを直接起動するAPIを使用します。この機能は、Webサービスにも役立ちます。
-java
オプションの機能は、-sql
オプションの機能をミラー化したもので、クライアント側Javaクラスを作成して、サーバー側のSQLオブジェクトやPL/SQLパッケージにアクセスするのではなく、クライアント側Javaスタブ・クラスを作成して、サーバー側Javaクラスにアクセスします。クライアント側のスタブ・クラスでは、サーバー側のクラスをミラー化するJPublisherコードが使用され、次の機能が含まれます。
サーバー・クラスのpublic
static
メソッドに対応するメソッド。
2つのコンストラクタ。1つはJDBC接続を取得するコンストラクタ、もう1つはJPublisherのデフォルトの接続コンテキスト・インスタンスを取得するコンストラクタです。
このスタブ・クラスは、実行時に、JDBC接続を使用してインスタンス化されます。スタブ・クラスのメソッドのコールは、結果としてサーバー側クラスの対応するメソッドのコールとなります。これらの公開されたメソッドで使用されるすべてのJava型は、プリミティブ型、またはシリアライズ可能型である必要があります。
図3-1に、static
サーバー側Javaメソッドを直接起動するクライアント側スタブAPIの例を示します。JPublisherでは、スタブ生成が透過的に処理されます。
次のように、-java
オプションを使用してサーバー側Javaクラスを公開できます。
-java=className
次のAPIを使用したoracle.sqlj.checker.JdbcVersion
サーバー側Javaクラスについて考えます。
public class oracle.sqlj.checker.JdbcVersion { ... public java.lang.String toString(); public static java.lang.String to_string(); ... }
例として、サーバーで次のメソッドをコールするとします。
public String oracle.sqlj.checker.JdbcVersion.to_string();
次のコマンドを使用して、JPublisherによりクライアント側の起動用にJdbcVersion
を公開します。
% jpub -sql=HR -java=oracle.sqlj.checker.JdbcVersion:JdbcVersion Client
Enter HR password: password
このコマンドで生成されるクライアント側JavaクラスJdbcVersionClient
には、次のAPIが含まれます。
public class JdbcVersionClient { ... public java.lang.String toString(long _handle); public java.lang.String to_string(); ... }
すべての静的メソッドが、クライアント側のコードに含まれるインスタンス・メソッドにマップされます。サーバー側のクラスに含まれるインスタンス・メソッド(toString()
など)は、追加ハンドルが含まれるメソッドにマップされます。ハンドルは、サーバーのoracle.sqlj.checker.JdbcVersion
のインスタンスを表します。ハンドルは、サーバー側でのインスタンス・メソッドのコールに使用されます。
関連項目: 『Oracle Database JPublisherユーザーズ・ガイド』 |
デフォルトのサービス機能の使用
Oracle Database 11gリリース1(11.1)から、Oracle Databaseクライアントではデフォルトの新しい接続機能が提供されます。Oracle Databaseクライアントをインストールする場合、接続URLにデータベース・サーバーの詳細をすべて指定する必要はありません。特定の状況では、Oracle Database接続アダプタで、データベースがインストールされているコンピュータのホスト名のみが必要になります。
たとえば、JDBC接続URL構文では次のようになります。
jdbc:oracle:driver_type:[username/password]@[//]host_name[:port][:ORCL]
次の指定はオプションになります。
//
はオプションです。
:port
はオプションです。
Oracle Netのデフォルトのリスナー・ポート(1521)が使用されない場合のみ、ポートを指定する必要があります。
:ORCL
またはサービス名はオプションです。
Oracle Databaseクライアントの接続アダプタは、ホストのデフォルト・サービスに接続します。ホストでは、これはlistener.ora
ファイルのORCL
に設定されています。
基本構成を使用したデフォルト・サービスのテスト
次のコードは、デフォルト・サービスが定義されているlistener.ora
ファイルの基本構成を示しています。
例3-1 デフォルト・サービスが定義されたlistener.oraの基本構成
MYLISTENER = (ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcp)(HOST=testserver1)(PORT=1521))) DEFAULT_SERVICE_MYLISTENER=dbjf.app.myserver.com SID_LIST_MYLISTENER = (SID_LIST=(SID_DESC=(SID_NAME=dbjf) (GLOBAL_DBNAME=dbjf.app.myserver.com)(ORACLE_HOME=/test/oracle)) )
listener.ora
ファイルを定義した後、次のコマンドを使用してリスナーを再起動します。
lsnrctl start mylistener
これで、次のURLは、listener.ora
ファイルのこの構成と連携して機能します。
jdbc:oracle:thin:@//testserver1.myserver.com.com
jdbc:oracle:thin:@//testserver1.myserver.com:1521
jdbc:oracle:thin:@testserver1.myserver.com
jdbc:oracle:thin:@testserver1.myserver.com:1521
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=testserver1.myserver.com)(PORT=1521)))
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=testserver1.myserver.com)))
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=testserver1.myserver.com)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=)))
注意: デフォルト・サービスは、Oracle Database 11gリリース1(11.1)以降の機能です。Oracle Database 11gクライアントより以前のバージョンを使用してデータベースに接続する場合、SID を指定する必要があります。 |
サーバーとクライアントで異なる方法で実行するJavaコードを作成する場合があります。通常、このようなJavaコードの作成はお薦めしません。実際には、JDBCおよびSQLJでは、サーバーとクライアントで使用するドライバが異なる場合でも、この問題を回避する移植可能なコードを作成できます。
コードがサーバーで実行されているかどうかを確認する必要がある場合は、次のようにSystem.getProperty()
メソッドを使用します。
System.getProperty ("oracle.jserver.version")
getProperty()メソッドから戻される結果は、次のとおりです。
Oracle Databaseのリリースを表すString
(サーバー上で実行中の場合)。
null
(クライアント上で実行中の場合)。
Oracle JVMの出力先をさらに広範囲にわたって制御するために、SQL文にJava出力を渡すことができます。PL/SQLのパッケージDBMS_JAVA
は次の新しいファンクションを追加することで拡張され、これにより、以前はDBMS_JAVA.SET_OUTPUT
プロシージャでのみ使用可能であった機能が拡張されています。
set_output_to_sql
set_output_to_sql
は、デフォルトのSystem.out
およびSystem.err
への出力ストリームが発生すると、SQL文の実行命令で構成される指定の出力仕様を定義します。この仕様は、現在のセッションの期間内、またはremove_output_to_sql
ファンクションがそのIDでコールされるまで定義されます。Java出力がある場合、仕様で規定されたSQLアクションが実行されます。これを停止するにはdisable_output_to_sql
ファンクションをコールし、開始するにはenable_output_to_sql
ファンクションをコールします。このファンクションの戻り値は、正常に実行された場合はNULL、それ以外はエラー・メッセージになります。
FUNCTION set_output_to_sql (id VARCHAR2, stmt VARCHAR2, bindings VARCHAR2, no_newline_stmt VARCHAR2 default null, no_newline_bindings VARCHAR2 default null, newline_only_stmt VARCHAR2 default null, newline_only_bindings VARCHAR2 default null, maximum_line_segment_length NUMBER default 0, allow_replace NUMBER default 1, from_stdout NUMBER default 1, from_stderr NUMBER default 1, include_newlines NUMBER default 0, eager NUMBER default 0) return VARCHAR2;
表3-2に、set_output_to_sql
ファンクションが取る引数を示します。
表3-2 set_output_to_sqlの引数の概要
引数 | 説明 |
---|---|
id |
仕様の名前。同じセッションで複数の仕様を使用できますが、それぞれに個別のIDが必要です。このIDを使用して、 |
stmt |
Java出力が発生した場合に実行するデフォルトのSQL文。 |
bindings |
セットID、TEXT、LENGTH、LINENO、SEGNO、NLおよびERROUTからのトークンを含む文字列。この文字列は、SQL文
|
no_newline_stmt |
出力が改行で終わらない場合に実行するオプションの代替SQL文。 |
no_newline_bindings |
前述のbindings引数と同じ構文を使用する文字列。 |
newline_only_stmt |
出力が1つの改行の場合に実行するオプションの代替SQL文。 |
newline_only_bindings |
前述のbindings引数と同じ構文を使用する文字列。 |
maximum_line_segment_length |
指定されたSQL文の実行でバインドされる最大文字数。出力シーケンスが長い場合、識別可能なSEGNO値によって個々のコールに分けられます。値0は |
allow_replace |
同じIDの仕様が以前に定義されている場合の動作を制御します。値1は、古い仕様を置き換えます。0は、古い仕様を変更せずにエラー・メッセージを戻します。 |
from_stdout |
|
from_stderr |
|
include_newlines |
改行文字がテキストにバインドされる場合、それらの文字が出力に残るかどうかを制御します。値0は改行が含まれないことを示します。ただし、改行が存在するかどうかは、NLバインディングや |
eager |
改行で終了しない出力により、改行を受け取るたびにSQL文を実行するかどうかを制御するか、または、改行を受け取るまでこのような出力を蓄積します。値0は、終了しない出力が蓄積されることを示します。 |
remove_output_to_sql
remove_output_to_sql
は、set_output_to_sql
で作成された仕様を削除します。このような仕様がない場合は、エラー・メッセージが戻されます。
FUNCTION remove_output_to_sql (id VARCHAR2) return VARCHAR2;
enable_output_to_sql
enable_output_to_sql
は、set_output_to_sql
で作成された後、disable_output_to_sql
で無効化された仕様を再度有効にします。このような仕様がない場合は、エラー・メッセージが戻されます。現在、仕様が無効ではない場合、変更はありません。
FUNCTION enable_output_to_sql (id VARCHAR2) return VARCHAR2;
disable_output_to_sql
disable_output_to_sql
は、set_output_to_sql
で作成された仕様を無効にします。仕様を有効にするには、enable_output_to_sql
をコールします。無効になっている間、仕様で規定されたSQL文は実行されません。このような仕様がない場合は、エラー・メッセージが戻されます。仕様がすでに無効の場合、変更はありません。
FUNCTION disable_output_to_sql (id VARCHAR2) return VARCHAR2;
query_output_to_sql
query_output_to_sql
は、set_output_to_sql
で作成された仕様を説明するメッセージを戻します。このような仕様がない場合は、エラー・メッセージが戻されます。このファンクションにnull
を渡すと、既存のすべての仕様が表示されます。
FUNCTION query_output_to_sql (id VARCHAR2) return VARCHAR2;
Oracle JVMからの出力先を制御するには、自律型JavaセッションにJava出力を渡す方法もあります。これは、ディスク・ファイル、ソケットおよびURLなどの各種ターゲットに出力を伝播する一般的なメカニズムを提供します。ただし、出力を処理するJavaセッションはメイン・セッションとは論理的に異なるため、セッション間でその他の不要な相互作用はない点に注意する必要があります。これを実行するために、PL/SQLのパッケージDBMS_JAVA
には次のファンクションが用意されています。
set_output_to_java
set_output_to_java
は、デフォルトのSystem.out
およびSystem.err
への出力ストリームが発生すると、Javaメソッドを実行する命令を与える指定の出力仕様を定義します。仕様で規定されたJavaメソッドは、セッションの残りの部分とは別のJavaセッションの状態を持つ別のVMコンテキストで実行されます。
FUNCTION set_output_to_java (id VARCHAR2, class_name VARCHAR2, class_schema VARCHAR2, method VARCHAR2, bindings VARCHAR2, no_newline_method VARCHAR2 default null, no_newline_bindings VARCHAR2 default null, newline_only_method VARCHAR2 default null, newline_only_bindings VARCHAR2 default null, maximum_line_segment_length NUMBER default 0, allow_replace NUMBER default 1, from_stdout NUMBER default 1, from_stderr NUMBER default 1, include_newlines NUMBER default 0, eager NUMBER default 0, initialization_statement VARCHAR2 default null, finalization_statement VARCHAR2 default null)return VARCHAR2;
表3-3に、set_output_to_java
メソッドが取る引数を示します。
表3-3 set_output_to_javaの引数の概要
引数 | 説明 |
---|---|
class_name |
1つ以上のメソッドを定義するクラスの名前。 |
class_schema |
クラスが定義されるスキーマ。NULL値は、現行スキーマまたはPUBLICでクラスが定義されることを示します。 |
method |
メソッドの名前。 |
bindings |
メソッドの引数がバインドされる方法を定義する文字列。これは、 |
no_newline_method |
出力が改行で終わらない場合に実行するオプションの代替メソッド。 |
newline_only_method |
出力が1つの改行の場合に実行するオプションの代替メソッド。 |
initialization_statement |
出力を受け取るメソッドを最初に実行する前に、Javaセッションごとに1回実行されるオプションのSQL文。この文は、出力メソッドが実行されるのと同じJava VMコンテキストで実行されます。通常、このような文は、出力を受け取るメソッドが予定どおりに機能するように、別のVMコンテキストで条件を初期化するJavaストアド・プロシージャを実行する際に使用します。たとえば、このようなプロシージャは、出力メソッドによって書き込まれるストリームを開きます。 |
finalization_statement |
出力仕様が削除される直前、またはセッションが終了するときに1回実行されるオプションのSQL文。 |
remove_output_to_java
remove_output_to_java
は、set_output_to_java
で作成された仕様を削除します。このような仕様がない場合、エラー・メッセージが戻されます。
FUNCTION remove_output_to_java (id VARCHAR2) return VARCHAR2;
enable_output_to_java
enable_output_to_java
は、set_output_to_java
で作成された後、disable_output_to_java
で無効化された仕様を再度有効にします。このような仕様がない場合は、エラー・メッセージが戻されます。現在、仕様が無効ではない場合、変更はありません。
FUNCTION enable_output_to_java (id VARCHAR2) return VARCHAR2;
disable_output_to_java
disable_output_to_java
は、set_output_to_java
で作成された仕様を無効にします。仕様は、enable_output_to_java
で再度有効にできます。無効になっている間、仕様で規定されたSQL文は実行されません。このような仕様がない場合は、エラー・メッセージが戻されます。仕様がすでに無効の場合、変更はありません。
FUNCTION disable_output_to_java (id VARCHAR2) return VARCHAR2;
query_output_to_java
query_output_to_java
は、set_output_to_java
で作成された仕様を説明するメッセージを戻します。このような仕様がない場合は、エラー・メッセージが戻されます。このファンクションにnull
を渡すと、既存のすべての仕様が表示されます。
FUNCTION query_output_to_java (id VARCHAR2) return VARCHAR2;
set_output_to_file
set_output_to_file
は、デフォルトのSystem.out
およびSystem.err
に送信された出力ストリームを捕捉し、これを特定のファイルに追加する命令で構成された指定の出力仕様を定義します。これを実装するには、特殊なset_output_to_java
を使用します。引数file_path
は、出力の追加先のファイルのパスを指定します。引数allow_replace、from_stdout
およびfrom_stderr
は、set_output_to_sql
の同じ名前の引数と類似しています。
FUNCTION set_output_to_file (id VARCHAR2, file_path VARCHAR2, allow_replace NUMBER default 1, from_stdout NUMBER default 1, from_stderr NUMBER default 1) return VARCHAR2;
remove_output_to_file
このファンクションは、remove_output_to_java
と似ています。
FUNCTION remove_output_to_file (id VARCHAR2) return VARCHAR2;
enable_output_to_file
このファンクションは、enable_output_to_java
と似ています。
FUNCTION enable_output_to_file (id VARCHAR2) return VARCHAR2;
disable_output_to_file
このファンクションは、disable_output_to_java
と似ています。
FUNCTION disable_output_to_file (id VARCHAR2) return VARCHAR2;
query_output_to_file
このファンクションは、query_output_to_java
と似ています。
FUNCTION query_output_to_file (id VARCHAR2) return VARCHAR2;
次のDBMS_JAVA
ファンクションは、.trc
ファイルにJava出力が表示されるかどうかを制御します。
PROCEDURE enable_output_to_trc;
PROCEDURE disable_output_to_trc;
FUNCTION query_output_to_trc return VARCHAR2;
注意: 11gリリース1 (11.1)以前は、.trc ファイルに表示されるJava出力は変更できませんでした。 |
SQL*Plusテキスト・バッファへの出力のリダイレクト
以前のリリースと同様、DBMS_JAVA
パッケージのプロシージャSET_OUTPUT
を使用して、SQL*Plusテキスト・バッファに出力をリダイレクトできます。
SQL> SET SERVEROUTPUT ON SQL> CALL dbms_java.set_output(2000);
最小(デフォルト)バッファ・サイズは2,000バイトで、最大サイズは1,000,000バイトです。次の例では、バッファ・サイズを5,000バイトに増やしています。
SQL> SET SERVEROUTPUT ON SIZE 5000 SQL> CALL dbms_java.set_output(5000);
出力は、コール終了時に表示されます。
Oracle Database 10gより前のリリースでは、データベース・クライアントからJavaストアド・プロシージャおよびファンクションをコールするには、関連するPL/SQLラッパーをJDBCでコールする必要がありました。各ラッパーは、SQLシグネチャおよびJava実装とともに手動で公開する必要がありました。この方法には次のデメリットがあります。
Javaメソッド用にSQLシグネチャを公開するために、別の手順が必要でした。
シグネチャで許可されるJava型は、相当する型がSQLにある型のみでした。
Javaで発行された例外が正しく戻されませんでした。
1回のデータベース・ラウンドトリップごとに実行できるメソッドの起動が1回のみでした。
これらの問題を解決するために、Oracle Database 11g以降では、static
Javaストアド・プロシージャおよびファンクションの直接コール用に、簡易APIが実装されています。この新機能は一般的なアプリケーションにも役立ちますが、特にWebサービスに役立ちます。
簡易APIのクラスはoracle.jpub.reflect
パッケージに格納されています。このパッケージをクライアント側のコードにインポートします。
次に、API用のJavaインタフェースを示します。
public class Client { public static String getSignature(Class[]); public static Object invoke(Connection, String, String, String, Object[]); public static Object invoke(Connection, String, String, Class[], Object[]); }
例として、サーバーで次のメソッドをコールするとします。
public String oracle.sqlj.checker.JdbcVersion.to_string();
このメソッドは次のようにコールできます。
Connection conn = ...; String serverSqljVersion = (String) Client.invoke(conn, "oracle.sqlj.checker.JdbcVersion","to_string", new Class[]{}, new Object[]{});
Class[]
配列はメソッドのパラメータ・タイプ用で、Object[]
配列はパラメータの値用です。この場合、to_string
にはパラメータがないため、配列は空です。
次の点に注意してください。
任意のシリアル化可能な型(例: int[]
およびString[]
)を引数として渡すことができます。
最適化として、パラメータ値をString
として表すことができます。
String sig = oracle.jpub.reflect.Client.getSignature(new Class[]{}); ... Client.invoke(conn, "oracle.sqlj.checker.JdbcVersion", "to_string",sig, new Object[]{});
このAPIのセマンティクスは、PL/SQLラッパーを使用してストアド・プロシージャまたはファンクションをコールする場合のセマンティクスと次の点で異なります。
引数をOUT
またはIN OUT
に設定することはできません。戻り値はすべてファンクションの結果の一部であることが必要です。
例外が正しく戻されます。
メソッドの起動で実行者権限が使用されます。定義者権限を取得するようにはチューニングされていません。