3.1 Javaメソッドの起動
Javaアプリケーションのタイプによって、クライアントがJavaメソッドをコールする方法が決まります。次の項では、Javaメソッドのコールに使用できる各Java Application Programming Interface(API)について説明します。
3.1.1 PL/SQLラッパーの使用
Javaストアド・プロシージャは、PL/SQLストアド・プロシージャと同じ方法で実行できます。Oracle Databaseでは、通常、JavaはPL/SQLインタフェースを介して起動します。
Javaストアド・プロシージャをコールするには、コール仕様を使用して公開する必要があります。次の例は、String
を戻す簡単なJavaストアド・プロシージャを作成、解決、ロードおよび公開する方法を示しています:
3.1.1.1 JDK 11でのPL/SQLラッパーの使用
Oracle Databaseリリース23c以降では、Javaデータベース・オブジェクト名にモジュール・コンポーネントを含めることもできます。
モジュールのメンバーであるJavaオブジェクトは、次の形式の名前でデータベース・オブジェクトに格納されます:
<module_name>///<class_source_or_resource_name>
Javaデータベース・オブジェクトがモジュールの一部ではない場合、つまり、名前のないモジュールの一部である場合は、以前のデータベース・リリースと同様に<class_source_or_resource_name>の書式になります。名前のclass_source_or_resource
の部分では、以前のデータベース・リリースと同様に、パッケージ・デリミタのピリオド(.
)が、データベース・オブジェクト名ではスラッシュ(/
)に置き換えられます。
名前のモジュール部分では、文字は置換されません。データベース・オブジェクト・クラス名の完全モジュール化された形式は、メソッドが呼び出される最上位クラスの名前として指定します。たとえば、hello.in.there
という名前のモジュールのhello.Hello
という名前のクラスでメソッドworld
をコールするコール仕様は、次のようになります:
CREATE OR REPLACE FUNCTION helloworld RETURN VARCHAR2 AS LANGUAGE JAVA NAME
'hello.in.there///hello.Hello.world () return java.lang.String';
以前のデータベース・リリースの場合と同様に、コールされるストアド・プロシージャのデータベース・オブジェクト名のclass_name
部分で、ピリオド(.
)またはフォワード・スラッシュ(/
)のデリミタが指定されたクラス名は両方とも受け入れられます。引数または戻り値のクラスがモジュールのメンバーである場合でも、コール仕様の引数および戻り値の部分にモジュール名は指定されません。
すべてのJDKおよびOracle JVMシステムのクラスは、それ自体がJDK11のモジュールに含まれています。例外的に、起動されるJavaストアド・プロシージャのクラス名が組込みシステム・クラスのいずれかである場合は、完全モジュール化されたデータベース・オブジェクト名、またはコールされるメソッドのクラス名の部分のみのいずれかを、ストアド・プロシージャの定義に指定できます。
3.1.2 JNIサポートについて
Java Native Interface (JNI)は、Javaネイティブ・メソッドの作成、およびJVMのネイティブ・アプリケーションへの埋込みを行うための標準プログラミング・インタフェースです。JNIの主要目的は、プラットフォーム固有のネイティブ・ライブラリを使用するJavaアプリケーションのバイナリ互換性を提供することです。
ネイティブ・メソッドを使用すると、サーバーのクラッシュ、セキュリティ違反およびデータ破損などの問題が発生する可能性があります。Oracle Databaseでは、JavaアプリケーションにおけるJNIの使用はサポートされていません。JNIを使用する場合、アプリケーションが100パーセントPure Javaではないため、ネイティブ・メソッドをプラットフォーム間で移植する必要があります。
3.1.3 データベースでのJDBCとJavaの併用について
JavaクライアントからJava Database Connectivity (JDBC) APIを使用できます。これらのAPIにより、指定したユーザー名とパスワードを使用してデータベース上でセッションが確立され、データベースに対するSQL問合せが実行されます。すべてのOracle JDBCドライバが、Oracle SQLおよびPL/SQLとシームレスに通信します。
3.1.3.1 JDBCの使用
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操作はあまり採用されていません。
3.1.4 コマンドライン・インタフェースの使用について
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 コマンドライン引数の概要
引数 | 説明 |
---|---|
classpath |
ディレクトリ、JARアーカイブおよびZIPアーカイブのコロン(:)で区切られたリスト(Windowsシステムの場合はセミコロンで区切られたリスト)を受け入れて、クラス・ファイルを検索します。通常、 |
D |
既存のJavaセッションの状態がない場合、システム・プロパティの値を設定します。コマンドライン・インタフェースのデフォルトの動作、つまり |
Xbootclasspath |
ディレクトリ、JARアーカイブおよびZIPアーカイブのコロン(:)で区切られたリスト(Windowsシステムの場合はセミコロンで区切られたリスト)を受け入れます。このオプションは、ブートストラップ・クラスおよびリソースの検索パスの設定に使用します。 |
|
ディレクトリ、JARアーカイブおよびZIPアーカイブのコロン(:)で区切られたリスト(Windowsシステムの場合はセミコロンで区切られたリスト)を受け入れます。ブートストラップ・クラスのパスの最後に付加されます。 |
|
ディレクトリ、JARアーカイブおよびZIPアーカイブのコロン(:)で区切られたリスト(Windowsシステムの場合はセミコロンで区切られたリスト)を受け入れます。ブートストラップ・クラスのパスの前に付加されます。 |
|
|
ノート:
create java system
で作成されたシステム・クラスは、-Xbootclasspath
オプションを使用して検出されるファイルやフォルダを使用する前に必ず使用されます。
関連トピック
3.1.5 クライアント側スタブの使用の概要
Oracle Database 10gでは、以前はサーバー側JavaコードをコールするネイティブなJavaインタフェースとして知られていたクライアント側スタブが導入されました。これは、簡略化されたアプリケーション統合です。クライアント側および中間層のJavaアプリケーションは、PL/SQLラッパーを定義しないでデータベース内のJavaを直接コールできます。クライアント側スタブでは、サーバー側Javaクラスのリフレクション機能が使用されます。
以前のリリースでは、データベース・クライアントからJavaストアド・プロシージャおよびファンクションをコールするには、関連するPL/SQLラッパーをJava Database Connectivity(JDBC)でコールする必要がありました。各ラッパーは、SQLシグネチャおよびJava実装とともに手動で公開する必要がありました。この方法には次のデメリットがあります。
-
シグネチャで許可されるJava型は、相当する型がSQLにある場合のみでした。
-
Javaで発行された例外が正しく戻されません。
Oracle Database 12c リリース2 (12.2.0.1)以降、クライアント側スタブを生成するためにOracle JVM Webサービス・コールアウト・ユーティリティを使用できます。
3.1.5.1 デフォルトのサービス機能の使用
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
に設定されています。
3.1.5.2 基本構成を使用したデフォルト・サービスのテスト
次のコード・スニペットは、デフォルト・サービスが定義されている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=)))