Oracle® Database

SQLJ開発者ガイド

11gリリース2(11.2)

B56282-02(原本部品番号:E10590-02)

2013年7月

Oracle Database SQLJ開発者ガイド, 11g リリース2 (11.2)

B56282-02

Copyright © 1999, 2013, Oracle and/or its affiliates.All rights reserved.

原本著者: Tulika Das

原本協力者:  Venkatasubramaniam Iyer、Brian Wright、Janice Nygard

協力者:  Amit Bande、Krishna Mohan、Amoghavarsha Ramappa、Dhilipkumar Gopal、Quan Wang、Angela Barone、Ekkehard Rohwedder、Brian Becker、Alan Thiesen、Lei Tang、Julie Basu、Pierre Dufour、Jerry Schwarz、Risto Lakinen、Cheuk Chau、Vishu Krishnamurthy、Rafiul Ahad、Jack Melnick、Tim Smith、Thomas Pfaeffle、Tom Portfolio、Ellen Barnes、Susan Kraft、Sheryl Maring

このソフトウェアおよび関連ドキュメントの使用と開示は、ライセンス契約の制約条件に従うものとし、知的財産に関する法律により保護されています。ライセンス契約で明示的に許諾されている場合もしくは法律によって認められている場合を除き、形式、手段に関係なく、いかなる部分も使用、複写、複製、翻訳、放送、修正、ライセンス供与、送信、配布、発表、実行、公開または表示することはできません。このソフトウェアのリバース・エンジニアリング、逆アセンブル、逆コンパイルは互換性のために法律によって規定されている場合を除き、禁止されています。

ここに記載された情報は予告なしに変更される場合があります。また、誤りが無いことの保証はいたしかねます。誤りを見つけた場合は、オラクル社までご連絡ください。

このソフトウェアまたは関連ドキュメントを、米国政府機関もしくは米国政府機関に代わってこのソフトウェアまたは関連ドキュメントをライセンスされた者に提供する場合は、次の通知が適用されます。

U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, delivered to U.S. Government end users are "commercial computer software" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations.As such, use, duplication, disclosure, modification, and adaptation of the programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, shall be subject to license terms and license restrictions applicable to the programs.No other rights are granted to the U.S. Government.

このソフトウェアもしくはハードウェアは様々な情報管理アプリケーションでの一般的な使用のために開発されたものです。このソフトウェアもしくはハードウェアは、危険が伴うアプリケーション(人的傷害を発生させる可能性があるアプリケーションを含む)への用途を目的として開発されていません。このソフトウェアもしくはハードウェアを危険が伴うアプリケーションで使用する際、安全に使用するために、適切な安全装置、バックアップ、冗長性(redundancy)、その他の対策を講じることは使用者の責任となります。このソフトウェアもしくはハードウェアを危険が伴うアプリケーションで使用したことに起因して損害が発生しても、オラクル社およびその関連会社は一切の責任を負いかねます。

OracleおよびJavaはOracle Corporationおよびその関連企業の登録商標です。その他の名称は、それぞれの所有者の商標または登録商標です。

Intel、Intel Xeonは、Intel Corporationの商標または登録商標です。すべてのSPARCの商標はライセンスをもとに使用し、SPARC International, Inc.の商標または登録商標です。AMD、Opteron、AMDロゴ、AMD Opteronロゴは、Advanced Micro Devices, Inc.の商標または登録商標です。UNIXは、The Open Groupの登録商標です。

このソフトウェアまたはハードウェア、そしてドキュメントは、第三者のコンテンツ、製品、サービスへのアクセス、あるいはそれらに関する情報を提供することがあります。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスに関して一切の責任を負わず、いかなる保証もいたしません。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスへのアクセスまたは使用によって損失、費用、あるいは損害が発生しても一切の責任を負いかねます。

目次

例一覧

図一覧

表一覧

タイトルおよび著作権情報

はじめに

- 対象読者

- ドキュメントのアクセシビリティについて

- 関連ドキュメント

- 表記規則

1 SQLJの基本事項

- 前提と要件

- 環境に対する前提

- Oracle SQLJ実装を使用するための要件

- SQLJ環境

- 環境に関する考慮事項

- SQLJの下位互換性

- インストールおよび設定の確認

- SQLJおよびデモ用アプリケーションの可用性の確認

- インストール先のディレクトリとファイルの確認

- PATHとCLASSPATHの設定

- sqljutlパッケージのインストールの確認

- 設定のテスト

- ランタイム接続の設定

- データベース検証用の表の作成

- JDBCドライバの検証

- SQLJトランスレータとランタイムの検証

- SQLJトランスレータからデータベースへの接続の検証

2 SQLJについて

- SQLJの概要

- SQLJコンポーネントの概要

- SQLJトランスレータ

- SQLJランタイム

- SQLJ規格に準拠したOracle拡張型の概要

- SQLJの拡張型

- SQLJの拡張機能

- 基本的な変換処理とランタイム処理

- SQLJ変換処理

- トランスレータ入出力の概要

- トランスレータへの入力

- トランスレータの出力

- ファイルの出力先

- SQLJランタイム処理

- SQLJのサンプル・コード

- SQLJバージョンのサンプル・コード

- JDBCバージョンのサンプル・コード

- 他のデプロイメント例

- アプレットでのSQLJの実行

- 開発およびデプロイメントに関する一般的な考慮事項

- エンド・ユーザーのための一般的な考慮事項

- Java環境およびJavaプラグイン

- サーバー側SQLJの概要

- 他の開発環境

- SQLJグローバリゼーション・サポート

- Oracle JDeveloper 10g などのIDEでのSQLJの使用

- Windowsに関する注意事項

3 プログラミング上の主な考慮事項

- JDBCドライバの選択

- Oracle JDBCドライバの概要

- 変換用ドライバの選択

- 実行時に使用するドライバの選択および登録

- 接続の際の考慮事項

- DefaultContextを使用した単一接続または複数接続

- 接続の終了

- 宣言済の接続コンテキスト・クラスを使用した複数接続

- Oracleクラスについて

- DefaultContextクラスについて

- 変換時の接続

- カスタマイズ時の接続

- NULLの処理

- NULL処理用のラッパー・クラス

- NULL処理の例

- 例外処理の基本

- SQLJおよびJDBCの例外処理要件

- 例外の処理

- SQLExceptionサブクラスの使用方法

- 基本的なトランザクション制御

- トランザクションの概要

- 自動コミットと手動コミットとの違い

- 接続を定義する際の自動コミットの指定

- 既存の接続の自動コミットに対する変更

- 手動COMMITまたはROLLBACKの使用方法

- イテレータおよび結果セットに対するコミットおよびロールバックの影響

- セーブポイントの使用

- 概要: 簡単なSQLJコード

- Oracle固有コード生成(プロファイルなし)

- Oracle固有コード生成でのコード上の考慮事項と制限事項

- Oracle固有コード生成時のSQLJ使用方法の変更

- Oracle固有コード生成でのサーバー側の考慮事項

- Oracle固有コード生成のメリットとデメリット

- ISO標準コード生成

- ISO標準コード生成用環境の要件

- SQLJトランスレータとSQLJランタイム

- SQLJプロファイル

- プロファイルの概要

- バイナリ移植性

- SQLJ変換処理

- トランスレータ入出力の概要

- トランスレータへの入力

- トランスレータの出力

- ファイルの出力先

- SQLJランタイム処理

- デプロイメント例

- Oracle固有コード生成とISO標準コード生成との違い

- ネーミングの要件および制限事項

- Javaのネームスペース: ローカル変数およびクラスのネーミングに関する制限事項

- SQLJのネームスペース

- SQLのネームスペース

- ファイル名の要件と制限

- 中間層のSQLJに関する考慮事項

4 基本的な言語機能

- SQLJ宣言の概要

- SQLJ宣言の規則

- イテレータ宣言

- 接続コンテキスト宣言

- IMPLEMENTS句宣言

- WITH句宣言

- 標準WITH句の使用例

- Oracle固有のWITH句の使用例

- returnabilityの例

- SQLJ実行文の概要

- SQLJ実行文の規則

- SQLJ句

- 接続コンテキスト・インスタンスと実行コンテキスト・インスタンスの指定

- 実行文の例

- 実行文のPL/SQLブロック

- Javaホスト式、コンテキスト式および結果式

- ホスト式の概要

- 基本的なホスト式の構文

- ホスト式の例

- 結果式とコンテキスト式の概要

- Java式の実行時評価

- Java式の実行時評価の例(ISOコード生成)

- ホスト式の制限事項

- 単一行の問合せ結果: SELECT INTO文

- SELECT INTO構文

- SELECT INTO文の例

- SELECTリストにホスト式を使用する例

- SELECT INTOエラー状態

- 複数行の問合せ結果: SQLJイテレータ

- イテレータの概念

- 強い型指定のイテレータの概要

- 弱い型指定のイテレータの概要

- イテレータの使用手順

- 名前付きイテレータ、位置イテレータおよび結果セット・イテレータ

- 名前付きイテレータの使用

- 位置イテレータの使用

- ホスト変数としてのイテレータおよび結果セットの使用

- イテレータ列としてのイテレータおよび結果セットの使用

- 代入文(SET)

- ストアド・プロシージャおよびストアド・ファンクションのコール

- ストアド・プロシージャのコール

- ストアド・ファンクションのコール

- ストアド・ファンクションの戻り値としてのイテレータおよび結果セットの使用

5 型のサポート

- ホスト式での型サポート

- サポートされている型の概要

- JDBC 2.0でサポートされている型と要件

- PL/SQLのBOOLEAN型、RECORD型およびTABLE型の使用

- ストリームのサポート

- SQLJストリームの一般的な使用方法

- ストリームをサポートするクラスの主な特長

- データ送信時のSQLJストリームの使用

- ストリームへのデータの取出し: 注意

- データ取得時のSQLJストリームの使用

- ストリーム・クラスのメソッド

- ストリーム・データの取出しおよび処理例

- 出力パラメータおよびファンクションの戻り値としてのSQLJストリーム・オブジェクト

- JDBC 2.0 LOB型とOracle拡張型のサポート

- パッケージoracle.sql

- BLOB、CLOBおよびBFILEのサポート

- Oracle ROWIDのサポート

- OracleのREF CURSOR型のサポート

- その他のOracle Database 11g データ型のサポート

- BigDecimalのサポート強化

6 オブジェクト、コレクションおよびOPAQUE型

- Oracleのオブジェクトとコレクションについて

- オブジェクトとコレクションの概要

- Oracleオブジェクトの基本概念

- Oracleコレクションの基本概念

- オブジェクトとコレクションのデータ型

- カスタムJavaクラス

- カスタムJavaクラスのインタフェース指定

- オブジェクト・メソッドでのカスタムJavaクラスのサポート

- カスタムJavaクラスの要件

- カスタムJavaクラスのコンパイル

- カスタム・データの読込みと書込み

- ORAData実装のその他の使用例

- ユーザー定義データ型

- JPublisherとカスタムJavaクラスの作成

- JPublisherで生成される内容

- カスタムJavaクラスの生成

- JPublisherのINPUTファイルおよびプロパティ・ファイル

- カスタムJavaクラスの作成およびメンバー名の指定

- JPublisherで生成されるラッパー・メソッド

- JPublisherのカスタムJavaクラスの例

- JPublisher生成クラスの拡張

- SQLJ実行文の強い型指定のオブジェクトと参照

- オブジェクトとオブジェクト参照のイテレータ列への取出し

- オブジェクトの更新

- 各オブジェクト属性から作成したオブジェクトの挿入

- オブジェクト参照の更新

- SQLJ実行文の強い型指定のコレクション

- ネストした表へのアクセス: TABLE構文とCURSOR構文

- ネストした表を含む行の挿入

- ホスト式へのネストした表の取出し

- TABLE構文によるネストした表の操作

- ネスト・イテレータによるネストした表からのデータの選択

- ホスト式へのVARRAYの取出し

- VARRAY行への挿入

- シリアライズされたJavaオブジェクト

- RAWおよびBLOB列に対するJavaクラスのシリアライズ

- SerializableDatum: ORADataの実装

- SQLJアプリケーションのSerializableDatum

- SerializableDatum(クラス全体)

- 弱い型指定のオブジェクト、参照およびコレクション

- 弱い型指定のオブジェクト、参照およびコレクションのサポート

- 弱い型指定のオブジェクト、参照およびコレクションの使用制限

- Oracle OPAQUE型

7 高度な言語機能

- 接続コンテキスト

- 接続コンテキストの概要

- 接続コンテキストのロジスティクス

- 接続コンテキスト・クラスの宣言と使用方法の補足

- 複数の接続コンテキストの例

- 接続コンテキスト・クラスの実装と機能

- 接続コンテキスト宣言でのIMPLEMENTS句の使用

- 接続コンテキストのセマンティクス・チェック

- 標準データ・ソースのサポート

- SQLJ固有のデータ・ソース

- JavaServer Pages用のSQLJ固有の接続JavaBeans

- グローバル・トランザクションのSQLJサポート

- 実行コンテキスト

- 実行コンテキストと接続コンテキストとの関係

- 実行コンテキスト・インスタンスの作成と指定

- 実行コンテキストの同期

- 実行コンテキストのメソッド

- 状態メソッド

- 制御メソッド

- 取消しメソッド

- バッチ更新メソッド

- セーブポイント・メソッド

- クローズ・メソッド

- 例: ExecutionContextメソッドの使用

- 実行コンテキストとマルチスレッドの関係

- SQLJでのマルチスレッド

- イテレータ・クラスの実装と拡張機能

- イテレータ・クラスの実装と機能

- イテレータ宣言でのIMPLEMENTS句の使用

- イテレータ・クラスの拡張のサポート

- 結果セット・イテレータ

- スクロール可能なイテレータ

- 詳細なトランザクション制御

- SET TRANSACTION構文

- アクセス・モードの設定

- 分離レベルの設定

- JDBC接続クラスのメソッドの使用

- SQLJとJDBCの連係動作

- SQLJ接続コンテキストとJDBC接続の連係動作

- SQLJイテレータとJDBC結果セットの連係動作

- 動的SQLのサポート

- メタ・バインド式

- SQLJ動的SQLの例

- 実行計画の修正

8 トランスレータのコマンドラインとオプション

- トランスレータのコマンドラインとプロパティ・ファイル

- SQLJのオプション、フラグおよび接頭辞

- コマンドラインの構文と処理

- プロパティ・ファイルによるオプション設定

- 環境変数SQLJ_OPTIONSによるオプションの設定

- オプション設定の優先順位

- 基本的なトランスレータ・オプション

- 基本的なコマンドライン専用オプション

- 出力ファイルとディレクトリのオプション

- 接続オプション

- レポートと行マッピングのオプション

- DMSのオプション

- コード生成、最適化およびCHAR比較のオプション

- 高度なトランスレータ・オプション

- オプション設定を他の実行可能プログラムに渡す接頭辞

- 特殊処理のフラグ

- セマンティクス・チェックとオフライン解析のオプション

- トランスレータによる代替環境のサポートとオプション

- Javaおよびコンパイラのオプション

- カスタマイズのオプション

9 トランスレータとランタイムの検証

- トランスレータの内部操作

- JavaとSQLJのコード解析と構文チェック

- SQLのセマンティクス・チェックとオフライン解析

- コードの生成

- Javaコンパイル

- プロファイルのカスタマイズ(ISOコード生成の場合)

- トランスレータのエラー、メッセージおよび終了コード

- トランスレータのエラー、警告および情報メッセージ

- トランスレータのステータス・メッセージ

- トランスレータの終了コード

- SQLJランタイム

- SQLJランタイム・パッケージ

- ランタイム・エラーの分類

- トランスレータおよびランタイムでのグローバリゼーション・サポート

- 文字エンコーディングと言語サポート

- SQLJおよびJavaの文字エンコーディングと言語サポートの設定

- SQLJ拡張グローバリゼーション・サポート

- SQLJ外部でのグローバリゼーション・サポート用の操作

10 パフォーマンスとデバッグ

- パフォーマンス強化の機能

- 行プリフェッチ

- 文のキャッシング

- バッチ更新機能

- 列の定義

- パラメータ・サイズの定義

- SQLJのデバッグ機能

- デバッグ用のSQLJ -linemapフラグ

- サーバー側のdebugオプション

- AuditorInstaller専用カスタマイザの概要

- Oracle10g JDeveloperでの開発とデバッグの概要

- Oracle Performance MonitoringのSQLJサポート

- SQLJ DMSサポートの概要

- DMS用のSQLJコマンドライン・オプションの概要

- DMS用のSQLJランタイム・コマンドおよびプロパティ・ファイル設定

- SQLJ DMSセンサーとメトリック

- SQLJ DMSの例

11 サーバー側SQLJ

- サーバー側SQLJの概要

- サーバーで使用するSQLJコードの作成

- サーバー側でのデータベース接続

- サーバー側でのコーディングの注意事項

- サーバーのデフォルトの出力デバイス

- サーバー側での名前解決

- SQL名とJava名

- クライアント側でのSQLJソースの変換とコンポーネントのロード

- クラスおよびリソースのサーバーへのロード

- ロードされたクラスとリソース・スキーマ・オブジェクトの名前付け

- クラス・ファイルとリソース・ファイルをロードした後のアプリケーションの公開

- サーバー側でのクライアント・アプリケーションの実行の概要

- SQLJソースのロードとサーバーでの変換

- SQLJソース・コードのサーバーへのロード

- サーバー側の埋込みトランスレータでサポートされるオプション

- ロードされたソース、生成されたクラスおよびリソース・スキーマ・オブジェクトの名前付け

- サーバー側埋込みトランスレータからのエラー出力

- ソース・ファイルをロードした後の、アプリケーションの公開

- Javaスキーマ・オブジェクトの削除

- サーバー側のその他の考慮事項

- サーバーでのJavaマルチスレッド

- サーバーでの再帰的SQLJコール

- サーバーでのコードの実行状況の確認

A カスタマイズおよび専用カスタマイザ

- プロファイルについて

- コード生成時のプロファイルの生成

- プロファイル・エントリの例

- SQLJ実行文

- 対応するSQLJプロファイル・エントリ

- プロファイルのカスタマイズについて

- カスタマイザ・ハーネスおよびカスタマイザの概要

- カスタマイズ処理の手順

- プロファイルのカスタマイズと登録

- カスタマイズ時のエラー・メッセージとステータス・メッセージ

- カスタマイズされたプロファイルの実行時の機能

- カスタマイズ・オプションとカスタマイザの選択

- カスタマイザ・ハーネスのオプションの概要

- カスタマイザ・ハーネスのオプションの構文

- カスタマイザ・ハーネスでサポートされているオプション

- カスタマイザ・ハーネスの一般オプション

- プロファイル・バックアップ・オプション(backup)

- カスタマイズ接続コンテキスト・オプション(context)

- カスタマイザ・オプション(customizer)

- カスタマイズ用JARファイルのダイジェスト・オプション(digests)

- カスタマイズ用ヘルプ・オプション(help)

- カスタマイズ用の詳細オプション(verbose)

- カスタマイザ・ハーネスの接続用オプション

- カスタマイズ用ユーザー・オプション(user)

- カスタマイズ用パスワード・オプション(password)

- カスタマイズ用URL・オプション(url)

- カスタマイズ用JDBCドライバ・オプション(driver)

- 専用のカスタマイザの起動に使用するカスタマイザ・ハーネスのオプション

- 専用カスタマイザ: プロファイル・デバッグ・オプション(debug)

- 専用カスタマイザ: プロファイル出力オプション(print)

- 専用カスタマイザ: プロファイルのセマンティクス・チェック用オプション(verify)

- カスタマイザ固有のオプションの概要

- Oracleカスタマイザのオプション

- Oracleカスタマイザでサポートされているオプション

- Oracleカスタマイザのバージョン互換性オプション(compat)

- Oracleカスタマイザの強制オプション(force)

- Oracleカスタマイザの列定義オプション(optcols)

- Oracleカスタマイザのパラメータ定義オプション(optparams)

- Oracleカスタマイザ用パラメータのデフォルト・サイズ・オプション(optparamdefaults)

- Oracleカスタマイザによる空白埋めを考慮したCHAR比較(fixedchar)

- OracleカスタマイザのSQL表示オプション(showSQL)

- Oracleカスタマイザ用の文のキャッシュ・サイズ・オプション(stmtcache)

- Oracleカスタマイザのサマリー・オプション(summary)

- 他のカスタマイザ用のオプション

- プロファイルのカスタマイズ用のSQLJトランスレータのオプション

- プロファイルのJARファイル

- JARファイルの要件

- JARファイルのロジスティクス

- プロファイルのセマンティクス・チェック用のSQLCheckerCustomizer

- カスタマイザ・ハーネスのverifyオプションによるSQLCheckerCustomizerの起動

- SQLCheckerCustomizerオプション

- SQLCheckerCustomizerセマンティクス・チェッカのオプション(checker)

- SQLCheckerCustomizerの警告オプション(warn)

- デバッグ用のAuditorInstallerカスタマイザ

- オーディタとコード・レイヤーの概要

- カスタマイザ・ハーネスの-debugオプションによるAuditorInstallerの起動

- AuditorInstallerのランタイム出力

- AuditorInstallerオプション

- AuditorInstallerのdepthオプション(depth)

- AuditorInstallerのlog_fileオプション(log)

- AuditorInstallerのprefixオプション(prefix)

- AuditorInstallerの戻り引数オプション(showReturns)

- AuditorInstallerのスレッド名オプション(showThreads)

- AuditorInstallerのuninstallオプション(uninstall)

- 完全なコマンドラインの例

索引

例一覧

- 5-1 名前付きイテレータのCharacterStream列へのLONGデータの格納

- 5-2 位置イテレータのBinaryStream列へのLONG RAWの格納

- 5-3 BFILEでのoracle.sql.BFILEファイル処理メソッドの使用

- 5-4 BFILEでのDBMS_LOBファイル処理ルーチンの使用

- 5-5 CLOBでのoracle.sql.CLOB読取りメソッドの使用

- 5-6 CLOBでのDBMS_LOB読取りルーチンの使用

- 5-7 BLOBでのoracle.sql.BLOB書込みルーチンの使用

- 5-8 BLOBでのDBMS_LOB書込みルーチンの使用

図一覧

- 2-1 制御フロー

- 7-1 グローバル・トランザクション

表一覧

- 4-1 SQLJステートメント句

- 4-2 SQLJ代入句

- 5-1 ホスト式でサポートされている型の対応

- 5-2 Oracle拡張型とJDBC 2.0型との相関関係

- 5-3 for_updateオプションの値および対応するSQL文

- 6-1 JPublisherでのSQL型の分類、サポートされている設定およびデフォルト

- 7-1 アウトラインを生成するオプションおよび値

- 8-1 SQLJトランスレータのオプション

- 8-2 SQLJによるjavacオプションのサポート

- 8-3 SQLJの警告のテストとフラグ

- 8-4 OracleCheckerで選択されるOracleオンライン・セマンティクス・チェッカ

- 8-5 OracleCheckerで選択されるOracleオフライン・セマンティクス・チェッカ

- 8-6 機能の比較: オフライン解析とオンライン・セマンティクス・チェック

- 9-1 生成されたコールの動作、ISO標準とOracle固有の比較

- 9-2 SQLJトランスレータのエラー・メッセージの分類

- 9-3 JDBC型およびSQLJ型とグローバリゼーション型

はじめに

この章では、『Oracle Database SQLJ開発者ガイド』の概要、対象読者および表記規則について説明します。関連するOracleドキュメントのリストも提供します。

この章の構成は、次のとおりです。

- 対象読者

- ドキュメントのアクセシビリティについて

- 関連ドキュメント

- 表記規則

対象読者

このマニュアルは、SQLJプログラミングに関心のあるすべての読者を対象にしていますが、次の事項に関するいくらかの予備知識があることを前提にしています。

- Java

- SQL

- PL/SQL

- Oracle Database

SQLの一般知識で十分ですが、JDBCおよびOracle固有のSQL機能に関する知識もあると役立ちます。

ドキュメントのアクセシビリティについて

Oracleのアクセシビリティについての詳細情報は、Oracle Accessibility ProgramのWebサイト(http://www.oracle.com/pls/topic/lookup?ctx=acc&id=docacc)を参照してください。

Oracle Supportへのアクセス

Oracleサポート・サービスでは、My Oracle Supportを通して電子支援サービスを提供しています。詳細情報は(http://www.oracle.com/pls/topic/lookup?ctx=acc&id=info) か、聴覚に障害のあるお客様は (http://www.oracle.com/pls/topic/lookup?ctx=acc&id=trs)を参照してください。

関連ドキュメント

Oracle Java Platformグループでは、次のOracleリソースを入手できます。

- 『Oracle Database Java開発者ガイド』
このマニュアルでは、Oracle Database 11gにおけるJavaの基本概念を導入し、サーバー側の構成と機能に関する一般的な情報を提供します。このマニュアルには、JDBCやSQLJなどの特定の製品ではなく、Oracle Database Java環境全体に関係している情報が記載されています。

Oracle Databaseで直接実行されるプログラムである、Javaストアド・プロシージャについても説明しています。ストアド・プロシージャを使用すると、Java開発者はビジネス・ロジックをサーバー・レベルで実装できるため、アプリケーションのパフォーマンス、スケーラビリティおよびセキュリティが向上します。

- 『Oracle Database JDBC開発者ガイドおよびリファレンス』
このマニュアルでは、JDBC標準のOracle実装のプログラミング構文および機能について説明しています。Oracle JDBCドライバの概要、JDBC 1.22、2.0、3.0および4.0機能のOracleの実装の詳細、Oracle JDBCの型の拡張とパフォーマンスの拡張の説明が記載されています。

- 『Oracle Database JPublisherユーザーズ・ガイド』
このマニュアルでは、Oracle JPublisherユーティリティを使用して、ユーザー定義のSQL型またはPL/SQLパッケージをJavaクラスに変換する方法を説明しています。オブジェクト型、VARRAY型、ネスト表型、オブジェクト参照型またはPL/SQLパッケージを使用するSQLJまたはJDBCアプリケーションを開発している場合、JPublisherでそれらにマップするカスタムJavaクラスを生成することができます。

次のドキュメントは、Oracle Server Technologiesグループから利用できます。

- 『Oracle XML DB開発者ガイド』

- 『Oracle XML Developer's Kitプログラマーズ・ガイド』

- 『Oracle Database XML Java API Reference』

- 『Oracle Databaseアドバンスト・アプリケーション開発者ガイド』

- 『Oracle Database SecureFilesおよびラージ・オブジェクト開発者ガイド』

- 『Oracle Databaseオブジェクト・リレーショナル開発者ガイド』

- 『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』

- 『Oracle Database PL/SQL言語リファレンス』

- 『Oracle Database SQL言語リファレンス』

- 『Oracle Database Net Services管理者ガイド』

- 『Oracle Database Advanced Security管理者ガイド』

- 『Oracle Databaseグローバリゼーション・サポート・ガイド』

- 『Oracle Databaseリファレンス』

- 『Oracle Databaseサンプル・スキーマ』

注意:
Oracleエラー・メッセージ・マニュアルは、HTML形式でのみ配布されます。Oracle Documentation CDのみを参照可能な場合は、エラー・メッセージを範囲ごとに参照できます。特定の範囲を検索した後、ブラウザの「ページの検索」機能を使用して特定のメッセージを検索できます。インターネットに接続している場合、Oracleオンライン・ドキュメントのエラー・メッセージ検索機能を使用して、特定のエラー・メッセージを検索できます。

SQLJ規格の機能および構文については、次の仕様を参照してください。

「Information Technology - Database Languages - SQL - Part 10: Object Language Bindings (SQL/OLB)」

このマニュアルでは、「ISO SQLJ規格」という用語がこの規格を指すために使用されています。

ISO SQLJ規格は、次のWebサイトでANSIから入手できます。

http://www.ansi.org/

「eStandards Store」をクリックし、「INCITS/ISO/IEC 9075-10」という語を検索します。

Webストアを通じて、ISOからISO SQLJ標準を取得することもできます。

http://www.iso.org/iso/store.htm

前述のリンク先で、「ISO/IEC 9075-10」という語を検索します。

次の場所にSQLJサンプル・アプリケーションがあります。

http://www.oracle.com/technetwork/database/focus-areas/application-development/index-099369.html

表記規則

このセクションでは、このマニュアルの本文およびコード例で使用される表記規則について説明します。この項の内容は次のとおりです。

- 本文の表記規則

- コード例の表記規則

注意:
コマンドラインの例は、システム・プロンプトが「%」のUNIX環境用であることに注意してください。これは単に慣例であり、使用するオペレーティング・システムで適切なように調整できます。

本文の表記規則

本文では、特定の項目が一目でわかるように、次の表記規則を使用します。次の表に、その規則と使用例を示します。

規則

意味

例

イタリック

イタリックは、ドキュメントのタイトルまたは強調、あるいは本文中で定義されている用語を示します。

『Oracle Database概要』
リカバリ・カタログおよびターゲット・データベースが同じディスクに存在しないことを確認します。

固定幅フォントの大文字

固定幅フォントの大文字は、システム指定の要素を示します。このような要素には、パラメータ、権限、データ型、RMANキーワード、SQLキーワード、SQL*Plusまたはユーティリティ・コマンド、パッケージおよびメソッドがあります。また、システム指定の列名、データベース・オブジェクト、データベース構造、ユーザー名およびロールも含まれます。

NUMBER列に対してのみ、この句を指定できます。
BACKUPコマンドを使用して、データベースのバックアップを作成できます。

USER_TABLESデータ・ディクショナリ・ビュー内のTABLE_NAME列を問い合せます。

DBMS_STATS.GENERATE_STATSプロシージャを使用します。

固定幅フォントの小文字

固定幅フォントの小文字は、実行可能ファイル、ファイル名、ディレクトリ名およびユーザーが指定する要素のサンプルを示します。このような要素には、コンピュータ名およびデータベース名、ネット・サービス名および接続識別子があります。また、ユーザーが指定するデータベース・オブジェクトとデータベース構造、列名、パッケージとクラス、ユーザー名とロール、プログラム・ユニットおよびパラメータ値も含まれます。
注意: プログラム要素には、大文字と小文字を組み合せて使用するものもあります。これらの要素は、記載されているとおりに入力してください。

sqlplusと入力してSQL*Plusをオープンします。
パスワードは、orapwdファイルで指定します。

/disk1/oracle/dbsディレクトリのデータ・ファイルおよび制御ファイルをバックアップします。

hr.departments表には、department_id、department_nameおよびlocation_id列があります。

QUERY_REWRITE_ENABLED初期化パラメータをtrueに設定します。

oeユーザーとして接続します。

JRepUtilクラスが次のメソッドを実装します。

固定幅フォントの小文字のイタリック

固定幅フォントの小文字のイタリックは、プレースホルダまたは変数を示します。

parallel_clauseを指定できます。
old_release.SQLを実行します。ここで、old_releaseとは、アップグレード前にインストールしたリリースを示します。

コード例の表記規則

コード例は、SQL、PL/SQL、SQL*Plusまたは他のコマンドライン文の例です。次のように固定幅フォントで表示され、通常のテキストと区別されます。

SELECT username FROM dba_users WHERE username = 'MIGRATE';

次の表に、コード例で使用される表記規則とその使用例を示します。

規則

意味

例

< >

このドキュメントでは、1つ以上のオプション項目を囲むために、丸カッコではなく、山カッコが使用されます。山カッコは入力しないでください。(丸カッコは、SQLJ構文を考慮して使用しません)

DECIMAL (digits < , precision >)

|

縦線は、大カッコまたは中カッコ内の複数の選択項目の区切りに使用します。項目のうちの1つを入力します。縦線は、入力しないでください。

{ENABLE | DISABLE}
[COMPRESS | NOCOMPRESS]

...

水平の省略記号は、次のいずれかを示します。

- 例に直接関連しないコードの一部が省略されている。

- コードの一部を繰り返すことができる。

CREATE TABLE ... AS subquery;

SELECT col1, col2, ... , coln FROM employees;

その他の記号

大カッコ、中カッコ、縦線および省略記号以外の記号は、記載されているとおりに入力する必要があります。

acctbal NUMBER(11,2);
acct CONSTANT NUMBER(4) := 3;

Italics

イタリック体は、特定の値を指定する必要があるプレースホルダや変数を示します。

CONNECT SYSTEM
Enter password: password

DB_NAME = database_name

UPPERCASE

大文字は、システム指定の要素を示します。これらの要素は、ユーザー定義の要素と区別するために大文字で示されます。大カッコ内にないかぎり、表示されているとおりの順序および綴りで入力します。ただし、大/小文字が区別されないため、小文字で入力してもかまいません。

SELECT last_name, employee_id FROM employees;
SELECT * FROM USER_TABLES;

DROP TABLE hr.employees;

lowercase

小文字は、ユーザー指定のプログラム要素を示します。たとえば、表名、列名またはファイル名などです。
注意: プログラム要素には、大文字と小文字を組み合せて使用するものもあります。これらの要素は、記載されているとおりに入力してください。

SELECT last_name, employee_id FROM employees;
sqlplus hr/hr

CREATE USER mjones IDENTIFIED BY ty3MU9;

1 SQLJの基本事項

この章では、Oracle SQLJインストールと設定をテストし、簡単なアプリケーションを実行します。

この章では、次の項目について説明します。

- 前提と要件

- インストールおよび設定の確認

- 設定のテスト

前提と要件

ここでは、SQLJを実行するための環境の前提とシステム要件を、次の項目に従って説明します。

- 環境に対する前提

- Oracle SQLJ実装を使用するための要件

- SQLJ環境

- 環境に関する考慮事項

- SQLJの下位互換性

環境に対する前提

Oracle SQLJ実装を実行するシステムでは、次の内容を前提とします。

- 使用しているシステム上で実行できる標準Java環境があること。通常は、Sun社のJava Development Kit(JDK)を使用しますが、他のJava環境も使用できます。Java(通常はjava)とJavaコンパイラ(通常はjavac)を実行できることを確認してください。
Sun JDK上でSQLJアプリケーションを変換して実行するには、JDK 1.5.xまたはJDK 1.6.xを使用する必要があります。SQLJと同じバージョンのJDBCドライバ(ThinドライバまたはOCI8ドライバ)を使用する必要があります。

関連項目:
「SQLJ環境」

注意:
Java Runtime Environment(JRE)は、Oracle Database 11g にインストールされるものも含めて、単独ではSQLJプログラムを変換できません。ただし、すでに変換およびコンパイルされているSQLJプログラムの実行に関しては、JREで十分です。

- 使用している環境で、JDBCアプリケーションを実行できること。

参照:
JDBCドライバの詳細は、『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

Oracle SQLJ実装を使用するための要件

Oracle SQLJ実装を使用するには、次のものが必要です。

- JDBCドライバを使用してアクセスできるデータベース・システム

- SQLJトランスレータ用クラス・ファイル
トランスレータ関連クラスは、次のファイル内で使用可能です。

ORACLE_HOME/sqlj/lib/translator.jar

注意:
translator.jarの詳細は、「PATHとCLASSPATHの設定」を参照してください。

- SQLJランタイム用クラス・ファイル
ORACLE_HOME/sqlj/lib/runtime12.jar

注意:
Oracle Database 11g リリース1(11.1)以上では、runtime12ee.jarが非推奨になりました。かわりに、runtime12.jarを使用してください。

SQLJ環境

完全な動作環境を確保するために、環境を様々な角度から(SQLJとそのコード生成モード、JDBCおよびJDKなど)考慮する必要があります。

注意:
コード生成は、SQLJの-codegenオプションによって決まります。詳細は、「コードの生成(-codegen)」を参照してください。

Oracle固有コード生成の一般的な環境設定を次に示します。

- SQLJコード生成: -codegen=oracle(デフォルト)

- SQLJ変換ライブラリ: translator.jar

- SQLJランタイム・ライブラリ: runtime12.jar

- JDBCドライバ: Oracle 11g リリース2(11.2)

- JDKバージョン: 1.5.xまたは1.6.x

注意:
異なるバージョンのJDBCに対して実行する場合は、古い方のバージョンに対して変換します。

環境に関する考慮事項

アプリケーションは、コードを変換したバージョン以上のバージョンのJDKに対して実行できます。

注意:
translator.jarの詳細は、「PATHとCLASSPATHの設定」を参照してください。

SQLJの下位互換性

Oracle SQLJ実装の下位互換性に関して、次の点に注意する必要があります。

- 現行より前のリリースのSQLJトランスレータで生成されたコードは、引き続き、現行のランタイム・ライブラリに対して実行およびコンパイルできます。ただし、「環境に関する考慮事項」で説明した相互の互換性の制限事項が適用されます。

- Oracle固有のトランスレータ出力(デフォルトの-codegen=oracle設定で生成されたコード)は、runtime12.jarライブラリを使用して、作成および実行する必要があります。また、次のことに注意してください。

- 前述のコードは、今後のOracle JDBCおよびSQLJ実装で実行できるようになる予定です。

- ただし、前述のコードは、Oracle JDBCドライバおよびOracle SQLJランタイムの以前のリリースでは実行できなくなります。この状況では、コードを再変換する必要があります。

インストールおよび設定の確認

前述の前提と要件が満たされていることを確認した後、SQLJインストールを確認します。次の操作を実行する必要があります。

- SQLJおよびデモ用アプリケーションの可用性の確認

- インストール先のディレクトリとファイルの確認

- PATHとCLASSPATHの設定

- sqljutlパッケージのインストールの確認

SQLJおよびデモ用アプリケーションを利用できるかどうかの確認

SQLJおよびデモ用アプリケーションの可用性に関するリリース固有の注意事項を次に示します。

- SQLJおよびデモ用アプリケーションはOracle Technology Network(OTN)の次の場所で入手できます。
http://www.oracle.com/technetwork/database/focus-areas/application-development/index-099369.html

- Oracle Database 11g の場合、インストール時にSQLJおよびデモ・アプリケーションがインストールされます。

インストール先のディレクトリとファイルの確認

次のディレクトリがインストールされ、その中にファイルが格納されていることを確認します。

JDBCのディレクトリ

システムにインストールする必要のあるJDBCファイルの詳細は、『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

SQLJのディレクトリ

Oracle Database 11g Java環境をインストールすると、sqljディレクトリがORACLE_HOME ディレクトリの下に作成されます。sqljディレクトリには次のサブディレクトリがあります。

- demo(この章で説明するものを含むデモ用アプリケーション)

- lib(SQLJのクラス・ファイルを含む.jarファイル)

これらのディレクトリがすべて作成され、ファイルが格納されたことを確認してください。特に、libは重要なディレクトリです。

ORACLE_HOME/binディレクトリには、SQLJおよびJPublisher実行可能ファイルを含む、すべてのJava製品で使用できるユーティリティが格納されています。

PATHとCLASSPATHの設定

環境変数PATHおよびCLASSPATHが、Oracle SQLJ実装用に設定されていることを確認します。Oracle SQLJ実装の環境変数PATHとCLASSPATHは、次のように設定します。

- PATHの設定
絶対パスを指定せずにsqljスクリプト(SQLJトランスレータを起動するスクリプト)を実行する場合には、環境変数PATHに次のディレクトリが指定してあることを確認してください。

ORACLE_HOME/bin

Microsoft Windowsでは円記号(\)を使用します。ORACLE_HOME には、実際のOracleホーム・ディレクトリを指定します。

- CLASSPATHの設定
環境変数CLASSPATHを変更して、カレント・ディレクトリと次の設定を指定します。

ORACLE_HOME/sqlj/lib/translator.jar

Microsoft Windowsでは円記号(\)を使用します。ORACLE_HOME には、実際のOracleホーム・ディレクトリを指定します。

CLASSPATHに、次のランタイム・ライブラリを指定します。

ORACLE_HOME/sqlj/lib/runtime12.jar

また、CLASSPATHの設定に、次のいずれかのJDBC JARを含める必要があります。

ORACLE_HOME/jdbc/lib/ojdbc5*.jar
ORACLE_HOME/jdbc/lib/ojdbc6*.jar

注意:
SQLJプログラムをJDK 1.5.x環境で変換または実行するにはCLASSPATHにojdbc5.jarを指定し、SQLJプログラムをJDK 1.6.x環境で変換または実行するにはCLASSPATHにojdbc6.jarを指定する必要があります。Oracle Databaseへの接続で実行時に正しいJDBC JARが使用されることを確認してください。

関連項目:
「Oracle SQLJ実装を使用するための要件」

注意:
ランタイム・ライブラリを追加しない場合は、SQLJトランスレータを実行できません。CLASSPATHにランタイム・ライブラリとトランスレータ・ライブラリを指定する必要があります。
SQLJが適切にインストールされていることと、SQLJ、JDBCおよびJavaのバージョン情報を確認するには、次のコマンドを実行します。

% sqlj -version-long

sqljutlパッケージのインストールの確認

sqljutlパッケージは、Oracle Databaseインスタンスのストアド・プロシージャとストアド・ファンクションのオンライン・チェックを行うために使用します。Oracle8i データベース リリース8.1.5以上では、Java対応データベース用のサーバー側Java Virtual Machine(JVM)のインストール中に、SYSスキーマの下に自動的にインストールされます。Java対応でないデータベースを使用している場合は、このパッケージを手動でインストールする必要があります。

sqljutlのインストールを確認するには、SQL*Plusから次のSQLコマンドを実行します。

describe sys.sqljutl

このコマンドを実行すると、パッケージの簡単な説明が出力されます。

パッケージが見つからないというメッセージが表示された場合、またはパッケージの更新版をインストールする場合は、SQL*Plusを使用してsqljutl.sqlスクリプト(Oracle8i データベースの場合はsqljutl8.sql)を実行します。

ORACLE_HOME/sqlj/lib/sqljutl.sql

設定のテスト

データベース、JDBCおよびSQLJセットアップをテストするには、次のソース・ファイルに定義されたデモ用アプリケーションを使用します。

- TestInstallCreateTable.java

- TestInstallJDBC.java

- TestInstallSQLJ.sqlj

- TestInstallSQLJChecker.sqlj

データベース接続の設定に役立つJavaプロパティ・ファイル(connect.properties)もあります。このファイルを編集して、適切なユーザー、パスワードおよびURL値を設定する必要があります。

この項で説明するデモ用アプリケーションは、SQLJインストールによりdemoディレクトリ中に格納されます。

ORACLE_HOME/sqlj/demo

必要に応じて一部のソース・ファイルを変更し、変換やコンパイルを行う必要がある場合があります。Oracle SQLJ実装で提供されるデモ用アプリケーションでは、ユーザー名scottおよびパスワードtigerのOracle Databaseアカウントで表を参照します。このアカウントは、ほとんどのOracle Database環境で使用されています。必要に応じて、scottとtigerに別の値を使用します。

注意:
デモ用アプリケーションを実行するには、demoディレクトリをカレント・ディレクトリにし、このカレント・ディレクトリ(「.」)をCLASSPATHで指定する必要があります。

ここでは、次の項目について説明します。

- ランタイム接続の設定

- データベース検証用の表の作成

- JDBCドライバの検証

- SQLJトランスレータとランタイムの検証

- SQLJトランスレータからデータベースへの接続の検証

関連項目:
「SQLJおよびデモ用アプリケーションの可用性の確認」

ランタイム接続の設定

ここでは、connect.propertiesファイルを変更し、Oracleにランタイム接続を設定します。このファイルはdemoディレクトリにあり、次のように記述されています。

注意:
Oracle Database 11g のJDBC実装では、SIDを使用したデータベースURL接続文字列は非推奨です。次に例を示します(orclがSID)。

jdbc:oracle:thin:@localhost:1521:orcl

警告が生成されますが、致命的なエラーではありません。かわりに、次の例のようにmyserviceなどのデータベース・サービス名を使用することをお薦めします。

jdbc:oracle:thin:@localhost:1521/myservice

データベース・サービス名の詳細は、『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

# Users should uncomment one of the following URLs or add their own.
# (If using Thin, edit as appropriate.)
#sqlj.url=jdbc:oracle:thin:@localhost:1521/myservice
#sqlj.url=jdbc:oracle:oci:@
#
# User name and password here
sqlj.user=scott
sqlj.password=tiger

Oracle JDBCドライバを使用した接続

新しいコードのOracle JDBC OCIドライバでは、接続文字列にociを使用します。ただし、下位互換性のために、oci8も使用できます。したがって、既存のコードを変更する必要はありません。

JDBC Thinドライバを使用する場合は、connect.propertiesのthin URL行のコメントアウトを解除し、Oracle接続に合わせて変更します。URLは、JDBCドライバの設定時に指定したURLを使用してください。

データベース検証用の表の作成

ここでのテストでは、SALESという表を使用します。次のようにTestInstallCreateTableをコンパイルおよび実行します。

% javac TestInstallCreateTable.java
% java TestInstallCreateTable

データベースおよびJDBCドライバが動作しており、connect.propertiesファイル内の接続設定が適切である場合、表が作成されます。

注意:
SALES表がスキーマにすでにあり、それを変更しない場合は、TestInstallCreateTable.javaを編集して表の名前を変更します。または、元の表を削除して、新しい表に置き換えます。

TestInstallCreateTableを使用しない場合は、次のSQL文を使用してSALES表を作成できます。

CREATE TABLE SALES (
ITEM_NUMBER NUMBER,
ITEM_NAME CHAR(30),
SALES_DATE DATE,
COST NUMBER,
SALES_REP_NUMBER NUMBER,
SALES_REP_NAME CHAR(20));

JDBCドライバの検証

Oracle JDBCドライバをさらに詳しく調べる場合は、TestInstallJDBCデモを使用します。接続がconnect.propertiesファイルに正しく設定されていることを確認します。その後、次のようにTestInstallJDBCをコンパイルして実行します。

% javac TestInstallJDBC.java
% java TestInstallJDBC

次のように出力されます。

Hello, JDBC!

SQLJトランスレータとランタイムの検証

TestInstallJDBCと似た機能を持つSQLJアプリケーションのTestInstallSQLJデモを、変換して実行してみます。次のコマンドを使用して、ソースを変換します。

% sqlj TestInstallSQLJ.sqlj

このコマンドではアプリケーションのコンパイルも行われることに注意してください。

UNIX環境では、sqljスクリプトはORACLE_HOME/binにあります(このパスはすでにPATHに指定されているはずです)。Windowsでは、binディレクトリのsqlj.exe実行可能ファイルを使用します。SQLJ translator.jarファイルには、SQLJトランスレータおよびランタイムのクラス・ファイルが含まれています。これはORACLE_HOME/sqlj/libにあり、このパスはすでにCLASSPATHに指定されているはずです。

関連項目:
「PATHとCLASSPATHの設定」

次のコマンドを実行して、アプリケーションを実行します。

% java TestInstallSQLJ

次のように出力されます。

Hello, SQLJ!

SQLJトランスレータからデータベースへの接続の検証

SQLJトランスレータをデータベースに接続できる場合、変換時にSQL操作のオンラインのセマンティクス・チェックを実行できます。SQLJトランスレータはJavaで記述されており、JDBCを使用して必要な情報を指定されたデータベース接続から取得します。オンラインのセマンティクス・チェックの接続パラメータを指定するには、sqljスクリプト・コマンドラインまたはSQLJプロパティ・ファイル(デフォルトでは、sqlj.properties)を使用します。

demoディレクトリで、sqlj.propertiesファイルを編集し、必要に応じてsqlj.password行、sqlj.url行およびsqlj.driver行に対して更新、コメントアウトまたはコメントアウトの解除を行い、データベース接続情報に反映します。詳細は、sqlj.propertiesファイルのコメントを参照してください。

Oracle JDBC OCIドライバを使用する場合の、ドライバ、URLおよびパスワードの設定例を次に示します。

sqlj.url=jdbc:oracle:oci:@
sqlj.driver=oracle.jdbc.OracleDriver
sqlj.password=tiger

オンラインのセマンティクス・チェックは、変換時の接続に対してユーザー名を指定した時点で有効になります。ユーザー名を指定するには、sqlj.propertiesファイルのsqlj.user行のコメントアウトを解除するか、-userコマンドライン・オプションを使用します。user、password、urlおよびdriverオプションは、コマンドラインまたはプロパティ・ファイルで設定できます。

関連項目:
「接続オプション」

オンラインのセマンティクス・チェックをテストするには、次のようにTestInstallSQLJChecker.sqljファイル(demoディレクトリ)を変換します。(または、別のユーザー名を使用してテストする方法もあります。)

% sqlj -user=scott TestInstallSQLJChecker.sqlj

Oracle JDBCドライバを使用している場合は、次のエラー・メッセージが表示されます。

TestInstallSQLJChecker.sqlj:41: Warning: Unable to check SQL query. Error returned by database is: ORA-00904:
invalid column name

TestInstallSQLJChecker.sqljを編集して、行41のエラーを修正します。列名は、ITEM_NAMAEではなくITEM_NAMEである必要があります。このように変更すると、次のコマンドを使用してエラーなしでアプリケーションを変換および実行できます。

% sqlj -user=scott TestInstallSQLJChecker.sqlj
% java  TestInstallSQLJChecker

正常に処理されると、次の行が表示されます。

Hello, SQLJ Checker!

2 SQLJについて

この章では、SQLJの機能と使用例について概要を説明します。内容は次のとおりです。

- SQLJの概要

- SQLJコンポーネントの概要

- SQLJ規格に準拠したOracle拡張型の概要

- 基本的な変換処理とランタイム処理

- SQLJのサンプル・コード

- 他のデプロイメント例

- 他の開発環境

SQLJの概要

SQLJの基本概念を紹介し、Oracle DatabaseアプリケーションにおけるJavaとPL/SQLとの間の相補的な関係を説明します。

SQLJを使用すると、アプリケーション開発者は、Javaの設計思想に基づいてJavaコード中にSQL文を埋め込むことができます。SQLJプログラムとは、SQL文が埋め込まれたJavaプログラムのことで、国際標準化機構(ISO)規格のSQLJ言語リファレンス構文に準拠しています。Oracle SQLJ実装では、ISOのSQLJ規格がサポートされています。この規格には、静的SQL操作のみが含まれます(事前定義済のSQL操作であるため、ユーザーによるアプリケーションの実行中にリアルタイムで変更されることはありません)。Oracle SQLJ実装には、動的SQL操作をサポートする拡張機能もあります(これは事前定義されていないため、操作をリアルタイムに変更できます)。また、SQLJアプリケーション内のJava Database Connectivity(JDBC)コードまたはPL/SQLコードを介して動的SQL操作を使用することも可能です。通常のアプリケーションには、動的SQL操作より静的SQL操作が多く含まれています。

SQLJは、トランスレータとランタイム・コンポーネントで構成され、開発環境にスムーズに統合できます。sqljフロントエンド・ユーティリティを使用すると、トランスレータを実行して、コードの変換、コンパイルおよびカスタマイズを1つの手順で実行できます。変換処理では、埋込みSQL文が、そのSQL文を処理するSQLJランタイムのコールに置き換えられます。ISO SQLJ規格では、このための手段として、通常、JDBCドライバのコールが使用されます(必須ではありません)。Oracle Databaseにアクセスするには、通常、Oracle JDBCドライバを使用します。SQLJアプリケーションを実行すると、SQL操作を処理できるようにSQLJランタイムが起動します。

SQLJトランスレータは、Oracleの他のプリコンパイラと概念的には同様であり、SQL構文のチェック、スキーマで使用可能なものに対するSQL操作の検証、およびJava型と対応するデータベース型との互換性のチェックを行うことができます。これによって、ユーザーの実行時にエラーになるのではなく、開発時にエラーを検出できます。トランスレータは次の項目をチェックします。

- 埋込みSQL文の構文をチェックします。

- SQLコンストラクトを、指定されたデータベース・スキーマに対してチェックし、特定のSQLエンティティ・セット内に一貫性があるかどうかを(必要に応じて)確認します。
具体的には、表や列の名前などを検証します。

- JavaとSQL間で変換されるデータのデータ型に互換性があることを確認し、型変換が適切に行われるようにするため、データ型をチェックします。

SQLJ文をJavaコードに直接埋め込むSQLJ方式は、扱いやすく簡潔で、データベース接続を必要とするJavaプログラムの開発費とメンテナンス費を節約できます。

一方、Javaプログラムの場合、JDBCまたはSQLJを使用することにより、PL/SQLストアド・プロシージャおよび無名ブロックのコールが可能となります。特にSQLJでは、SQLJ文の内部からストアド・プロシージャおよびファンクションをコールしたり、SQLJ文中に無名PL/SQLブロック埋込みも可能です。

注意:
SQLJ文内で無名PL/SQLブロックを使用すると、SQLJアプリケーション内で動的SQL操作をサポートできます。ただし、Oracle SQLJ実装には、動的SQL操作を直接サポートする拡張機能があります。

SQLJコンポーネントの概要

この項では、Oracle SQLJ実装の2つの主要なSQLJコンポーネントについて説明します。次の項目について説明します。

- SQLJトランスレータ

- SQLJランタイム

SQLJトランスレータ

このコンポーネントは、SQLJソース・コードの作成後に実行するプリコンパイラです。

トランスレータはPure Javaで書かれており、SQL文をSQLJ実行文に埋め込むためのプログラミング構文をサポートします。SQLJ実行可能文およびSQLJ宣言は、先頭に#sqlトークンが付き、SQLJソース・コード・ファイル内ではJava文と混在できます。SQLJソース・コード・ファイルの拡張子は、必ず.sqljにします。次に、SQLJ文の例を示します。

#sql { INSERT INTO emp (ename, sal) VALUES ('Joe', 43000) };

トランスレータによって.javaファイルが生成されます。

sqljコマンドライン・ユーティリティを使用して、トランスレータを起動できます。コマンドラインで、変換が必要なファイルおよび必要なすべてのSQLJオプション設定を指定します。

関連項目:
第8章「トランスレータのコマンドラインとオプション」

SQLJランタイム

このコンポーネントもPure Javaで書かれており、SQLJアプリケーションを実行するたびに自動的に起動されます。

Oracle JDBCコールは変換されたコードに直接生成されるため、SQLJランタイムの役割は非常に小さくなります。

関連項目:
「SQLJランタイム」

注意:
Oracle Database 10g リリース1(10.1)以上では、Oracle JDBCドライバのみがSQLJでサポートされています。

SQLJ規格に準拠したOracle拡張型の概要

Oracle SQLJ実装では、ISOのSQLJ規格がサポートされています。ISO SQLJ規格の機能を使用するには、Java2 Platform, Enterprise Edition(J2EE)に準拠したJava Development Kit(JDK)1.5.x以上の環境が必要です。SQLJトランスレータでは、ISO SQLJ規格の仕様より広範なSQL構文を使用できます。

注意:
Oracle SQLJ実装はJDK 1.5.xでのみサポートされています。

ISO SQLJ規格は、SQLのSQL-92エントリ・レベル言語に対応していますが、それを超える拡張にも対応しています。Oracle SQLJ実装では、OracleのSQL言語、つまりSQL-92エントリ・レベルのスーパーセットを使用できます。他のデータベースと連携するSQLJプログラムを作成する場合は、他の環境でサポートされない場合があるため、SQL-92エントリ・レベル以外のSQL構文とSQL型の使用を避ける必要があります。

ここでは、次の項目について説明します。

- SQLJの拡張型

- SQLJの拡張機能

関連項目:
Oracle Databaseで提供されるSQLJ拡張機能の詳細は、第5章「型のサポート」、第6章「オブジェクト、コレクションおよびOPAQUE型」を参照してください。

SQLJの拡張型

Oracle SQLJ実装では、次のJava型がSQLJ規格の拡張としてサポートされます。

- oracle.sql.*クラスのインスタンス。SQLデータのラッパーとして使用します。

関連項目:
「JDBC 2.0 LOB型とOracle拡張型のサポート」

- カスタムJavaクラス。通常、JPublisherユーティティで生成され、SQLオブジェクト、オブジェクト参照およびコレクションに対応付けられます。たとえば、oracle.sql.ORADataインタフェースやJDBC標準のjava.sql.SQLdataインタフェースを実装するクラスがあります。

注意:
SQLDataインタフェースが標準です。このインタフェースを実装するクラスは、JDBCドライバおよび他のベンダーのデータベースでもサポートされています。

関連項目:
「カスタムJavaクラス」

- ストリームのインスタンス(BinaryStreamおよびCharacterStream)。後者は非推奨のAsciiStreamおよびUnicodeStreamにかわるものです。出力パラメータとして使用します。

関連項目:
「ストリームのサポート」

- イテレータと結果セットのインスタンス。入力または出力パラメータとして使用されます。SQLJ規格では、結果式またはキャスト文での使用のみを規定しています。

関連項目:
「ホスト変数としてのイテレータおよび結果セットの使用」および「ストアド・ファンクションの戻り値としてのイテレータおよび結果セットの使用」

- Unicode文字の型(NString、NCHAR、NCLOBおよびNcharCharacterStream): NcharCharacterStreamは、非推奨のNcharAsciiStreamおよびNcharUnicodeStreamにかわるものです。

関連項目:
「SQLJ拡張グローバリゼーション・サポート」

これらの拡張要素のいずれかを使用した場合、変換時にOracle固有コード生成またはOracleのカスタマイズが必要になる他、アプリケーション実行時にOracle SQLJランタイムおよびOracle JDBCドライバも必要になります。自作コードが他の環境で使用される場合は、拡張型を使用しないでください。アプリケーションの移植性を確認するには、SQLJの-warn=portableフラグを使用します。

関連項目:
「トランスレータのコマンドラインとオプション」を参照してください。

SQLJの拡張機能

Oracle SQLJ実装では、次の拡張機能もサポートされています。

- Oracle固有コード生成
これによって、JDBCコードが直接生成されます。プログラムの実行中、SQLJランタイム機能の多くは無視されます。

関連項目:
「Oracle固有コード生成(プロファイルなし)」

- SQLJ文中の動的SQL

関連項目:
「動的SQLのサポート」

- 付加的なナビゲーション・メソッドによるスクロール可能な結果セット・イテレータ、および結果セット・イテレータやスクロール可能な結果セット・イテレータからのFETCH構文

関連項目:
「スクロール可能なイテレータ」

- 列定義とパラメータ・サイズ定義の最適化フラグ

関連項目:
「列の定義」、「パラメータ・サイズの定義」および「コード生成、最適化およびCHAR比較のオプション」

- 変更された変換動作のフラグ。識別子によってホスト式をバインドし、WHERE句のCHAR比較で空白埋めを考慮します。

関連項目:
「識別子によるホスト式のバインド(-bind-by-identifier)」および「空白埋めを考慮したCHAR比較(-fixedchar)」

- 接続コンテキストでのSQLJ文のキャッシング

関連項目:
「文のキャッシング」

基本的な変換処理とランタイム処理

SQLJソース・コードには、標準Javaソースと、SQLJクラス宣言、およびSQL文が埋め込まれたSQLJ実行文が混在して含まれています。SQLJソース・ファイルのファイル名拡張子は.sqljです。このファイル名は有効なJava識別子である必要があります。ソース・ファイルでPublicクラスを宣言する場合、ファイル名はこのクラスの名前と一致する必要があります。ソース・ファイルでPublicクラスを宣言しない場合、ファイル名は、最初に定義したクラスの名前と一致させる必要があります。

ここでは、次の項目について説明します。

- SQLJ変換処理

- トランスレータ入出力の概要

- SQLJランタイム処理

SQLJ変換処理

.sqljファイルを記述した後に、SQLJを実行してそのファイルを処理する必要があります。次の例では、PublicクラスFooを持つFoo.sqljソース・ファイルに対して、コマンドライン・オプションを指定しない最も単純な形で、SQLJを開始しています。

% sqlj Foo.sqlj

このコマンドを実行すると、プラットフォームに応じて、フロントエンドのスクリプトまたはユーティリティが実行されます。このスクリプトまたはユーティリティは、コマンドラインを読み込み、Java Virtual Machine(JVM)を起動し、引数をこのJVMに渡します。JVMはSQLJトランスレータを起動し、フロントエンドとして機能します。

図2-1 制御フロー

以降の処理は、次の順に展開されます(各手順でエラーが発生しなかった場合を想定しています)。

1. JVMでSQLJトランスレータを起動します。

2. トランスレータは、.sqljファイル内のSQLJおよびJavaコードを解析し、SQLJ構文が適切かどうかをチェックし、宣言されたSQLデータ型および対応するJavaホスト変数の間の型の不一致がないか探します。ホスト変数は、SQL操作で入力または出力パラメータとして使用されるJavaローカル変数です。

関連項目:
「Javaホスト式、コンテキスト式および結果式」

3. SQLJのオプション設定に従って、トランスレータがオンライン・セマンティクス・チェッカまたはオフライン・パーサー(あるいはその両方)を起動します。これによって、埋込みSQL文やPL/SQL文の構文が検証され、オンライン・チェックの場合はコード内のデータベース要素の使用が該当データベース・スキーマと照合してチェックされます。いずれのオプションも指定されていない場合でも、基本的なレベルのチェックは実行されます。
オンライン・チェックを指定すると、SQLJでは指定したデータベース・スキーマへの接続後に、アプリケーションで使用しているデータベース表、ストアド・プロシージャおよびSQL構文がすべてサポートされているかどうかが検証されます。また、SQLJアプリケーション内のホスト変数の型と対応するデータベース列のデータ型の互換性も検証されます。

4. Oracle固有のSQLJコード生成(デフォルトの-codegen=oracle)の場合は、SQL操作がOracle JDBCコールに直接変換されます。

関連項目:
「Oracle固有コード生成(プロファイルなし)」

生成されたJavaコードは.java出力ファイルに保存されます。次の内容がこのファイルに出力されます。

- .sqljソース・ファイル内のクラス定義とJavaコード。

- SQLJイテレータおよび接続コンテキストの宣言に基づいて生成されたクラス定義。

関連項目:
「SQLJ宣言の概要」

- Oracle JDBCドライバへのコール。埋込みSQL操作のアクションを実装します。

5. JVMがJavaコンパイラを起動します。通常、このコンパイラはSun社のJDKで提供される標準javacです。

6. 手順4で生成されたJavaソース・ファイルがコンパイルされ、Javaの.classファイルが生成されます。これには、定義した各クラス(各SQLJ宣言)に.classファイルが含まれます。

関連項目:
「トランスレータの内部操作」

SQLJの一般的な注意

SQLJアプリケーションを変換および実行する場合は、次の点を考慮してください。

- コマンドラインで、コンパイルされ、型変換が可能でもある既存の.javaファイルを指定することもできます。

関連項目:
「トランスレータのコマンドラインとプロパティ・ファイル」

- アプリケーションの実行時には、コードでOracle固有の機能を使用しない場合にも、Oracle JDBCドライバが必要になります。

トランスレータ入出力の概要

ここでは、SQLJトランスレータへの入力として扱われるもの、出力となるものおよびその出力先について、概要を説明します。ここでは、次の項目について説明します。

- トランスレータへの入力

- トランスレータの出力

- ファイルの出力先

注意:
ここでは、イテレータ・クラスと接続コンテキスト・クラスの宣言について説明します。イテレータはJDBC結果セットに似ていて、接続コンテキストはデータベース接続に使用します。

トランスレータへの入力

SQLJトランスレータは、入力として1つ以上の.sqljソース・ファイルを取り、その指定はコマンドラインで行うことができます。メインの.sqljファイルの名前は、そこで定義されるPublicクラス(ある場合)または定義された最初のクラスに基づきます。

メインの.sqljファイルでクラスMyClassを定義した場合は、ソース・ファイル名を次の名前にします。

MyClass.sqlj

Publicクラスが未定義でも、最初に定義したクラスの名前がMyClassであれば、ソース・ファイル名をこの名前にする必要があります。各Publicクラスは、別々の.sqljファイルに定義する必要があります。SQLJを実行するときは、複数のSQLJオプションをコマンドラインでもプロパティ・ファイルでも指定できます。

関連項目:
「トランスレータのコマンドラインとプロパティ・ファイル」

トランスレータの出力

変換処理では、ソース・コードでSQLJ実行可能文を使用する場合、アプリケーション内の.sqljファイルごとにJavaソース・ファイルが生成されます。

SQLJでは、次のJavaソース・ファイルが生成されます。

- Javaソース・ファイル。.sqljファイルと同じベース名の.javaファイルです。
たとえば、トランスレータによって、MyClassクラスを定義するMyClass.sqljに対応するMyClass.javaが生成されます。出力.javaファイルには、.sqljファイルで宣言したイテレータまたは接続コンテキスト・クラスのクラス定義も含まれています。

コンパイル処理によって、Javaソース・ファイルが複数のクラス・ファイルにコンパイルされます。.sqljソース・ファイルに定義されたクラスごとに、1つの.classファイルが生成されます。SQLJのイテレータまたは接続コンテキストを宣言した場合は、さらに.classファイルが生成されます。また、コード中に内部クラスまたは無名クラスが宣言されていれば、それらの各クラスごとに.classファイルが個別に生成されます。

関連項目:
「SQLJ宣言の概要」

これらの.classファイルには、次の名前が付けられます。

- 定義する各クラスのクラス・ファイル名は、クラス名および.class拡張子から構成されます。たとえば、トランスレータ出力ファイルMyClass.javaは、MyClass.classクラス・ファイルにコンパイルされます。

- トランスレータを実行すると、イテレータ・クラスと接続コンテキスト・クラスに、宣言内容に応じた名前が付けられます。たとえば、イテレータMyIterを宣言すると、コンパイラは対応するMyIter.classクラス・ファイルを生成します。

ファイルの出力先

デフォルトでは、生成された.javaファイルが.sqljファイルと同じディレクトリに出力されます。.javaファイルの出力先を変更するには、SQLJの-dirオプションを使用します。

SQLJのデフォルトの設定では、生成済.classファイルと.serファイルは、生成済.javaファイルと同じディレクトリに出力されます。.classファイルと.serファイルの出力先を変更するには、SQLJの-dオプションを使用します。このオプションの設定値がJavaコンパイラに渡され、.classファイルと.serファイルが同じディレクトリに出力されます。

-dまたは-dirオプションを使用するときは、既存のディレクトリを指定する必要があります。

関連項目:
「出力ファイルとディレクトリのオプション」

SQLJランタイム処理

ここでは、プログラム実行時のランタイム処理について説明します。

デフォルトの-codegen=oracle設定で変換する場合、プログラムの実行時に次のように実行されます。

- Oracle固有のApplication Programming Interface(API)の実行によって、Oracle JDBC文のバッチ処理サポート、作成および終了を確実に実行します。

- Oracle JDBC APIを直接コールして、パラメータおよび結果セットの登録、受渡しを実行します。

関連項目:
「Oracle固有コード生成(プロファイルなし)」

SQLJのサンプル・コード

ここでは、同じサンプル・コードの2つのバージョンを対照比較します(1つはSQLJで記述されたバージョンで、もう1つはJDBCで記述されたバージョンです)。この項の目的は、SQLJとJDBCの間のコード記述要件の違いを示すことです。この項の内容は次のとおりです。

- SQLJバージョンのサンプル・コード

- JDBCバージョンのサンプル・コード

注意:
ここで使用するSQLJ文と機能の詳細は、マニュアルの後の方で説明します。ここで示す例では、SQLJおよびJDBCを比較対照することで一般的な概念を理解できるようになっています。SQLJの概念および機能により習熟した後に、再度この例を参照するのもよいでしょう。

このサンプルでは、次のように2つのメソッドを定義します。getEmployeeAddress()は、従業員番号に基づいて表データを取り出し、その番号を持つ従業員の住所を戻します。updateAddress()は、取り出されたアドレスを受け取ってストアド・プロシージャをコールし、更新された住所をデータベースに戻します。

どちらのバージョンのコードも、次の事項を前提としています。

- SQLスクリプトが実行され、データベース内にスキーマが作成され、表にデータが取り込まれていること。いずれのバージョンのサンプル・コードも、このスクリプトによって生成されたオブジェクトおよび表を参照しています。

- 指定された住所を更新するPL/SQLストアド・ファンクションUPDATE_ADDRESS() が存在すること。

- Connectionオブジェクト(JDBC用)およびデフォルトの接続コンテキスト(SQLJ用)が、コール元によって生成されていること。

- コール元によって、例外処理が行われること。

- updateAddress()メソッドに渡される住所の引数(addr)に、NULL値が許容されていること。

注意:
サンプル・コードのJDBCとSQLJのバージョンは、単なる部分的なサンプルで、単独では実行できません。いずれのサンプルにも、main()メソッドはありません。

SQLJバージョンのサンプル・コード

次は、SQLJバージョンのサンプル・コードです。このコードには、データベースから従業員の住所を取り出し、それを更新し、更新後の住所をデータベースに戻すメソッドが定義されています。

import java.sql.*;

/**
This is what you have to do in SQLJ
**/
public class SimpleDemoSQLJ                                  // line 6
{
//TO DO: make a main that calls this

public Address getEmployeeAddress(int empno)              // line 10
throws SQLException
{
Address addr;                                           // line 13
#sql { SELECT office_addr INTO :addr FROM employees
WHERE empnumber = :empno };
return addr;
}
// line 18
public Address updateAddress(Address addr)
throws SQLException
{
#sql addr = { VALUES(UPDATE_ADDRESS(:addr)) };          // line 22
return addr;
}
}

10行目

getEmployeeAddress()メソッドは、明示的なConnectionオブジェクトを必要としません。SQLJでは、アプリケーションで初期設定されているデフォルトの接続コンテキスト・インスタンスを使用できます。

13から15行目

getEmployeeAddress()メソッドは、従業員番号に基づいて、従業員の住所を取り出します。標準のSQLJ SELECT INTO構文を使用して、getEmployeeAddress()に渡された番号(empno)が従業員番号に一致する場合に、従業員の住所をemployee表から選択します。これには、データを受け取るAddressオブジェクト(addr)を宣言する必要があります。empnoおよびaddr変数が、入力ホスト変数として使用されます。

16行目

getEmployeeAddress()メソッドは、addrオブジェクトを戻り値とします。

19行目

updateAddress()メソッドでも、デフォルトの接続コンテキスト・インスタンスが使用されます。

19から22行目

取り出された住所はupdateAddress()メソッドに渡され、このメソッドからデータベースに渡されます。データベースでその住所が更新され、更新されたデータが戻されます。実際の住所更新処理は、UPDATE_ADDRESS()ストアド・ファンクションによって実行されます。標準のSQLJファンクション・コール構文を使用して、UPDATE_ADDRESS()から戻されたaddr住所オブジェクトを取り出します。

23行目

updateAddress()メソッドは、addrオブジェクトを戻り値とします。

SQLJバージョンのコード固有の特徴

SQLJバージョンのサンプル・コードの次の特徴に注意してください。

- 明示的な接続は不要です。SQLJでは、アプリケーションで初期設定されているデフォルトの接続コンテキストを使用できます。

- データ型のキャストは不要です。

- SQLJでは、_SQL_TYPECODE、_SQL_NAMEまたはファクトリ・オブジェクトの知識は不要です。

- NULL値データの暗黙的な処理は必要です。

- リソースの明示的な管理(たとえば、StatementオブジェクトやResultSetオブジェクトの終了)は不要です。

- SQLJではホスト変数の埋込みが必要です。これに対し、JDBCではパラメータ・マーカーが使用されます。

- 長いSQL文での文字列の連結は不要です。

- 出力パラメータの登録は不要です。

- SQLJ構文はさらに簡略化されています。具体的には、SQLJではSELECT INTO文はサポートされていますが、OBDC形式のエスケープは使用されません。

- 文のキャッシュは、自分で実装する必要はありません。デフォルトで、SQLJでは自動的に#sql文がキャッシュされます。これによって、getEmployeeAddress()およびupdateAddress()を繰り返してコールする場合などのパフォーマンスが改善します。

JDBCバージョンのサンプル・コード

JDBCをよく理解していれば、次のJDBCバージョンのサンプル・コードを確認できます。このコードには、データベースから従業員の住所を取り出し、住所を更新した後、データベースに戻すメソッドが定義されています。

注意:
必要に応じて、TO DOで始まるコメント行にコードを追加すると、このサンプル・コードの有用性が高くなります。

import java.sql.*;
import oracle.jdbc.*;

/**
This is what you have to do in JDBC
**/
public class SimpleDemoJDBC                                  // line 7
{

//TO DO: make a main that calls this

public Address getEmployeeAddress(int empno, Connection conn)
throws SQLException                                     // line 13
{
Address addr;
PreparedStatement pstmt =                               // line 16
conn.prepareStatement("SELECT office_addr FROM employees" +
" WHERE empnumber = ?");
pstmt.setInt(1, empno);
OracleResultSet rs = (OracleResultSet)pstmt.executeQuery();
rs.next();                                              // line 21
//TO DO: what if false (result set contains no data)?
addr = (Address)rs.getORAData(1, Address.getORADataFactory());
//TO DO: what if additional rows?
rs.close();                                             // line 25
pstmt.close();
return addr;                                            // line 27
}
public Address updateAddress(Address addr, Connection conn)
throws SQLException                                     // line 30

{
OracleCallableStatement cstmt = (OracleCallableStatement)
conn.prepareCall("{ ? = call UPDATE_ADDRESS(?) }");   //line 34
cstmt.registerOutParameter(1, Address._SQL_TYPECODE, Address._SQL_NAME);
// line 36
if (addr == null) {
cstmt.setNull(2, Address._SQL_TYPECODE, Address._SQL_NAME);
} else {
cstmt.setORAData(2, addr);
}

cstmt.executeUpdate();                                  // line 43
addr = (Address)cstmt.getORAData(1, Address.getORADataFactory());
cstmt.close();                                          // line 45
return addr;
}
}

他のデプロイメント例

このマニュアルでは、主にクライアント側SQLJアプリケーションについて説明しています。しかし、次のような例においてもSQLJコードを実行すると便利な場合があります。

- アプレットから

- サーバー内で(SQLJトランスレータもサーバーで実行できます)

ここでは、次の項目について説明します。

- アプレットでのSQLJの実行

- サーバー側SQLJの概要

アプレットでのSQLJの実行

SQLJランタイムはPure Javaであるため、アプレットでもアプリケーションでもSQLJソース・コードを使用できます。ただし、いくつかの考慮事項があります。

関連項目:
Oracle JDBCドライバに適用するアプレットに関しては、『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

ここでは、次の項目について説明します。

- 開発およびデプロイメントに関する一般的な考慮事項

- エンド・ユーザーのための一般的な考慮事項

- Java環境およびJavaプラグイン

開発およびデプロイメントに関する一般的な考慮事項

次に、アプレットでSQLJを使用する際の一般的な考慮事項を示します。

- 次のSQLJランタイム・パッケージはすべて、アプレットとともにパッケージ化する必要があります。次のパッケージを含めます。

sqlj.runtime
sqlj.runtime.ref
sqlj.runtime.error

Oracle独自のカスタマイズを行った場合は、次のパッケージも含める必要があります。

oracle.sqlj.runtime
oracle.sqlj.runtime.error

これらのパッケージは、Oracleインストールによって、ORACLE_HOME/libディレクトリのランタイム・ライブラリの中の1つに組み込まれています。

関連項目:
「Oracle SQLJ実装を使用するための要件」

- データベース接続用のドライバとして、Oracle JDBC ThinドライバなどのPure Java JDBCドライバを指定する必要があります。

- アプレット内のSQLJ実行文ごとに、接続コンテキストのインスタンスを明示的に指定する必要があります。2つのSQLJアプレットを1つのブラウザで実行した場合、同じJVMで実行されるのを防ぐために、必ず明示的に指定してください。

関連項目:
「接続の際の考慮事項」

- デフォルトのトランスレータ設定-codegen=oracleによって、Oracle固有のコードが生成されます。これによって、実行時のJavaリフレクションの使用が削減されるので、異なるブラウザ環境間での移植性が向上します。

関連項目:
「コードの生成(-codegen)」および「Oracle固有コード生成(プロファイルなし)」

エンド・ユーザーのための一般的な考慮事項

エンド・ユーザーがSQLJアプレットを実行したときに、CLASSPATH内のクラスが、アプレットとともにダウンロードされたクラスと競合する可能性があります。これを回避するためには、アプレットを実行する前に、エンド・ユーザー側でCLASSPATHを削除することをお薦めします。

Java環境およびJavaプラグイン

Java環境およびOracle固有の機能の使用に関しては、追加で考慮する事項を次に示します。

- SQLJは、JDK 1.5の実行環境が必要です。ユーザーは、プラグインがない状態で、前のバージョンのJDKを使用するブラウザでSQLJアプレットを実行することはできません。Sun Microsystemsから提供されたJavaプラグインを使用する方法があります。詳細は、次を参照してください。
http://java.sun.com/products/plugin/

- Oracle固有の機能を使用するアプレットでは、Oracle SQLJランタイムを起動する必要があります。Oracle SQLJランタイムは、oracle.sqlj.*下のSQLJランタイム・ライブラリ・ファイル内のクラスで構成されます。Oracle SQLJ runtime.jarライブラリでは、Java Reflection API(java.lang.reflect.*)が必要です。大半のブラウザでは、Reflection APIをサポートしていなかったりセキュリティ上の制約があるのに対し、Sun社のJavaプラグインの場合はReflection APIに対するサポートが提供されています。

注意:
Oracle固有の機能とは、Oracle拡張型(第5章「型のサポート」を参照)を使用すること、およびOracle固有コード生成を必要とする(またはISO SQLJ標準コード生成の場合はOracle Databaseインスタンスと連携できるようにカスタマイズされたアプリケーションを必要とする)SQLJ機能を使用することを意味します。(たとえば、第4章「基本的な言語機能」で説明されているSET文がこれに該当します。)

これまで、Internet ExplorerやNetscapeのブラウザに重点を当てて説明してきました。その要約を次に示します。

- SQLJとJDBCのバージョンは一致している必要があります。たとえば、SQLJ 9.0.0ランタイムを使用するには、Oracle 9.0.0以前のJDBCドライバを使用する必要があります。

関連項目:
「Oracle SQLJ実装を使用するための要件」

- SQLJ文中にオブジェクト型、JDBC 2.0型、REF CURSORまたはCAST文を使用する場合は、次のいずれかに適合している必要があります。

- アプレットを変換するときに、デフォルトの-codegen=oracle設定を使用します。

- 実行するブラウザではJDK 1.5をサポートしていて、リフレクションが許可されていることを確認します。

- ブラウザのJavaプラグインを介してアプレットを実行します。

サーバー側SQLJの概要

SQLJコードは、クライアント・アプリケーションで使用できるばかりでなく、ターゲットのOracle Databaseのストアド・プロシージャ、ストアド・ファンクションまたはトリガーでも実行できます。サーバー側のアクセスは、サーバー内部で実行されるOracle JDBCドライバを介して発生します。また、Oracle Database 11g (およびそれ以前のバージョン)には埋込みSQLJトランスレータがあるため、サーバー側で使用するSQLJソース・ファイルをサーバーで直接変換することもできます。

次の2点については考慮が必要です。

- サーバー側で使用するSQLJコードの作成
ターゲットのOracle Database側で使用するSQLJアプリケーションのコードの記述方法は、クライアント側で使用するコードの記述方法と類似しています。主な相違点は、JDBCの全般的な特性によるものであり、SQLJ固有の特性によるものではありません。大きな相違点は、次のように接続に関するものです。

- 接続数が1つに限定されること。

- コードが実行されるデータベースに接続すること。

- 接続が暗黙的に行われること(クライアント側とは異なり、明示的に初期化する必要がありません)。

- 接続を終了できないこと。終了しようとしても無視されます。

この他、サーバー内で接続に使用するJDBCサーバー側ドライバは、自動コミット・モードをサポートしていないことも挙げられます。

注意:
サーバー側Thinドライバの一部には、あるサーバー内のコードから別のサーバーへ接続できるものがあります。この場合、クライアントのThinドライバを使用した場合と結果は同様で、しかもコードの記述方法も同様です。詳細は、「Oracle JDBCドライバの概要」を参照してください。

- サーバー側SQLJコードの変換とロード
コードの変換とコンパイルは、クライアントでもサーバーでも実行できます。クライアント側で行った場合は、そのクラス・ファイルとリソース・ファイルをクライアントからサーバーにロードできます。それには、Oracleのloadjavaユーティリティを使用してクライアントからファイルをプッシュするか、またはSQLコマンドを使用してサーバーからファイルをプルします。

また、サーバー側の埋込みSQLJトランスレータを使用して変換とロードを1ステップで行う方法もあります。クラス・ファイルまたはリソース・ファイルのかわりにSQLJソース・ファイルをロードすると、変換とコンパイルは自動的に実行されます。通常、loadjavaまたはSQLコマンドは、クラス・ファイルとリソース・ファイルに対して使用することも、ソース・ファイルに対して使用することも可能です。ユーザーの観点からは、.sqljファイルは.javaファイルと同様に扱われ、変換は暗黙的に実行されます。

関連項目:
サーバー側の埋込みトランスレータの使用方法は、「SQLJソース・コードのサーバーへのロード」を参照してください。

注意:
サーバー側トランスレータでは、SQLJ -codegenオプションおよびOracle固有のコード生成をサポートしていません。ISO SQLJ標準コードをサーバーで使用するには、クライアント上で変換して、個々のコンポーネントをサーバーにロードする必要があります。また、異なる設定で生成されたコードを実行するときには、相互運用性に関する制限事項に留意してください。詳細は、「クライアント側でのSQLソースの変換とコンポーネントのロード」および「Oracle固有コード生成(プロファイルなし)」を参照してください。

他の開発環境

このマニュアルの説明は、UNIX環境で英語版コードを手動で作成する場合を想定しています。ただし、SQLJは他のプラットフォームおよび統合開発環境(IDE)でも使用できます。他言語版のグローバリゼーション・サポートもあります。ここでは、次の項目について説明します。

- SQLJグローバリゼーション・サポート

- Oracle JDeveloper 10g などのIDEでのSQLJの使用

- Windowsに関する注意事項

SQLJグローバリゼーション・サポート

ネイティブ言語および文字のエンコードは、Javaの組込みグローバリゼーション・サポート機能を使用して、Oracle SQLJ実装によってサポートされます。

トランスレータ・メッセージおよびランタイム・メッセージ用の言語とエンコーディング方法は、JVM標準のuser.languageおよびfile.encodingプロパティによって、特定されます。変換時にソース・ファイルを解析および生成するためのエンコーディングは、SQLJの-encodingオプションで指定します。

関連項目:
「トランスレータおよびランタイムでのグローバリゼーション・サポート」

Oracle JDeveloper 10g などのIDEでのSQLJの使用

Oracle SQLJ実装はプログラムAPIを含むため、Oracle JDeveloper 10g などのIDEへ埋め込むことができます。IDEは、フロントエンドのsqljスクリプトと同じように機能し、トランスレータ、セマンティクス・チェッカ、コンパイラおよびカスタマイザ(使用する場合)を起動します。

JDeveloperは、Javaプログラミング用のJavaベースのクロス・プラットフォーム・ビジュアル開発環境です。開発者はJDeveloperで、スケーラブルな複数層インターネット・アプリケーションを構築し、Oracle Internet Platform全体でJavaを使用できます。この製品(JDeveloper IDE)では、コンポーネントベースのアプリケーションを作成、デバッグおよびデプロイできます。

Oracle JDBC OCIおよびThinドライバは、JDeveloperに含まれています。JDeveloperのコンパイル機能には、統合されたSQLJトランスレータが含まれており、SQLJアプリケーションがコンパイル時に自動的に変換されるようになっています。

JDeveloperに関する情報は、次のURLから閲覧できます。

http://www.oracle.com/technology/products/jdev/index.html

Windowsに関する注意事項

UNIX環境ではなくMicrosoft Windows環境を使用する場合は、次の点に注意してください。

- このマニュアルでは、UNIX構文を使用しています。JVMではプラットフォーム固有の形式のファイル名およびパスが求められるため、プラットフォームに適した、プラットフォーム固有のファイル名およびディレクトリ・セパレータ(Microsoft Windowsでは「\」など)を使用してください。これは、異なるファイル名構文が許可されるシェル(kshなど)を使用する場合でも同様です。

- UNIXの場合は、Oracle SQLJ実装のフロントエンド・スクリプトsqljを使用して、SQLJトランスレータを起動できます。Microsoft Windowsでは、かわりに、Oracleの実行可能ファイルsqlj.exeを使用します。Microsoft Windowsの.batファイルでは、引数への等号(=)の埋込み、引数の文字列操作およびファイル名引数でのワイルドカード文字の使用がサポートされていないため、Microsoft Windowsではスクリプトを使用できません。

- 環境変数の設定方法は、オペレーティング・システムによって異なります。OS固有の制限事項がある場合もあります。Windows 95では、「システム」コントロール・パネルの「環境」タブを使用します。また、Windows 95では変数設定で「=」文字を使用できないため、SQLJではSQLJ_OPTIONS(SQLJがオプション設定に使用できる環境変数)の設定に、「=」ではなく「#」を使用できます。環境変数の設定および構文についてはオペレーティング・システムのマニュアルを参照し、サイズ上の制限に注意してください。

- どのようなオペレーティング・システムおよび環境を使用している場合も同様ですが、特定の制限事項には留意してください。特に、展開された完全なSQLJコマンドラインのサイズが、許容されるコマンドラインのサイズの最大値を超えないようにしてください。Windows 95の場合は250文字以内、Windows NTの場合は4000文字以内にします。使用するオペレーティング・システムのドキュメントを参照してください。

詳細は、Windowsのリリース・ノートを参照してください。

3 プログラミング上の主な考慮事項

この章では、SQLJアプリケーションの開発および実行前に検討する必要がある重要な問題について説明し、要約とサンプル・アプリケーションも示します。内容は次のとおりです。

- JDBCドライバの選択

- 接続の際の考慮事項

- NULLの処理

- 例外処理の基本

- 基本的なトランザクション制御

- 概要: 簡単なSQLJコード

- Oracle固有コード生成(プロファイルなし)

- ISO標準コード生成

- ネーミングの要件および制限事項

- 中間層のSQLJに関する考慮事項

JDBCドライバの選択

Java Database Connectivity(JDBC)ドライバの選択にあたっては、変換時と実行時にそれぞれ別のドライバを使用するかどうかを検討する必要があります。変換用と実行用の各ドライバ・クラスを選択または登録し、そのドライバを接続URLで指定してください。

注意:
Oracle固有コード生成を使用する場合、またはISO SQLJ標準コード生成とOracleカスタマイザを使用する場合は、Oracle JDBCドライバが必要です。Oracle固有の機能を実際には使用しない場合にも必要です。

ここでは、次の項目について説明します。

- Oracle JDBCドライバの概要

- 変換用ドライバの選択

- 実行時に使用するドライバの選択および登録

Oracle JDBCドライバの概要

Oracle JDBCドライバを次に示します。

- Oracle Call Interface(OCI)ドライバ: Oracleクライアント環境とともにクライアント側で使用します。

- Thinドライバ: Pure Javaで記述されたドライバで、クライアント側で特にアプレットから使用します。Oracleクライアント環境は不要です。

- サーバー側Thinドライバ: クライアント側Thinドライバと同様の機能を備えていますが、Oracle Databaseインスタンス内で実行するコード用のドライバでありリモート・サーバーにアクセスするためのものです。

- サーバー側内部ドライバ: ターゲット・サーバー内(つまり、アクセスするOracle Databaseインスタンス内)で実行するコード用のドライバ。

Oracle Database 11g では、Java Development Kit(JDK)1.5と互換性があるクライアント側のドライバが用意されています。

関連項目:
『Oracle Database JDBC開発者ガイドおよびリファレンス』

注意:
変換時と実行時とで、別々のドライバを選ぶ場合もあります。具体的には、変換時のセマンティクス・チェックにはOracle JDBC OCIドライバを使用し、実行時にはOracle JDBC Thinドライバを使用します。

JDBCの中核となる機能

Oracle JDBCドライバは、いずれも同様の機能性を備えています。各ドライバでサポートされている機能セット、構文、プログラミング・インタフェースおよびOracle拡張型は、すべて同じです。

Oracle JDBCドライバはすべて、oracle.jdbc.OracleDriverクラスでサポートされています。

JDBC OCIドライバ

Oracle JDBC OCIドライバでは、OCIを直接Javaからコールしてデータベースにアクセスできるため、Oracle Databaseの様々なバージョンとの高度な互換性が確保されています。これらのドライバでは、インストール済Oracle Netアダプタ(プロセス間通信(IPC)、Named Pipes、TCP/IP、IPX/SPXなど)がサポートされています。

ネイティブ・メソッドを使用してCエントリ・ポイントをコールする際、このOCIドライバはOracleプラットフォームに依存するため、Oracle NetをはじめとするOracleクライアントのインストールが必要になります。このため、これはアプレットには適していません。

OCIドライバ用の接続文字列は次の形式になります(tns は、オプションでTNSの別名またはTNS完全指定です)。

jdbc:oracle:oci:@<tns>

注意:
下位互換性のため、ociのかわりにoci8も使用できます。

JDBC Thinドライバ

Oracle JDBC Thinドライバは、プラットフォームに依存しないPure Javaの実装であり、Javaソケットを使用してOracleまたはOracle以外のクライアントから直接Oracle Databaseに接続できます。アプレットの実行と同時にこのドライバをブラウザにダウンロードすることも可能です。

このJDBC Thinドライバでは、TCP/IPプロトコルしかサポートされていないため、データベース・サーバーからのTCP/IPソケットをリスニングするTNSリスナーが必要です。このJDBC Thinドライバとアプレットとを併用する場合、Javaソケットをサポートしているクライアント・ブラウザを使用してください。

JDBC Thinドライバ用の接続文字列は、通常次の形式です。

jdbc:oracle:thin:@host:port/servicename

関連項目:
データベース・サービス名の詳細は『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

Oracle Database 11g では、SIDを使用した接続文字列は非推奨になりましたが、下位互換性の目的で引き続きサポートされています。

jdbc:oracle:thin:@host:port:sid

JDBCサーバー側Thinドライバ

Oracle JDBCサーバー側のThinドライバは、クライアント側のJDBC Thinドライバと同様の機能性を備えていますが、さらにデータベース内で動作し、リモート・サーバーにアクセスできます。このドライバは、あるOracle Databaseインスタンス内部(Javaストアド・プロシージャなど)から別のOracle Databaseインスタンスへのアクセスに利用できます。

サーバー側Thinドライバ用の接続文字列は、クライアント側Thinドライバ用と同じです。

注意:
サーバー側Thinドライバの使用時に、元のデータベースをそのままにしておくためには、ユーザー・アカウントにSocketPermissionを割り当てる必要があります。詳細は『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。また、SocketPermissionおよび他のアクセス権の概要は、『Oracle Database Java開発者ガイド』を参照してください。

JDBCサーバー側内部ドライバ

Oracle JDBCサーバー側内部ドライバは、SQL操作を行うターゲットのOracle Databaseインスタンスで実行される、あらゆるJavaコードをサポートしています。サーバー側内部ドライバを使用すると、Oracle Java Virtual Machine(JVM)から直接SQLエンジンに通信できるようになります。このドライバは、Oracle Database 11g でストアド・プロシージャ、ストアド・ファンクションまたはトリガーとしてSQLJコードを実行するためのデフォルトのJDBCドライバです。

サーバー側内部ドライバ用の接続文字列は、次の形式です。

jdbc:oracle:kprb:

SQLJコードでデフォルトの接続コンテキストを使用する場合、SQLJでは、Oracle JVMで実行するコード用に自動的にこのドライバが使用されます。

変換用ドライバの選択

ドライバ・マネージャ・クラスを選択し、変換用のドライバを指定するには、コマンドラインまたはプロパティ・ファイルでSQLJオプションを設定します。

OracleDriver(デフォルト)以外のドライバ・マネージャ・クラスを選択するには、SQLJの-driverオプションを使用します。

SQLJの-urlオプションで接続URLを指定するときは、Oracle Database用のJDBC ThinドライバやJDBC OCIドライバなど、選択した特定のJDBCドライバも一緒に指定します。

関連項目:
「接続オプション」

通常は、ソース・コードでランタイム接続用に指定したドライバを使用します。

注意:
前述の-driverオプションは、特定のドライバの選択には使用できません。このオプションを使用すると、ドライバ・マネージャにあるドライバ・クラスを登録します。そのドライバ・クラスは、複数のドライバ・プロトコル(すべてのOracle JDBCプロトコルで使用されるOracleDriverなど)に使用できます。

実行時に使用するドライバの選択および登録

実行時にデータベースに接続するには、接続インスタンス(sqlj.runtime.ref.DefaultContextクラスまたは宣言済の接続コンテキスト・クラスのインスタンス)のいずれかに対して指定したURLを認識するドライバを1つ以上登録する必要があります。

Oracle JDBCドライバを使用している場合に、Oracle.connect()メソッドでデフォルトの接続を作成すると、SQLJはこれを自動的に処理します。Oracle.connect()メソッドによって、oracle.jdbc.OracleDriverクラスが登録されます。

Oracle JDBCドライバを使用し、Oracle.connect()を使用しない場合は、次のようにOracleDriverクラスを手動で登録する必要があります。

DriverManager.registerDriver(new oracle.jdbc.OracleDriver());

Oracle JDBCドライバを使用しない場合は、次のように適切なドライバ・クラスを登録する必要があります。

DriverManager.registerDriver(new mydriver.jdbc.driver.MyDriver());

どの場合でも、接続URL、ユーザー名およびパスワードの設定が必要です。

関連項目:
「DefaultContextを使用した単一接続または複数接続」

注意:
JDBC接続を確立する際にJDBCドライバ・マネージャのかわりに、データ・ソースを使用することができます。「WITH句宣言」で説明するように、with句にデータ・ソースを指定できます。データ・ソースの概要は、『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

接続の際の考慮事項

SQLJアプリケーションで使用するデータベース接続の選択にあたっては、次の点を考慮してください。

- 必要なデータベース接続が単一であるか複数であるか。

- 複数の接続(また、必要に応じて複数のスキーマ)を使用する場合、各接続で同じ名前のSQLエンティティ、つまり、表の名前、列の名前とデータ型、ストアド・プロシージャの名前とシグネチャなどは、各接続のたびに同じ名前のものを使用するか。

- 変換時と実行時にそれぞれ別の接続を使用するか、同じ接続を使用するか。

データベース接続用の接続コンテキストのインスタンス(DefaultContextまたは宣言した接続コンテキスト・クラスのインスタンス)は、SQLJ実行文で指定します。接続コンテキスト仕様を指定せずに、デフォルトの接続(デフォルトとしてあらかじめ設定したDefaultContextのインスタンス)を使用することも可能です。

注意:
操作の際に数種類のSQLエンティティを使用する場合は、通常、新たに接続コンテキスト・クラスを宣言し、使用します。

ここでは、次の項目について説明します。

- DefaultContextを使用した単一接続または複数接続

- 接続の終了

- 宣言済の接続コンテキスト・クラスを使用した複数接続

- Oracleクラスについて

- DefaultContextクラスについて

- 変換時の接続

- カスタマイズ時の接続

DefaultContextを使用した単一接続または複数接続

ここでは、DefaultContextクラスの接続インスタンスのみを使用する場合について説明します。

単一接続や、名前とデータ型が同じSQLエンティティを使用する複数接続では、代表的な方法です。

単一接続

単一接続の場合は、DefaultContextクラスのインスタンスを1つ使用します。DefaultContextオブジェクトの作成時に、データベースURL、ユーザー名およびパスワードを指定します。

この作業は、oracle.sqlj.runtime.Oracleクラスのconnect()メソッドで行えます。このメソッドをコールすると、デフォルトの接続コンテキスト・インスタンスが自動的に初期化されます。このメソッドには複数のシグネチャがあり、たとえば、ユーザー名、パスワードおよびURLを直接指定できるものや、プロパティ・ファイルに指定するものがあります。次に、プロパティ・ファイルconnect.propertiesを使用した例を示します。

Oracle.connect(MyClass.class, "connect.properties");

注意:
connect.propertiesファイルは、指定したクラスに基づいて検索されます。たとえばMyClassがmy-packageにある場合、connect.propertiesは同じパッケージの場所であるmy-packageで検索されます。

connect.propertiesを使用する場合は、必要な編集とアプリケーションでのパッケージ化を行ってください。この例では、oracle.sqlj.runtime.Oracleクラスのインポートも必要です。

次のようにすると、ユーザー名、パスワードおよびURLを直接指定できます。

Oracle.connect("jdbc:oracle:thin:@localhost:1521/myservice", "scott", "tiger");

この例では、JDBC Thinドライバを使用してscottユーザー(パスワードtiger)をコンピュータlocalhost上のデータベースに、ポート1521経由で接続します。myserviceは、接続用のデータベース・サービスの名前です。

どちらの場合も、DefaultContextクラスの特別な静的インスタンスが生成され、デフォルトの接続としてインストールされます。DefaultContextのインスタンスを直接操作する必要はありません。

ここまでの手順を終えた後、アプリケーションのSQLJ実行文に対していっさい接続を指定しないことも可能です。ただし、その場合は常にデフォルトの接続が使用されます。

JDBC Thinドライバを使用する場合は、前の例で示したように、ホスト名、ポート番号およびサービス名(またはSID、ただしOracle Database 11gでは非推奨)をURLに含める必要があります。また、データベースには、指定したポートで実行されるリスナーが必要です。JDBC OCIドライバを使用する場合、クライアントのデフォルト・アカウントを使用するときはサービス名(またはSID)は不要です。このドキュメントの例はこれに該当します。また、名前-値ペアを使用することもできます。

関連項目:
詳細は、『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

次のURLでは、クライアントのデフォルト・アカウントに接続できます。

jdbc:oracle:oci:@

注意:

- デフォルトの接続がすでに設定されていれば、Oracle.connect()を指定した場合でもデフォルトの接続が再設定されることはありません。この場合は、NULLが戻されます。この機能により、クライアントとサーバーで同じコードを使用できます。デフォルトの接続を指定変更するには、DefaultContextのstatic setDefaultContext()メソッドを使用します。

- Oracle.connect()メソッドの自動コミット・フラグのデフォルト値はfalseです。ただし、このメソッドのシグネチャは明示的に設定できます。Oracle JDBC実装の自動コミット・フラグのデフォルト値はtrueです。

- Oracle.connect()をコールする際に、必要に応じて、MyClass.classのかわりにgetClass()を指定できますが、この指定はgetClass()をstaticメソッドからコールしない場合にのみ有効です。getClass()メソッドは、一部のSQLJデモ・アプリケーションで使用されています。

- 次のように、static DefaultContextインスタンスに接続できます。これは、デフォルトの接続に対応しています。

DefaultContext.getDefaultContext();

複数接続

複数接続の場合は、DefaultContextクラスのインスタンスをさらに作成して使用します。デフォルト接続もそのまま使用できます。

DefaultContextのインスタンス化するには、次の例のようにOracle.getConnection()メソッドを使用します。

最初に、デフォルト接続を大半の文で使用し、残りの文では別の接続を使用するとします。DefaultContextのインスタンスを新たに1つ作成する必要があります。

DefaultContext ctx = Oracle.getConnection (
"jdbc:oracle:thin:@localhost2:1521/myservice2", "bill", "lion");

注意:
同一スキーマに対して複数の操作を行う場合は、ctxでscott/tigerスキーマを使用することも可能です。

デフォルトの接続を使用する場合は、接続コンテキストを指定する必要はありません。

#sql { SQL operation };

これは実際には、次の形式を省略しています。

#sql [DefaultContext.getDefaultContext()] { SQL operation };

追加した接続を使用する場合は、接続としてctxを指定します。

#sql [ctx] { SQL operation };

次に、複数の接続を使用する状況を想定し、各接続を名前付きDefaultContextインスタンスにします。これによって、接続を交互に切り替えることができます。

次の文は、同一スキーマに対して複数の接続を確立します(複数のOracle Databaseセッションやトランザクションを使用する場合など)。接続ごとにDefaultContextクラスをインスタンス化します。

DefaultContext ctx1 = Oracle.getConnection
("jdbc:oracle:thin:@localhost1:1521/myservice1", "scott", "tiger");
DefaultContext ctx2 = Oracle.getConnection
("jdbc:oracle:thin:@localhost1:1521/myservice1", "scott", "tiger");

接続コンテキストのインスタンスが2つ作成されます。どちらも、Oracle JDBC Thinドライバを介して、コンピュータlocalhost1上でサービスmyservice1を使用してscott/tigerに接続します。

次に、スキーマごとにそれぞれ別の接続を使用する場合を想定します。この場合も、接続ごとにDefaultContextクラスをインスタンス化します。

DefaultContext ctx1 = Oracle.getConnection
("jdbc:oracle:thin:@localhost1:1521/myservice1", "scott", "tiger");
DefaultContext ctx2 = Oracle.getConnection
("jdbc:oracle:thin:@localhost2:1521/myservice2", "bill", "lion");

接続コンテキストのインスタンスが2つ作成されます。この2つのインスタンスは、Oracle JDBC Thinドライバを使用し、それぞれ別のスキーマを使用します。ctx1オブジェクトは、コンピュータlocalhost1上のサービスmyservice1を使用してscott/tigerに接続し、ctx2オブジェクトは、コンピュータlocalhost2上のサービスmyservice2を使用してbill/lionに接続します。

アプリケーションのSQLJ実行文でこれらの接続を交互に切り替える方法には、次の2通りがあります。

- 接続の切替え頻度が高い場合に、アプリケーションの各文に対して、次のように接続を指定する方法。

#sql [ctx1] { SQL operation };
...
#sql [ctx2] { SQL operation };

注意:
接続コンテキストのインスタンスの名前は、必ず大カッコで囲みます。大カッコも構文の構成要素です。

- コード・フロー内の行で片方の接続を複数回連続して使用する場合、デフォルト接続をリセットするために、DefaultContextクラスのstatic setDefaultContext()メソッドを定期的に使用する方法。このメソッドによって、デフォルトの接続コンテキスト・インスタンスが初期化されます。この方法では、SQLJ文で接続を指定する必要がありません。

DefaultContext.setDefaultContext(ctx1);
#sql { SQL operation };   // These three statements all use ctx1
#sql { SQL operation };
#sql { SQL operation };
...
DefaultContext.setDefaultContext(ctx2);
#sql { SQL operation };   // These three statements all use ctx2
#sql { SQL operation };
#sql { SQL operation };

注意:
前述の文では接続コンテキストを指定していないため、変換時にデフォルトの接続コンテキストかどうかが文ごとにチェックされます。

接続の終了

接続が完了した後、接続コンテキスト・インスタンスをクローズしてください。tryブロックのfinally句(アプリケーションが例外時に終了した場合)でクローズを指定することをお薦めします。

DefaultContextクラス、および宣言したその他のあらゆる接続コンテキスト・クラスには、close()メソッドが用意されています。このclose()メソッドをコールすると、SQLJ接続コンテキスト・インスタンスが終了し、デフォルトでは、基になるJDBC接続インスタンスおよび物理的な接続も終了します。

また、oracle.sqlj.runtime.Oracleクラスに用意されているstatic close()メソッドを使用すると、デフォルトの接続のみが終了します。次の例では、あらゆる接続コンテキスト・クラスのインスタンスをctxとして示した場合を想定しています。

...
finally
{
ctx.close();
}
...

SQL例外が発生して、finally句がtryブロック内にない場合は、次のようになります。

...
finally
{
try { ctx.close(); } catch(SQLException ex) {...}
}
...

デフォルトの接続を終了する方法としては、Oracleクラスに用意されているclose()メソッドを使用する方法もあります。

...
finally
{
Oracle.close();
}
...

接続を終了する前に、必ず保留中の変更をコミットまたはロールバックしてください。接続を閉じる際に暗黙的なCOMMIT操作が行われるかどうかは、JDBC規格では指定されておらず、またベンダーによっても異なります。Oracleの場合、接続を終了する際に暗黙的なCOMMITが行われるようになっており、接続が終了されずにガベージ・コレクションが行われた場合は暗黙的なROLLBACKが行われるようになっていますが、これらのメカニズムに頼るのはお薦めできません。

注意:
基になる接続(共有接続の場合)を終了せずに、接続コンテキスト・インスタンスを終了することも可能です。詳細は、「共有接続の終了」を参照してください。

宣言済の接続コンテキスト・クラスを使用した複数接続

数種類のSQLエンティティを使用した接続の場合は、接続コンテキストの宣言によって、接続コンテキスト・クラスをさらに定義すると利便性が高まります。使用するSQLエンティティごとに個別の接続コンテキスト・クラスを作成すると、SQLJではコードのセマンティクス・チェックがより厳密に行われます。

関連項目:
「接続コンテキスト」

Oracleクラスについて

Oracle SQLJ実装のoracle.sqlj.runtime.Oracleクラスでは、DefaultContextクラスのインスタンスを簡単に作成して使用できます。

static connect()メソッドは、デフォルトの接続コンテキスト・インスタンスを初期化します(DefaultContextオブジェクトのインスタンスを作成し、デフォルトの接続としてインストールします)。connect()から戻されたDefaultContextのインスタンスの代入や使用は、任意に行ってください。デフォルトの接続がすでに確立されていると、connect()からNULLが戻されます。

static getConnection()メソッドでは、単にDefaultContextオブジェクトのインスタンスが生成され、そのインスタンスが戻されます。必要に応じて、戻されたインスタンスを使用できます。

oracle.jdbc.OracleDriverクラスをCLASSPATHに指定すると、どちらのメソッドを使用してもOracle JDBCドライバ・マネージャが自動的に登録されるようになります。static close()メソッドは、デフォルトの接続を終了するメソッドです。

Oracle.connect()メソッドおよびOracle.getConnection()メソッドのシグネチャ

いずれのメソッドにも、入力として次のパラメータをとるシグネチャがあります。

- URL(String)、ユーザー名(String)、パスワード(String)

- URL(String)、ユーザー名(String)、パスワード(String)、自動コミット・フラグ(boolean)

- URL(String)、java.util.Propertiesオブジェクト(接続のプロパティが格納されているオブジェクト)

- URL(String)、java.util.Propertiesオブジェクト、自動コミット・フラグ(boolean)

- ユーザー名やパスワードなど、接続を詳細に指定するURL(String)
次に示すURL文字列の形式の例では、ユーザー名(scott)およびパスワード(tiger)が指定されており、Oracle JDBCドライバとしてはJDBC Thinドライバが使用されています。

"jdbc:oracle:thin:scott/tiger@localhost:1521/myservice"

- URL(String)、自動コミット・フラグ(boolean)

- クラスのjava.lang.Classオブジェクト(そのクラスに基づいてプロパティ・ファイルがロードされる)、プロパティ・ファイル名(String)

- java.lang.Classオブジェクト、プロパティ・ファイル名(String)、自動コミット・フラグ(boolean)

- java.lang.Classオブジェクト、プロパティ・ファイル名(String)、ユーザー名(String)、パスワード(String)

- java.lang.Classオブジェクト、プロパティ・ファイル名(String)、ユーザー名(String)、パスワード(String)、自動コミット・フラグ(boolean)

- JDBC接続オブジェクト(Connection)

- SQLJ接続コンテキスト・オブジェクト

最後の2つのシグネチャは既存のデータベース接続を継承します。接続を継承すると、その接続に対する自動コミットの設定も継承されます。

自動コミット・フラグは、SQL操作を自動的にコミットするかしないかを指定するフラグです。Oracle.connect()メソッドおよびOracle.getConnection()メソッドの場合にのみ、デフォルトはfalseになっています。デフォルト値を使用すると、入力として自動コミットをとらないシグネチャを使用できます。ただし、コンストラクタを使用して、DefaultContextなどの接続コンテキスト・クラスのインスタンスを作成する場合は、自動コミットの設定を指定する必要があります。Oracle JDBC実装の自動コミット・フラグは、デフォルトとしてtrueをとります。

関連項目:
「基本的なトランザクション制御」および「DefaultContextを使用した単一接続または複数接続」

Oracle.close()メソッドのオプションのパラメータ

Oracle.close()を使用してデフォルト接続を閉じる際に、基になる物理的なデータベース接続を終了するかどうかを指定できます。デフォルトでは接続の終了が指定されます。この指定は、物理的な接続を複数の接続オブジェクト(SQLJ接続コンテキスト・インスタンスまたはJDBC接続インスタンス)で共有している場合に関係します。

基になる物理的な接続を、オープンした状態に保つには、次のようにします。

Oracle.close(ConnectionContext.KEEP_CONNECTION);

基になる物理的な接続を終了するには、次のようにします(デフォルトの動作)。

Oracle.close(ConnectionContext.CLOSE_CONNECTION);

KEEP_CONNECTIONおよびCLOSE_CONNECTIONは、ConnectionContextインタフェースのstatic定数です。

関連項目:
「共有接続の終了」

DefaultContextクラスについて

sqlj.runtime.ref.DefaultContextクラスは、接続コンテキスト・クラスの完全なデフォルト実装を提供します。接続コンテキストを宣言して作成したクラスと同じように、DefaultContextクラスもsqlj.runtime.ConnectionContextインタフェースを実装します。DefaultContextクラスのクラス定義は、次のように宣言したときにSQLJトランスレータで生成される定義と同じです。

#sql public context DefaultContext;

DefaultContextメソッド

DefaultContextクラスの主なメソッドを次に示します。

- getConnection()
基になるJDBC接続オブジェクトを取得します。これは、動的SQL操作を使用する1つの方法として、アプリケーションにJDBCコードを使用する場合に役立ちます。基になるJDBC接続オブジェクトのsetAutoCommit()メソッドを使用すると、接続の自動コミット・フラグを設定できます。

- setDefaultContext()
アプリケーションで使用するデフォルトの接続を設定します。これは、入力としてDefaultContextインスタンスをとるstaticメソッドです。SQLJ実行文で接続コンテキストのインスタンスを指定しないと、このメソッドまたはOracle.connect()メソッドを使用して定義したデフォルトの接続が使用されます。

- getDefaultContext()
アプリケーションのデフォルト接続として現在定義されているDefaultContextインスタンスを戻します。これは、staticメソッドです。

- close()
接続コンテキスト・インスタンスをクローズします。

getConnection()メソッドおよびclose()メソッドは、sqlj.runtime.ConnectionContextインタフェースで指定します。

注意:
クライアント側では、setDefaultContext()をあらかじめコールしないと、getDefaultContext()からの戻り値がNULLになります。ただし、データ・ソース・オブジェクトがJNDIのjdbc/defaultDataSource下にバインドされている場合は、クライアントでデフォルトの接続としてこのデータ・ソース・オブジェクトが使用されます。
サーバーでは、getDefaultContext()によってデフォルトの接続(サーバー自体への接続)が戻されます。

DefaultContextコンストラクタ

通常は、Oracle.connect()またはOracle.getConnection()メソッドを使用してDefaultContextをインスタンス化します。ただし、DefaultContextの場合、5つのコンストラクタのうちのいずれかを使用すると、インスタンスを直接作成できます。これらのコンストラクタには、次の異なる入力パラメータ・セットがあります。

- URL(String)、ユーザー名(String)、パスワード(String)、自動コミット(boolean)

- URL(String)、java.util.Propertiesオブジェクト、自動コミット(boolean)

- URL(ユーザー名やパスワードなど、接続の詳細を指定するString)、自動コミットの設定(boolean)
次に示すURLの形式の例では、ユーザー名およびパスワードが指定されており、Oracle JDBCドライバとしてはJDBC Thinドライバが使用されています。

"jdbc:oracle:thin:scott/tiger@localhost:1521/myservice"

- JDBC接続オブジェクト(Connection)

- SQLJ接続コンテキスト・オブジェクト

最後の2つのシグネチャは既存のデータベース接続を継承します。接続を継承すると、その接続に対する自動コミットの設定も継承されます。

DefaultContextインスタンスを作成する例を、次に示します。

DefaultContext defctx = new DefaultContext
("jdbc:oracle:thin:@localhost:1521/myservice", "scott", "tiger", false);

接続コンテキスト・コンストラクタに関する注意:

注意:
接続コンテキスト・コンストラクタを使用する際は、次の点に注意する必要があります。

- 接続コンテキスト・クラスは、Oracle.connect()メソッドとは異なり、自動コミットの設定が必要です。

- 前述のコンストラクタのうち、最初の3つを使用するには、あらかじめJDBCドライバを登録する必要があります。ドライバを自動的に登録するには、Oracle JDBCドライバを使用し、Oracle.connect()をコールします。「実行時に使用するドライバの選択および登録」を参照してください。

- 通常宣言する接続コンテキスト・クラスのコンストラクタ・シグネチャは、DefaultContextクラスと同じです。ただし、接続コンテキスト・クラスをデータ・ソースに対応付けるように宣言する場合、別のコンストラクタが用意されています。詳細は、「標準データ・ソースのサポート」を参照してください。

- JDBC接続オブジェクトを引数とするコンストラクタを使用する場合は、接続コンテキスト・インスタンスをNULL JDBCで初期化しないでください。

- 自動コミットの設定では、SQL操作が自動的にコミットされるかどうかが定義されます。詳細は、「基本的なトランザクション制御」を参照してください。

DefaultContext close()メソッドのオプションのパラメータ

接続コンテキスト・インスタンスを終了するとき、基になる物理的な接続を終了するかどうかを指定できます。デフォルトでは接続の終了が指定されます。この指定は、複数の接続オブジェクト(SQLJ接続コンテキスト・インスタンスまたはJDBC接続インスタンス)で物理的な接続を共有している場合に有効です。DefaultContextインスタンスのdefctxを前提とした例を、いくつか次に示します。

基になる物理的な接続をオープンした状態に保つには、次の構文を使用します。

defctx.close(ConnectionContext.KEEP_CONNECTION);

基になる物理的な接続を終了する(デフォルトの動作)には、次の構文を使用します。

defctx.close(ConnectionContext.CLOSE_CONNECTION);

KEEP_CONNECTIONおよびCLOSE_CONNECTIONは、ConnectionContextインタフェースのstatic定数です。

関連項目:
これらのパラメータの使用方法および共有接続の詳細は、「共有接続の終了」を参照してください。

変換時の接続

変換時にオンラインのセマンティクス・チェックを使用する場合、SQLJで使用するデータベース接続を指定する必要があります。これらは、基本スキーマといいます。

関連項目:
「接続コンテキストの概要」

変換時と実行時で別々の接続を使用できます。実際、別々の接続を使用する必要がある場合、またそれが推奨される場合が多くあります。現在開発を行っている環境と将来アプリケーションを実行する環境とが異なる場合は、別々の接続を使用する必要が生じる場合があります。変換時にランタイム接続を使用できる場合でも、オンライン・チェックの精度を高めるためにはリソースを絞り込んでアカウントを作成する方が望ましいといえます。実際にこの精度を高めるには、ランタイム接続時に使用可能なSQLエンティティうち、アプリケーションで使用するSQLエンティティのサブセットを少量にします。アプリケーションで実際に使用するSQLエンティティのみに絞り込んだ基本スキーマを作成すると、オンライン・チェックの精度と信頼度が高まります。

変換時の接続を指定するには、コマンドラインまたはプロパティ・ファイルでSQLJトランスレータの接続オプションを使用します。

関連項目:
「接続オプション」

カスタマイズ時の接続

一般に、Oracleのカスタマイズではデータベース接続は不要です。ただし、Oracle SQLJ実装ではカスタマイザ接続がサポートされています。これは、2つの環境で利用できます。

- 使用するOracleカスタマイザのoptcolsオプションを使用可能にすると、接続が必須になります。このオプションを使用すると、イテレータ列型およびサイズは、パフォーマンスが最適化されるように定義されます。

- SQLCheckerCustomizerと呼ばれる、プロファイルに対してセマンティクス・チェックを実行する特別なカスタマイザを使用した場合、オンライン・チェッカ(デフォルトでは使用)を使用するためには接続が必要になります。

Oracle固有コード生成の場合は、SQLJトランスレータに、同じ機能を持つ-optcolsオプションがあります。SQLCheckerCustomizerは、Oracleカスタマイザ・ハーネスのverifyオプションを指定すると起動されるようになります。どのカスタマイザを使用する場合にも、必要に応じて、カスタマイザ・ハーネスのuser、password、urlおよびdriverオプションを使用して、接続パラメータを指定します。

関連項目:

- 「Oracleカスタマイザの列定義オプション(optcols)」

- 「プロファイルのセマンティクス・チェック用のSQLCheckerCustomizer」

- 「カスタマイザ・ハーネスの接続用オプション」

NULLの処理

Javaの基本型(int、double、floatなど)は、null値をとりません。結果式およびホスト式の型を選択するときは、このことに注意してください。

ここでは、次の項目について説明します。

- NULL処理用のラッパー・クラス

- NULL処理の例

NULL処理用のラッパー・クラス

JDBCではNULLを0または特定のデータ型に対してはfalseとして取り出されますが、SQLJではSQLのNULLは、常にJavaのnullとして取り出されます。そのため、SQLでNULLを受け取る可能性がある場合に、SQLJで出力変数にJavaの基本型を使用しないでください(Javaの基本型は、null値をとらないためです)。

このことは、結果式、出力ホスト式、入出力ホスト式およびイテレータ列の型について当てはまるので、注意が必要です。Javaの基本型を受取り用にしてSQLのNULLを取り出そうとすると、sqlj.runtime.SQLNullExceptionが発生し、代入が行われなくなります。

Javaの基本型にNULL値が代入されるのを避けるには、基本型のかわりに次のラッパー・クラスを使用します。

- java.lang.Boolean

- java.lang.Byte

- java.lang.Short

- java.lang.Integer

- java.lang.Long

- java.lang.Double

- java.lang.Float

基本型の値に再変換する必要が生じた場合は、ラッパー・クラスのxxxValue()メソッドを使用してください。たとえば、intValue()を使用すると、int値がIntegerオブジェクトから戻され、floatValue()を使用すると、float値がFloatオブジェクトから戻されます。この例では、intobjをIntegerオブジェクトとします。

int j = intobj.intValue();

注意:

- SQLNullExceptionは、標準java.sql.SQLExceptionクラスのサブクラスです。

- JavaオブジェクトはNULL値を持つことができます。SQLJでは、他のホスト言語(C、C++、COBOLなど)と異なり、インジケータ変数は不要です。

NULL処理の例

次に、java.langラッパー・クラスを使用してNULLを処理する例を示します。

NULL入力ホスト変数の例

次の例では、Floatオブジェクトを使用して、NULL値をデータベースに渡します。

int empno = 7499;
Float commission = null;

#sql { UPDATE emp SET comm = :commission WHERE empno = :empno };

この場合は、Javaの基本型floatを使用できません。

NULLイテレータ行の例

次の例では、NULLデータに対応できるように、イテレータにDouble列型を使用します。

emp表の従業員のうち、給与が$50,000以上の従業員の名前(ENAME)と歩合(COMM)をイテレータに取り出します。次に各行をテストして、COMMフィールドが実際にNULLになっているかどうかを調べます。NULLの場合は、NULLの処理が行われます。

#sql iterator EmployeeIter (String ename, Double comm);

EmployeeIter ei;
#sql ei = { SELECT ename, comm FROM emp WHERE sal >= 50000 };

while (ei.next())
{
if (ei.comm() == null)
System.out.println(ei.ename() + " is not on commission.");
}
ei.close();
...

注意:
WHERE句のNULL値との比較を実行するには、次のSQL構文を使用します。

...WHERE :x IS NULL

例外処理の基本

ここでは、SQLJアプリケーションにおける例外処理の基本として、エラー・チェック要件などについて説明します。ここでは、次の項目について説明します。

- SQLJおよびJDBCの例外処理要件

- 例外の処理

- SQLExceptionサブクラスの使用方法

SQLJおよびJDBCの例外処理要件

SQLJ実行文は、sqlj.runtimeからのJDBCコールになり、JDBCではSQL例外が捕捉またはスローされる必要があるため、SQLJでも、SQLJ実行文を含むブロックで、SQL例外が捕捉またはスローされる必要があります。適切な例外処理が含まれていないと、ソース・コードのコンパイル中にエラーが生成されます。

SQL例外の処理には、SQLExceptionクラスが必要です。これは標準JDBCのjava.sql.*パッケージに含まれています。

例外処理の例

SQLJアプリケーションに必要な基本的な例外処理の例です。このコードでは、try/catchブロックを含むmainメソッド、および例外発生時にSQLExceptionをスローする別のメソッドを宣言します。このコードを次に示します。

/* Import SQLExceptions class.  The SQLException comes from
JDBC. Executable #sql clauses result in calls to JDBC, so methods
containing executable #sql clauses must either catch or throw
SQLException.
*/
import java.sql.* ;
import oracle.sqlj.runtime.Oracle;

// iterator for the select

#sql iterator MyIter (String ITEM_NAME);

public class TestInstallSQLJ
{
//Main method
public static void main (String args[])
{
try {

// Set the default connection to the URL, user, and password
// specified in your connect.properties file
Oracle.connect(TestInstallSQLJ.class, "connect.properties");

TestInstallSQLJ ti = new TestInstallSQLJ();

// This method throws SQLException. Therefore, it ic called within a try block
ti.runExample();

} catch (SQLException e) {
System.err.println("Error running the example: " + e);
}

} //End of method main

//Method that runs the example
void runExample() throws SQLException
{
//Issue SQL command to clear the SALES table
#sql { DELETE FROM SALES };
#sql { INSERT INTO SALES(ITEM_NAME) VALUES ('Hello, SQLJ!')};

MyIter iter;
#sql iter = { SELECT ITEM_NAME FROM SALES };

while (iter.next()) {
System.out.println(iter.ITEM_NAME());
}
}
}

例外の処理

ここでは、SQLJアプリケーションにおける例外の処理および解析方法について説明します。実行時の例外の発生元は次のいずれかです。

- SQLJランタイム

- JDBCドライバ

- RDBMS

エラー・テキストの出力

前項の例では、SQL例外の捕捉方法およびエラー・メッセージの出力方法を示しました。このコードの一部を次に示します。

...
try {
...
} catch (SQLException e) {
System.err.println("Error running the example: " + e);
}
...

この結果、SQLExceptionオブジェクトからのエラー・テキストが出力されます。

エラー情報を取り出すには、SQLExceptionクラスのgetMessage()、getErrorCode()およびgetSQLState()メソッドを使用します。

この例に示したようにエラー・テキストを出力すると、エラー・メッセージの他にSQLExceptionなどのテキストも出力されます。

SQLの状態およびエラー・コードの取出し

java.sql.SQLExceptionクラスとサブクラスには、メソッドgetMessage()、getErrorCode()およびgetSQLState()があります。次のメソッドを使用すると、例外またはエラーの発生元およびこれらの実装方法に応じて、次のような補足情報が得られます。

- String getMessage()
SQLJランタイムまたはJDBCドライバで発生したエラーに対してこのメソッドを使用すると、接頭辞なしのエラー・メッセージが戻されます。RDBMSで発生したエラーに対してこのメソッドを使用すると、接頭辞としてORA番号の付いたエラー・メッセージが戻されます。

- int getErrorCode()
SQLJランタイムで発生したエラーに対しては、このメソッドを使用しても役立つ情報は戻されません。JDBCドライバまたはRDBMSで発生したエラーに対してこのメソッドを使用すると、ORA番号が5桁の整数として戻されます。

- String getSQLState()
SQLJランタイムで発生したエラーに対してこのメソッドを使用すると、SQLの状態を示す5桁のコードと文字列が戻されます。JDBCドライバで発生したエラーに対しては、このメソッドを使用しても役立つ情報は戻されません。RDBMSで発生したエラーに対してこのメソッドを使用すると、SQLの状態を示す5桁のコードが戻されます。アプリケーションには、NULLの戻り値を扱えるように適切なコードを含める必要があります。

次に、エラー・メッセージを出力し、さらにSQLの状態をチェックする例を示します。

...
try {
...
} catch (SQLException e) {
System.err.println("Error running the example: " + e);
String sqlState = e.getSQLState();
System.err.println("SQL state = " + sqlState);
}
...

SQLExceptionサブクラスの使用方法

さらに細かいエラー・チェックを実行するには、java.sql.SQLExceptionクラスのサブクラスを使用します。

SQLJでは、java.sql.SQLExceptionのサブクラスであるsqlj.runtime.NullExceptionクラスが提供されます。この例外は、Javaの基本型変数にNULLが戻される場合に使用できます。

バッチ処理が有効な環境では、標準java.sql.BatchUpdateExceptionサブクラスを使用できます。詳細は、「バッチ実行中のエラー状態」を参照してください。

SQLExceptionサブクラスを使用する際は、サブクラスの例外を捕捉してから、SQLExceptionを捕捉してください。次に例を示します。

...
try {
...
} catch (SQLNullException ne) {
System.err.println("Null value encountered: " + ne); }
catch (SQLException e) {
System.err.println("Error running the example: " + e); }
...

このようにするのは、サブクラスの例外もSQLExceptionとして捕捉できるからです。SQLExceptionを先に捕捉すると、サブクラスの例外に対して特別な処理が行われるコード部分まで進みません。

基本的なトランザクション制御

ここでは、データ更新を管理する方法について説明します。次の項目について説明します。

- トランザクションの概要

- 自動コミットと手動コミットとの違い

- 接続を定義する際の自動コミットの指定

- 既存の接続の自動コミットに対する変更

- 手動COMMITまたはROLLBACKの使用方法

- イテレータおよび結果セットに対するコミットおよびロールバックの影響

- セーブポイントの使用

関連項目:
「詳細なトランザクション制御」

トランザクションの概要

トランザクションは、Oracleで1つの単位として順次処理されるSQL操作です。次の処理を行った後のSQL実行文でトランザクションが開始されます。

- データベースへの接続

- COMMIT(データの更新を自動的にまたは手動でデータベースにコミットします)

- ROLLBACK(変更内容を取り消します)

トランザクションは、COMMIT操作またはROLLBACK操作で終了します。

注意:
Oracle Database 11g では、CREATE、ALTERなどのすべてのデータ定義言語(DDL)文に暗黙的なCOMMITが含まれます。これによって、DDL文のみでなく、コミットまたはロールバックされていない、実行済のすべてのデータ操作言語(DML)文(INSERT、DELETE、UPDATEなど)もコミットされます。

自動コミットと手動コミットとの違い

SQLJまたはJDBCを使用すると、自動でも手動でも、データの更新をコミットできます。どちらの場合も、新規のトランザクションはCOMMIT操作で開始されます。変更内容の自動コミットを指定するには、自動コミット・フラグを使用可能にします。これを行うには、SQLJ接続を定義するときに自動コミット・フラグを使用可能にするか、既存の接続の基になるJDBC接続オブジェクトのsetAutoCommit()メソッドを使用します。手動で制御するには、自動コミット・フラグを使用禁止にし、SQLJのCOMMIT文およびROLLBACK文を使用します。

自動コミットを使用可能にすると、手間が省けますが、細かい制御ができません。たとえば、変更内容のロールバックができません。また、自動コミット・モードでは、SQLJやJDBCの一部の機能を使用できません。そのため、バッチ更新やSELECT FOR UPDATE構文を使用する場合などは、自動コミット・フラグを使用禁止にする必要があります。

接続を定義する際の自動コミットの指定

Oracle.connect()またはOracle.getConnection()メソッドでDefaultContextのインスタンスを作成し、接続を定義すると、自動コミット・フラグがデフォルトでfalseに設定されます。ただし、これらのメソッドのシグネチャでは、このフラグを明示的に設定できます。自動コミット・フラグは、必ず最後のパラメータで指定します。

次に、DefaultContextをインスタンス化し、自動コミット・モードのデフォルト値falseを使用する例を示します。

Oracle.getConnection
("jdbc:oracle:thin:@localhost:1521/myservice", "scott", "tiger");

trueに設定するには、次のように指定します。

Oracle.getConnection
("jdbc:oracle:thin:@localhost:1521/myservice", "scott", "tiger", true);

関連項目:
「Oracleクラスについて」

コンストラクタで接続コンテキストのインスタンスを作成する場合は、DefaultContextクラスの場合でも、宣言済の接続コンテキスト・クラスの場合でも、自動コミットの設定を指定する必要があります。この設定のフラグも、次のように最後のパラメータで指定します。

DefaultContext ctx = new DefaultContext
("jdbc:oracle:thin:@localhost:1521/myservice", "scott", "tiger", false);

関連項目:
「DefaultContextクラスについて」

JDBCのConnectionインスタンスを直接作成する理由がある場合、自動コミット・フラグの設定は、プログラムがクライアント側で実行されるときはデフォルトでtrueになり、サーバー側で実行されるときはデフォルトでfalseになります。JDBCのConnectionインスタンスを直接作成するときに自動コミットの設定値は指定できませんが、その設定をsetAutoCommit()メソッドで変更することはできます。

注意:
自動コミット機能は、サーバー側のJDBC内部ドライバではサポートされていません。

既存の接続の自動コミットに対する変更

既存の接続の場合は、自動コミット・フラグの設定変更は通常不要ですが、必要な場合は変更できます。変更するには、基になるJDBC接続オブジェクトのsetAutoCommit()メソッドを使用します。

基になるJDBC接続オブジェクトを取得するには、SQLJの接続コンテキスト・インスタンスのgetConnection()メソッドを使用します。つまり、DefaultContextクラスのインスタンスのメソッドを使用するか、または宣言済の接続コンテキスト・クラスのインスタンスのメソッドを使用します。

この2つの操作を一度に行うには、次のように指定します。

ctx.getConnection().setAutoCommit(false);

または

ctx.getConnection().setAutoCommit(true);

この例では、ctxをSQLJの接続コンテキストのインスタンスとしています。

注意:
トランザクションの処理中は、自動コミットの設定を変更しないでください。

手動COMMITまたはROLLBACKの使用方法

自動コミット・フラグを使用禁止にした場合は、データの更新を手動でコミットする必要があります。最終のCOMMIT操作以降に加えられた変更内容をコミットするには、次のようにSQLJのCOMMIT文を使用します。

#sql { COMMIT };

最終のCOMMIT操作以降に加えられた変更内容のロールバックを行うには、次のようにSQLJのROLLBACK文を使用します。

#sql { ROLLBACK };

注意:

- 自動コミットを使用可能にしたときは、COMMITコマンドやROLLBACKコマンドを使用しないでください。使用した場合は、意図しない動作またはSQL例外が発生します。

- 指定したセーブポイントをロールバックすることもできます。「セーブポイントの使用」を参照してください。

- Oracle SQL構文のすべてのDDL文には、暗黙的なCOMMIT操作が組み込まれています。SQLJには、この機能はありません。DDL文は標準のOracle SQL規則に従います。

- 自動コミット・モードがオフの場合に、クライアント・アプリケーションから接続コンテキスト・インスタンスをクローズすると、最後のCOMMIT操作後に行った変更がコミットされます(ただし、接続コンテキスト・インスタンスをKEEP_CONNECTIONでクローズした場合を除きます)。詳細は、「共有接続の終了」を参照してください。

イテレータおよび結果セットに対するコミットおよびロールバックの影響

COMMITおよびROLLBACK操作は、オープンしている結果セットとイテレータには反映されません。結果セットおよびイテレータはオープンしたままになります。通常それぞれの内容はSELECT文を実行したときのデータベースの状態が引き続き反映されています。

注意:
イテレータ・クラスをsensitivity=SENSITIVEと宣言している場合は例外です。この場合、イテレータをウィンドウ・サイズの外部でスクロールすると、基になる結果セットへの変更が表示されます。スクロール可能なイテレータの詳細は、「スクロール可能なイテレータ」を参照してください。基になるスクロール可能な結果セットの詳細は、『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

UPDATE、INSERTおよびDELETE文をSELECT文の後に実行した場合も同じです。これらの文を実行しても、オープンしている結果セットとイテレータの内容は変わりません。

SELECT、UPDATEおよびCOMMITの各操作をこの順に実行した場合を考えてください。UPDATEおよびCOMMITを実行しても、sensitiveではない結果セットやイテレータの内容は、SELECT文で設定されたときの状態のまま変更されません。

さらに、UPDATE、SELECTおよびROLLBACKの操作をこの順に実行したとします。SELECTで移入されたsensitiveでない結果セットやイテレータには、依然として更新データが格納されており、その後に実行されたROLLBACKの影響は受けません。

セーブポイントの使用

JDBC 3.0の仕様では、セーブポイントのサポートが追加されました。セーブポイントとは、トランザクション全体をロールバックするのではなく、必要に応じてトランザクション内でロールバックできるように定義された位置です。セーブポイントとは、SAVEPOINT文が出現するトランザクション内の位置です。

Oracle9i データベース リリース2(9.2)のSQLJで、セーブポイントをサポートするためのOracle固有の構文が導入されました。Oracle Database 11g のSQLJでは、ISO SQLJ規格のセーブポイント構文のサポートが追加されています。

ISO SQLJ規格のSQLJセーブポイント構文のサポート

ISO SQLJ規格の構文では、SAVEPOINT文で文字列リテラルを使用して、セーブポイントの名前を指定します。これを行うには、次の構文を使用します。

#sql { SAVEPOINT savepoint1 };

そのセーブポイントまで変更をロールバックする場合、次のように、後でROLLBACK TO文にその指定した名前を指定できます。

#sql { ROLLBACK TO savepoint1 };

セーブポイントが不要になった場合、RELEASE SAVEPOINT文を使用します。

#sql { RELEASE SAVEPOINT savepoint1 };

セーブポイントは、SQLJ実行コンテキストに保存されます。SQLJ実行コンテキストには、これらの3つの文の機能に相当するメソッドがあります。

関連項目:
「セーブポイント・メソッド」

COMMIT操作によってトランザクションが終了するため、トランザクション内のセーブポイントもすべて解放されます。

Oracle SQLJのセーブポイント構文

ISO SQLJ規格の構文に加えて、次に示すOracle固有のセーブポイントの構文がサポートされています。Oracle構文では、文字列リテラルではなく、文字列のホスト式が使用されていることに注意してください。

セーブポイントを設定するには、次の構文を使用します。

#sql { SET SAVEPOINT :savepoint };

この例のホスト式、savepoint は、セーブポイントの名前をJavaのStringで指定する変数です。

セーブポイントまでロールバックするには、次の構文を使用します。

#sql { ROLLBACK TO :savepoint };

セーブポイントを解放するには、次のSQLJ文を使用します。

#sql { RELEASE :savepoint };

注意:
Oracle固有の構文は、下位互換性のために引き続きサポートされています。Oracle構文とISO SQLJ規格の構文の次の相違点に注意してください。

- Oracle構文は、文字列リテラルではなく、文字列変数をとります。

- Oracle構文では、SAVEPOINTのかわりにSET SAVEPOINTを使用します。

- Oracle構文では、RELEASE SAVEPOINTのかわりにRELEASEを使用します。

概要: 簡単なSQLJコード

これまでに説明したSQLJ実行文の特長と機能について要点を把握するには、簡潔で包括的なプログラムを試してみるのが一番効果的な方法です。ここでは、2つの例を示します。

最初の例では、操作を1つずつ示してから、全体を示します。この例では、SELECT INTO文を使用して従業員表の2つの列に対して単一行の問合せを実行します。この例を実行する場合は、connect.propertiesファイルのパラメータを、適切なデータベースに接続できる設定に変更する必要があります。

2番目の例は多少複雑です。SQLJのイテレータを使用して複数行問合せを実行します。

必要なクラスのインポート

必要なJDBCまたはSQLJパッケージをすべてインポートします。少なくとも、java.sqlパッケージ内のクラスがいくつか必要です。

import java.sql.*;

java.sqlパッケージ内のクラスを、必ずしもすべて使用するわけではありません。主に使用するクラスとしては、java.sql.SQLExceptionと、明示的に参照するクラスがあります。たとえば、java.sql.Dateやjava.sql.ResultSetです。

Oracleクラスには、次のパッケージが必要です。通常、DefaultContextオブジェクトをインスタンス化し、デフォルト接続を確立するときに、このクラスを使用します。

import oracle.sqlj.runtime.*;

SQLJのランタイム・クラスをコード中に直接使用する場合は、次のパッケージをインポートします。

import sqlj.runtime.*;
import sqlj.runtime.ref.*;

ただし、コード中にSQLJのランタイム・クラスを直接使用しない場合でも、ランタイム・クラスをCLASSPATHに指定するのみで十分です。

重要なランタイム・クラスとしては、sqlj.runtimeパッケージのResultSetIteratorおよびExecutionContextと、sqlj.runtime.refパッケージのDefaultContextなどがあります。

JDBCドライバの登録およびデフォルト接続の設定

デフォルトの接続を設定するには、static Oracle.connect()メソッドを使用するコンストラクタで、SimpleExampleクラスを宣言します。この結果、Oracle JDBCドライバの登録も行われます。

ここでは、URL、ユーザー名およびパスワードをconnect.propertiesファイルから取得するconnect()のシグネチャを使用します。このファイルの例は、ORACLE_HOME/sqlj/demoディレクトリおよび「ランタイム接続の設定」にあります。

public class SimpleExample {

public SimpleExample() throws SQLException {
// Set default connection (as defined in connect.properties).
Oracle.connect(getClass(), "connect.properties");
}

例外処理の設定

main()を作成します。このメソッドからSimpleExampleコンストラクタをコールし、try/catchブロックをセットアップします。このブロックでは、runExample()メソッドにより発生したSQL例外を処理します。このアプリケーションの実際の処理は、このメソッドが行います。

...
public static void main (String [] args) {

try {
SimpleExample o1 = new SimpleExample();
o1.runExample();
}
catch (SQLException ex) {
System.err.println("Error running the example: " + ex);
}
}
...

接続を終了するには、try/catchブロックをfinally句の内部に使用します。SQL例外の場合にfinally句がtry/catchブロック内部に使用されていないことが前提です。

finally
{
try { Oracle.close(); } catch(SQLException ex) {...}
}

ホスト変数のセットアップ、SQLJ句の実行、結果の処理

次の処理を行うrunExample()メソッドを作成します。

1. main()メソッドに対してSQL例外をスローし、処理させます。

2. Javaのホスト変数を宣言します。

3. SQLJ句を実行します。Javaのホスト変数が埋込みSELECT文にバインドされ、データがホスト変数に取り込まれます。

4. 結果を出力します。

このメソッドのコードは次のようになります。

void runExample() throws SQLException {

System.out.println( "Running the example--" );

// Declare two Java host variables--
Float salary;
String empname;

// Use SELECT INTO statement to execute query and retrieve values.
#sql { SELECT ename, sal INTO :empname, :salary FROM emp
WHERE empno = 7499 };

// Print the results--
System.out.println("Name is " + empname + ", and Salary is " + salary);
}
}    // Closing brace of SimpleExample class

前述のコード例では、Javaのホスト変数としてsalaryとempnameが宣言されています。その次のSQLJ句の処理では、emp表のename列とsal列から選択されたデータが、ホスト変数に格納されます。最後に、salaryとempnameの値が出力されます。

このSELECT文では、emp表から選択できる行は1行のみです。WHERE句のempno列が表の主キーになっているためです。

SELECT INTOを使用した単一行問合せの例

ここでは、前に1つずつ順を追って説明した内容をSimpleExampleクラスを使用して総復習します。次の例は単一行問合せの例であるため、イテレータは使用しません。

// Import SQLJ classes:
import sqlj.runtime.*;
import sqlj.runtime.ref.*;
import oracle.sqlj.runtime.*;

// Import standard java.sql package:
import java.sql.*;

public class SimpleExample {

public SimpleExample() throws SQLException {
// Set default connection (as defined in connect.properties).
Oracle.connect(getClass(), "connect.properties");
}

public static void main (String [] args) throws SQLException {

try {
SimpleExample o1 = new SimpleExample();
o1.runExample();
}
catch (SQLException ex) {
System.err.println("Error running the example: " + ex);
}
}

finally
{
try { Oracle.close(); } catch(SQLException ex) {...}
}

void runExample() throws SQLException {

System.out.println( "Running the example--" );

// Declare two Java host variables--
Float salary;
String empname;

// Use SELECT INTO statement to execute query and retrieve values.
#sql { SELECT ename, sal INTO :empname, :salary FROM emp
WHERE empno = 7499 };

// Print the results--
System.out.println("Name is " + empname + ", and Salary is " + salary);
}
}

名前付きイテレータの設定

次の例は、前の例がベースになっていますが、それに加えて名前付きイテレータを使用し、複数行問合せを実行します。

最初に、イテレータ・クラスを宣言します。NULL値が戻される可能性がある場合は、基本型intとfloatではなくて、オブジェクト型IntegerとFloatを使用してください。

#sql iterator EmpRecs(
int empno,       // This column cannot be null, so int is OK.
// (If null is possible, use Integer.)
String ename,
String job,
Integer mgr,
Date hiredate,
Float sal,
Float comm,
int deptno);

次にEmpRecsクラスをインスタンス化し、問合せ結果を移入します。

EmpRecs employees;

#sql employees = { SELECT empno, ename, job, mgr, hiredate,
sal, comm, deptno FROM emp };

次に、イテレータのnext()メソッドで結果を出力します。

while (employees.next())  {
System.out.println( "Name:       " + employees.ename() );
System.out.println( "EMPNO:      " + employees.empno() );
System.out.println( "Job:        " + employees.job() );
System.out.println( "Manager:    " + employees.mgr() );
System.out.println( "Date hired: " + employees.hiredate() );
System.out.println( "Salary:     " + employees.sal() );
System.out.println( "Commission: " + employees.comm() );
System.out.println( "Department: " + employees.deptno() );
System.out.println();
}

最後に、イテレータを終了します。

employees.close();

名前付きイテレータを使用した複数行問合せの例

この例では、名前付きイテレータを使用して複数行問合せを行い、従業員表から複数のデータ列を選択します。

この例は、名前付きイテレータを使用していることを除けば、前に示した単一行問合せの例と概念はほとんど同じです。

// Import SQLJ classes:
import sqlj.runtime.*;
import sqlj.runtime.ref.*;
import oracle.sqlj.runtime.*;

// Import standard java.sql package:
import java.sql.*;

// Declare a SQLJ iterator.
// Use object types (Integer, Float) for mgr, sal, And comm rather
// than primitive types to allow for possible null selection.

#sql iterator EmpRecs(
int empno,       // This column cannot be null, so int is OK.
// (If null is possible, Integer is required.)
String ename,
String job,
Integer mgr,
Date hiredate,
Float sal,
Float comm,
int deptno);

// This is the application class.
public class EmpDemo1App {

public EmpDemo1App() throws SQLException {
// Set default connection (as defined in connect.properties).
Oracle.connect(getClass(), "connect.properties");
}

public static void main(String[] args) {

try {
EmpDemo1App app = new EmpDemo1App();
app.runExample();
}
catch( SQLException exception ) {
System.err.println( "Error running the example: " + exception );
}
}

finally
{
try { Oracle.close(); } catch(SQLException ex) {...}
}

void runExample() throws SQLException  {
System.out.println("\nRunning the example.\n" );

// The query creates a new instance of the iterator and stores it in
// the variable 'employees' of type 'EmpRecs'.  SQLJ translator has
// automatically declared the iterator so that it has methods for
// accessing the rows and columns of the result set.

EmpRecs employees;

#sql employees = { SELECT empno, ename, job, mgr, hiredate,
sal, comm, deptno FROM emp };

// Print the result using the iterator.

// Note how the next row is accessed using method 'next()', and how
// the columns can be accessed with methods that are named after the
// actual database column names.

while (employees.next())  {
System.out.println( "Name:       " + employees.ename() );
System.out.println( "EMPNO:      " + employees.empno() );
System.out.println( "Job:        " + employees.job() );
System.out.println( "Manager:    " + employees.mgr() );
System.out.println( "Date hired: " + employees.hiredate() );
System.out.println( "Salary:     " + employees.sal() );
System.out.println( "Commission: " + employees.comm() );
System.out.println( "Department: " + employees.deptno() );
System.out.println();
}

// You must close the iterator when it's no longer needed.
employees.close() ;
}
}

Oracle固有コード生成(プロファイルなし)

このマニュアルでは、全体にわたって一般的かつ標準的なSQLJランタイム・レイヤーおよびSQLJプロファイルについて説明しています。ただし、Oracle SQLJ実装では、SQLJランタイムをコールするISO SQLJ規格コードではなく、Oracle JDBCドライバを直接コールするOracle固有コードがデフォルトで生成されます。Oracle固有コード生成の場合、プロファイル・ファイルはなく、SQLJランタイム・レイヤーの役割はプログラム実行時に大幅に縮小されます。Oracle固有コードでは、すべてのOracle固有の拡張機能がサポートされています。

コード生成は、SQLJトランスレータの-codegenオプションによって決まります。Oracle固有コード生成のデフォルト設定は、-codegen=oracleです。また、ISO SQLJ規格に従ったコード生成を行うために、-codegen=isoを設定することもできます。

関連項目:
「コードの生成(-codegen)」

ここでは、次の項目について説明します。

- Oracle固有コード生成でのコード上の考慮事項と制限事項

- Oracle固有コード生成時のSQLJ使用方法の変更

- Oracle固有コード生成でのサーバー側の考慮事項

- Oracle固有コード生成のメリットとデメリット

Oracle固有コード生成でのコード上の考慮事項と制限事項

Oracle固有コード生成が使用されるSQLJアプリケーションのコーディング時には、次のプログラミング上の考慮事項および制限に注意してください。

- デフォルト以外の文キャッシュ・サイズを使用する場合は、Oracleカスタマイザのstmtcacheオプションが使用できないため、コードに適切なメソッド・コールを記述する必要があります。「Oracle固有コード生成時のSQLJ使用方法の変更」を参照してください。

- 同じアプリケーションに、Oracle固有生成コードとISO SQLJ規格生成コードを混在しないでください。ただし、Oracle固有コードおよびISO SQLJ規格コードが同じ接続を共有する必要がある場合は、次のいずれかを実行します。

- Oracle固有コードおよびISO標準コードが、必ず異なるSQLJ実行コンテキスト・インスタンスを使用するようにします。SQLJ実行コンテキストの詳細は、「実行コンテキスト」を参照してください。

- トランザクション境界(手動のCOMMIT文またはROLLBACK文)を2種類のコードの間に配置します。

コードの混在に関するこの制限事項は、あるセッションで実行中のすべてのJavaコードが同じJDBC接続とSQLJ接続コンテキストを使用するので、サーバー側のコードで特に重要になります。

関連項目:
「Oracle固有コード生成でのサーバー側の考慮事項」

- データベースから値が戻されるとき、パラメータ表現での副作用に頼らないでください。Oracle固有コード生成では、OUTパラメータ、IN OUTパラメータ、SELECT INTO変数、またはSQL文の戻り引数を評価するための一時変数が作成されません。
たとえば、次のような文は使用しないでください。

#sql { SELECT * FROM EMP INTO :(x[i++]), :(f_with_sideffect()[i++]),
:(a.b[i]) };

または

#sql x[i++] = { VALUES f(:INOUT (x[i++]), :OUT (f_with_sideffect())) };

引数の評価は、生成コードの適切な場所で実行されます。これによって、ISO SQLJ規格に従って評価が実施される場合と、動作が異なることになります。

関連項目:
「Java式の実行時評価」および「Java式の実行時評価の例(ISOコード生成)」

- Oracleオブジェクト機能の型マップは、対応するJavaクラスでjava.sql.SQLDataインタフェースが実装されることを前提としています(その他の点ではJPublisherで生成されたJavaクラスには型マップは必要ない場合)。Oracleオブジェクト機能の型マップを使用する場合、イテレータ宣言と接続コンテキスト宣言で同じ型マップを指定する必要があります。これは、with句で指定します。
たとえば、接続コンテキスト・クラスを宣言する場合、次のようにします。

#sql context TypeMapContext with (typeMap="MyTypeMap");

また、この接続コンテキスト・クラスのインスタンスを使用するSQLJ文からイテレータ・インスタンスを移入するには、次のようにします。

TypeMapContext tmc = new TypeMapContext(...);
...
MyIterator it;
#sql [tmc] it = ( SELECT pers, addr FROM tab WHERE ...);

イテレータ宣言では同じ型マップを指定する必要があります。次のようにします。

#sql iterator MyIterator with (typeMap="MyTypeMap")
(Person pers, Address addr);

関連項目:
「カスタムJavaクラスの要件」および「WITH句宣言」

注意:
この制限事項の理由は、Oracle固有コード生成の場合、イテレータを取得するすべてのメソッドが変換時に完全にOracle JDBCコールとして生成されているためです。適切なコールを生成するには、イテレータがある特定の型マップで使用されるかどうかをSQLJトランスレータで把握する必要があります。

Oracle固有コード生成時のSQLJ使用方法の変更

以前にOracleカスタマイザのオプションとしてのみ使用可能なオプションで、Oracle固有コード生成でも便利なオプションがあります。プロファイルのカスタマイズはOracle固有コード生成には適用できないため、これらのオプションは他の方法で使用できるようになりました。

文キャッシュのサイズを変更したり、Oracle固有コードの生成時に文のキャッシングを無効化するには、カスタマイザのstmtcacheオプションではなく、メソッド・コールをコードに使用します。sqlj.runtime.ref.DefaultContextクラスと同様に、宣言するすべての接続コンテキスト・クラスには、現在次のstaticメソッドがあります。

- setDefaultStmtCacheSize(int)

- int getDefaultStmtCacheSize()

また、次のインスタンス・メソッドがあります。

- setStmtCacheSize(int)

- int getStmtCacheSize()

デフォルトで、文のキャッシングを使用できます。

関連項目:
「文のキャッシング」

さらに、次のオプションは、Oracleカスタマイザのオプションと同様に、フロントエンドのOracle SQLJトランスレータとして使用できます。

- -optcols: パフォーマンスが最適化されるようにイテレータ列型およびサイズ定義を有効化するためのオプション。

- -optparams: JDBCリソース割当てが最適化されるようにパラメータ・サイズ定義を有効化するためのオプション。このオプションは、optparamdefaultsと併用されます。

- -optparamdefaults: 特定のデータ型に対してパラメータ・サイズのデフォルトを設定するためのオプション。このオプションは、optparamsと併用されます。

- -fixedchar: WHERE句に関して、空白埋めを考慮したCHAR比較を有効にするためのオプション。

関連項目:
「コード生成、最適化およびCHAR比較のオプション」

次の点に注意してください。

- オンラインのセマンティクス・チェックを使用している場合のみ(SQLJトランスレータの-user、-passwordおよび-urlオプションを使用して、変換時にデータベース接続を要求している場合)、-optcolsオプションを使用します。

- -optcols、-optparamsおよび-optparamdefaultsオプションの機能とデフォルト値は、カスタマイザのオプションと同じです。

Oracle固有コード生成でのサーバー側の考慮事項

SQLJコードをサーバーで実行する場合は、次の点を考慮します。

- サーバー側SQLJトランスレータでは、ISO標準生成コードがサポートされなくなりました。サーバーにロードされコンパイルされたSQLJソース・コードは、常にデフォルトの-codegen=oracle設定で変換されます。
したがって、ISO標準生成コードをサーバーで使用するには、クライアント上でSQLJコードを変換し、コンパイルしてから、個々のコンポーネントをサーバーにロードする必要があります。

関連項目:
「クライアント側でのSQLJソースの変換とコンポーネントのロード」

- Oracle固有生成コードとISO標準生成コードの混在に対する注意事項は、Javaストアド・プロシージャまたはストアド・ファンクションをコールするサーバー側Javaコードに当てはまります。このストアド・プロシージャがPL/SQLラッパーからコールされた場合でも同様です。これは再帰的コールインにも当てはまります。デフォルトで、ExecutionContextオブジェクトは、コール側のモジュールとコールされる側のモジュールで共有されています。そのため、両方のモジュールが同じ-codegen設定で変換される必要があります。
ISO標準コード生成で変換したコードと連係して動作するには、次の例のように、実行コンテキスト・インスタンスを明示的にインスタンス化することをお薦めします。

public static method() throws SQLException
{
Execution Context ec = new ExecutionContext();
...
try {
...
#sql [ec] { SQL operation };
...
} finally { ec.close(); }
}

注意:
明示的なExecutionContextインスタンスを使用する際にリソースのリークを回避するには、この例のように、close()メソッドを使用します。

関連項目:
「Oracle固有コード生成でのコード上の考慮事項と制限事項」

Oracle固有コード生成のメリットとデメリット

Oracle固有コード生成を使用すると、ISO標準コード生成と比較して次のメリットがあります。

- アプリケーションの実行がより効率的になります。コードではJDBC Application Programming Interface (API)を直接コールするため、ランタイムのパフォーマンスがただちにJDBCレベルになります。中間的なSQLJランタイム・レイヤーの役割は、プログラム実行時に大幅に縮小されます。

- アプリケーションのサイズが小さくなります。

- プロファイル・ファイル(.ser)は生成されません。変換されたアプリケーションをデータベースにロードするか、別のシステムに移植すると、コンポーネントが少ないため、これは特に便利です。

- プロファイルのカスタマイズ処理がないので、変換が高速になります。

- 実行時に、Oracle SQLJランタイムとOracle JDBCドライバは同じ文キャッシュ・リソースを使用するため、Oracle SQLJランタイムとOracle JDBCドライバ間のリソースのパーティション化が不要です。

- プロファイル・ファイルではなくJavaクラス・ファイルにSQL固有情報があると、潜在的なセキュリティの問題を回避できます。

- 静的SQLコードの実行のために考慮されている拡張機能など、将来サポートされるOracle JDBCのパフォーマンス強化のメリットを活用するために、コードを再度記述する必要はありません。Oracle SQLJトランスレータの将来のリリースではこれが自動的に処理できるようになります。

- ブラウザ環境に完全な移植性が備わるので、Javaリフレクションが実行時に使用されることが少なくなります。

ただし、いくつかのデメリットがあります。

- Oracle固有の生成コードは、汎用JDBCプラットフォームには移植できません。

- プロファイル固有の機能は使用できません。たとえば、後からOracleカスタマイザ・ハーネスの-debug、-verifyおよび-printオプションを使用してカスタマイズを実行することができません。

関連項目:
「カスタマイザ・ハーネスの接続用オプション」および「デバッグ用のAuditorInstallerカスタマイザ」

ISO標準コード生成

ここでは、次の項目について説明します。

- ISO標準コード生成用環境の要件

- SQLJトランスレータとSQLJランタイム

- SQLJプロファイル

- SQLJ変換処理

- トランスレータ入出力の概要

- SQLJランタイム処理

- デプロイメント例

ISO標準コード生成用環境の要件

Oracle SQLJ実装では、デフォルトで、SQLJランタイムをコールするISO SQLJ規格コードを生成するのではなく、Oracle JDBCドライバを直接コールするOracle固有コードを生成します。ISO標準コード生成の一般的な環境設定を次に示します。

- SQLJコード生成: -codegen=iso

- SQLJ変換ライブラリ: translator.jar

- SQLJランタイム・ライブラリ: JDK 1.5.xおよびOracle JDBCドライバ 11g リリース2 (11.2)を含むruntime12.jar

- JDBCドライバ: Oracle 11gリリース2(11.2)

- JDKバージョン: 1.5.x

SQLJトランスレータとSQLJランタイム

ここでは、ISO標準コード生成の場合に見られるOracle SQLJ実装の特徴について説明します。

- SQLJトランスレータ: .javaファイルに加え、トランスレータによってISO標準コード生成用に1つ以上のSQLJプロファイルも生成されます。これらのプロファイルには、埋込みSQL操作についての情報が含まれます。SQLJでは、その後Javaコンパイラが自動的に起動され、.javaファイルから.classファイルが生成されます。

関連項目:
「SQLJトランスレータ」

- SQLJランタイム: ISO標準コード生成の場合、SQLJランタイムによって、JDBCドライバを介してデータベースにアクセスすることで、SQL操作の必要な処理が実装されます。汎用のISO SQLJ標準では、SQLJランタイムはJDBCドライバを使用してデータベースにアクセスする必要はありません。

関連項目:
「SQLJランタイム」

トランスレータとランタイムに加え、カスタマイザと呼ばれるコンポーネントも役割を担います。カスタマイザを使用すると、特定のデータベースの実装、ベンダー固有の機能およびデータ型に合わせてSQLJプロファイルが調整されます。デフォルトでは、ISO標準コードに対して、SQLJフロントエンドがOracleカスタマイザを起動し、Oracle DatabaseインスタンスとOracle固有の機能およびデータ型に合わせてプロファイルを調整します。

変換時にOracleカスタマイザを使用すると、アプリケーションの実行時にSQLJランタイムおよびOracle JDBCドライバが必要になります。

注意:
Oracle Database 10g リリース1(10.1)以上では、Oracle JDBCドライバのみがSQLJでサポートされています。

SQLJプロファイル

ISO標準コード生成の場合、SQLJプロファイルとは、SQLJトランスレータによって生成される、シリアライズされたJavaリソースまたはクラスのことで、埋込みSQL文に関する詳細情報が記述されています。トランスレータはこれらのプロファイルを作成します。次に、トランスレータのオプション設定に従って、プロファイルをシリアライズしてバイナリ・リソース・ファイルに出力するか、.classファイルに出力します。

ここでは、次の項目について説明します。

- プロファイルの概要

- バイナリ移植性

プロファイルの概要

ISO標準コードでは、SQLJ実行文に埋込みSQL操作を実装する場合にSQLJプロファイルを使用します。プロファイルの内容は、SQL操作およびアクセスするデータの型とモードに関する情報です。プロファイルはエントリの集合であり、各エントリが1つのSQL操作に対応します。各エントリでは、対応するSQL操作が十分に指定され、この指示の処理時に使用される各パラメータが記述されています。

SQLJでは、アプリケーション内の接続コンテキスト・クラスごとにプロファイルが生成され、各接続コンテキスト・クラスはデータベース操作で使用する特定のSQLエンティティのセットに対応しています。デフォルトの接続コンテキスト・クラスが1つあり、さらにクラスを宣言できます。ISO SQLJ規格では、プロファイルを標準の形式および内容にする必要があります。そのため、アプリケーションでベンダー固有の拡張機能を使用する場合は、プロファイルのカスタマイズが必要になります。デフォルトの設定では、これが自動的に行われ、Oracle固有の拡張機能を使用するようにプロファイルがカスタマイズされます。

プロファイルをカスタマイズすると、次の利点があります。

- ベンダー固有のデータ型とSQL構文を使用できます。たとえば、Oracleカスタマイザを使用して、変換済SQLJコードのJDBC標準PreparedStatementメソッド・コールをOraclePreparedStatementメソッド・コールにマッピングすることにより、Oracle拡張型がサポートされます。

- ベンダー固有の最適化によってパフォーマンスを向上できます。

注意:

- デフォルトの設定では、SQLJプロファイルの拡張子が.serになりますが、すべての.serファイルがプロファイルであるとは限りません。その他のシリアライズされたオブジェクトにもこの拡張子を使用できるため、SQLJプログラム・ユニットでプロファイル以外のシリアライズされたオブジェクトを使用できます。必要に応じて、プロファイルは.serファイルではなく.classファイルにも変換できます。

- ソース・コード中にSQLJ実行文を記述しないかぎり、SQLJプロファイルは生成されません。

バイナリ移植性

SQLJで生成したプロファイル・ファイルは、バイナリ移植性をサポートしています。つまり、プロファイル・ファイルをそのまま異種データベースまたは他の環境に移植して使用できます(ただし、ベンダー固有のデータ型または機能を使用していない場合に限ります)。生成した.classファイルについても同様です。

SQLJ変換処理

ISO標準コード生成(-codegen=iso)の場合は、トランスレータがSQLJソース・コードを処理し、SQL操作をSQLJランタイム・コールに変換し、Java出力コードと1つ以上のSQLJプロファイルを生成します。プロファイルは、ソース・コード中の接続コンテキスト・クラスごとに別個に生成されますが、これは操作で使用される相互に関係するSQLエンティティのセットごとに、通常は異なる接続コンテキスト・クラスが使用されるためです。

生成されたJavaコードは.java出力ファイルに保存されます。次の内容がこのファイルに出力されます。

- .sqljソース・ファイル内のクラス定義とJavaコード。

- SQLJイテレータおよび接続コンテキストの宣言に基づいて生成されたクラス定義。

関連項目:
「SQLJ宣言の概要」

- 専用クラス(プロファイルキー・クラス)のクラス定義。SQLJでは、このクラスは、プロファイルとともに生成され、使用されます(ISO標準SQLJコード生成のみ)。

- SQLJランタイムへのコール。埋込みSQL操作のアクションを実装します。

生成されたプロファイルには、実行するアクション、操作するデータ型、アクセスする表など、SQLJソース・コード中のすべての埋込みSQL文に関する情報が格納されます。アプリケーションを実行すると、SQLJランタイムはプロファイルにアクセスしてSQL操作を取り出し、JDBCドライバに渡します。

プロファイルは、デフォルトでシリアライズ・リソース・ファイル(.ser)に出力されますが、オプションで、変換時に.serファイルを.classファイルに変換できます。

生成されたJavaソース・ファイルがコンパイルされ、Javaの.classファイルが生成されます。これには、定義される各クラス、各SQLJ宣言、プロファイルキー・クラスに対する.classファイルが含まれます。次に、JVMでOracleカスタマイザまたは指定したその他のカスタマイザを起動して、生成したプロファイルをカスタマイズします。

関連項目:
「トランスレータの内部操作」

SQLJの一般的な注意

ISO固有のコード生成でSQLJアプリケーションを変換および実行する場合は、次の点を考慮してください。

- Oracle固有コード生成では、コマンドラインで既存の.javaファイルをコンパイルして、型変換可能にすることに加え、次を実行する必要があります。

- 既存のプロファイルのカスタマイズ

- プロファイルを含むJava Archive(JAR)ファイルのカスタマイズ

関連項目:
「トランスレータのコマンドラインとプロパティ・ファイル」

- ソース・コードにSQLJ実行可能文が含まれる場合のみ、SQLJによってプロファイルおよびプロファイルキー・クラスが生成されます。

- 変換時にOracleカスタマイザを使用する場合は、アプリケーションの実行時にOracle SQLJランタイムおよびOracle JDBCドライバが必要になります(コードでOracle固有の機能を使用しない場合でも必要です)。変換時に-profile=falseを指定して、Oracle固有のカスタマイズを省略すると、これを回避できます。

トランスレータ入出力の概要

Oracle固有のコード生成の場合に、SQLJトランスレータが入力としてとるもの、出力として生成するもの、およびその出力先について説明しました。ここでは、同じ項目について、ISO標準のコード生成の観点で説明します。

- トランスレータへの入力

- トランスレータの出力

- ファイルの出力先

関連項目:
「トランスレータ入出力の概要」

トランスレータへの入力

Oracle固有のコード生成の場合と同様に、SQLJトランスレータは、入力として1つ以上の.sqljソース・ファイルをとります。このソース・ファイルはコマンドラインで指定できます。メインの.sqljファイルの名前は、そこで定義されるPublicクラス(ある場合)または定義された最初のクラスに基づきます。

関連項目:
「トランスレータへの入力」

トランスレータの出力

変換処理では、アプリケーション内の.sqljファイルごとにJavaソース・ファイルが生成されます。また、ISO標準コード生成の場合、アプリケーションのプロファイルは、1つ以上生成されます(ソース・コードにSQLJ実行文があるとき)。

SQLJでは、次のJavaソース・ファイルとアプリケーション・プロファイルが生成されます。

関連項目:
「トランスレータの出力」

- Oracle固有のコード生成の場合と同様に、Javaソース・ファイルは.sqljファイルと同じベース名の.javaファイルです。

- アプリケーションのプロファイル・ファイル(ある場合)には、SQLJアプリケーションのSQL操作に関する情報が含まれます。プロファイルは、アプリケーションで使用する接続クラスごとに1つ生成されます。プロファイルの名前は、メインの.sqljファイルと同じベース名になり、次の拡張子が付きます。

_SJProfile0.ser
_SJProfile1.ser
_SJProfile2.ser
...

たとえば、MyClass.sqljの場合は、トランスレータによって次のプロファイル・ファイルが生成されます。

MyClass_SJProfile0.ser

.serファイル拡張子は、プロファイルがシリアライズされていることを示します。.serファイルはバイナリ・ファイルです。

注意:
トランスレータ・オプション-ser2classを指定すると、トランスレータによって生成されるプロファイル・ファイルが.serファイルではなく.classファイルになります。ファイル名の拡張子以外の部分は、同じになります。

Oracle固有のコード生成のコンパイル手順と同様に、Javaソース・ファイルを複数のクラス・ファイルにコンパイルすると、.sqljソース・ファイルに定義されたクラスごとに、1つの.classファイルが生成されます。ただし、ISOコード生成の場合は、トランスレータがSQL操作を実装するためにプロファイルとともに生成して使用するプロファイルキー・クラスと呼ばれるクラスに対しても、1つの.classファイルが生成されます。SQLJのイテレータまたは接続コンテキストを宣言した場合は、さらに.classファイルが生成されます。また、Oracle固有コード生成と同様に、コード中に内部クラスまたは無名クラスが宣言されている場合は、それらのクラスごとに.classファイルが個別に生成されます。

関連項目:
「SQLJ宣言の概要」

これらの.classファイルには、次の名前が付けられます。

- Oracle固有のコード生成と同様に、定義された各クラスのクラス・ファイル名は、クラス名および.class拡張子で構成されます。

- トランスレータで生成されたプロファイルキー・クラスは、メインの.sqljファイルのベース名と次の文字列から構成される名前が付けられます。

_SJProfileKeys

つまり、クラス・ファイルの拡張子は、次のような名前になります。

_SJProfileKeys.class

たとえば、MyClass.sqljの場合は、トランスレータとコンパイラによって次のクラス・ファイルが生成されます。

MyClass_SJProfileKeys.class

- Oracle固有のコード生成と同様に、トランスレータを実行すると、イテレータ・クラスと接続コンテキスト・クラスに、宣言方法に従って名前が付けられます。

カスタマイズ処理によってプロファイルが変更されますが、追加出力はありません。

関連項目:
「プロファイルのカスタマイズ(ISOコード生成の場合)」

注意:
必ずしもSQLJプロファイルまたはプロファイルキー・クラスを直接参照する必要はありません。これらは、すべて自動的に処理されます。

ファイルの出力先

Oracle固有のコード生成とISO標準のコード生成のファイルの出力先は同じです。

関連項目:
「ファイルの出力先」

SQLJランタイム処理

ここでは、プログラム実行時のISO標準コードに対するランタイム処理について説明します。

ISO標準SQLJアプリケーションの場合は、SQLJランタイムがプロファイルを読み取って接続プロファイルを作成し、接続プロファイルにデータベース接続情報が組み込まれます。アプリケーションでデータベースへのアクセスが必要になると、そのつど次に示す処理が発生します。

1. SQLJで生成したアプリケーション・コードは、SQLJで生成したプロファイルキー・クラスのメソッドを使用して接続プロファイルにアクセスし、関係するSQL操作を読み取ります。アプリケーション内のSQLJ実行文とプロファイル内のSQL操作はマッピングされています。

2. SQLJで生成したアプリケーション・コードからSQLJランタイムをコールします。SQL操作がプロファイルから読み込まれます。

3. SQLJランタイムがJDBCドライバをコールして、SQL操作をドライバに渡します。

4. SQLJランタイムが入力パラメータをJDBCドライバに渡します。

5. JDBCドライバがSQL操作を実行します。

6. 戻り値がある場合は、データベースがデータをJDBCドライバに送ります。このデータはドライバからSQLJランタイムに送られ、アプリケーションで使用できるようになります。

注意:
入力パラメータを渡すことは、入力パラメータをバインドするまたはホスト式をバインドするとも言います。ホスト変数、ホスト式、バインド変数およびバインド式という用語はすべて、SQL操作の入力または出力として使用されるJava変数または式を説明するために使用されます。

デプロイメント例

次の方法でOracle固有のSQLJコードを実行する方法について説明しました。

- アプレットから

- サーバー内で(SQLJトランスレータもサーバーで実行できます)

アプレットからISO標準コードを実行する際に、いくつかの考慮事項があります。

関連項目:
「他のデプロイメント例」

- 次のSQLJランタイム・パッケージはすべて、アプレットとともにパッケージ化する必要があります。次のパッケージを含めます。

sqlj.runtime
sqlj.runtime.ref
sqlj.runtime.profile
sqlj.runtime.profile.ref
sqlj.runtime.error

Oracle独自のカスタマイズを行った場合は、次のパッケージも含める必要があります。

oracle.sqlj.runtime
oracle.sqlj.runtime.error

これらのパッケージは、Oracleインストールによって、ORACLE_HOME/libディレクトリのランタイム・ライブラリの中の1つに組み込まれています。

関連項目:
「Oracle SQLJ実装を使用するための要件」

- Netscape Navigator 4.xなどの一部のブラウザでは、プロファイル用のSQLJシリアル化オブジェクト・ファイルの拡張子である、.ser拡張子の付いたリソース・ファイルをサポートしていません。ただし、Sun MicrosystemsのJavaプラグインでは.serファイルをサポートしています。
Oracle SQLJ実装では、このプラグインを使用する以外の方法として、.serファイルを.classファイルに変換するための-ser2classオプションを使用する方法があります。

関連項目:
「.serファイルから.classファイルへの変換(-ser2class)」

注意:
この考慮事項は、プロファイルが生成されないデフォルトのOracle固有コード生成には適用されません。

- Oracle固有の機能を使用するアプレットでは、Oracle SQLJランタイムを起動する必要があります。Oracle SQLJランタイムは、oracle.sqlj.*下のSQLJランタイム・ライブラリ・ファイル内のクラスで構成されます。Oracle SQLJ runtime.jarライブラリでは、Java Reflection API(java.lang.reflect.*)が必要です。大半のブラウザでは、Reflection APIをサポートしていなかったりセキュリティ上の制約があるのに対し、Sun社のJavaプラグインの場合はReflection APIに対するサポートが提供されています。
ISO標準のコード生成の場合、次のSQLJ言語の機能では、使用しているSQLJランタイムのバージョンに関係なく、常にJava Reflection APIが必要となります。

- CAST文

- SQLJイテレータのインスタンスとしてのデータベースから取得されるREF CURSORパラメータまたはREF CURSOR列

- java.sql.Ref、Struct、Array、BlobまたはClobオブジェクトの取得

- oracle.sql.ORADataまたはjava.sql.SQLDataインタフェースを実装するJavaクラスのインスタンスとしてのSQLオブジェクトの取得

注意:

- ただし、ISOと完全に互換性のあるモードでSQLJを使用する場合は例外です。つまり、SQLJをJ2EEに準拠した環境で使用する場合、SQLJ runtime12ee.jarライブラリでプログラムを変換および実行する場合、およびISOで指定したように接続コンテキストの型マップを採用する場合です。この場合、java.sql.Ref、Struct、Array、Blob、ClobおよびSQLDataのインスタンスは、リフレクションを使用せずに取得されます。

- Oracle固有コード生成を使用すると、前述のすべてのインスタンスでのリフレクションの使用を削減します。

Oracle固有コード生成とISO標準コード生成との違い

Oracle SQLJの実装により、Oracle固有コード生成が可能になり、Oracle JDBCコールがコード内に直接生成されます。これはデフォルトの動作です。Oracle固有コード生成の場合、次の点に注意する必要があります。

- プロファイル・ファイルがないため、変換時のカスタマイズ処理もありません。

- 変換されたコード内に、SQLJランタイム・コールではなくJDBCコールが直接生成されるため、実行時にSQL操作はSQLJランタイム・レイヤーを経由する必要がありません。

ネーミングの要件および制限事項

ネーミング要件、ネーミング制限および予約語については、次の4点を考慮する必要があります。

- Javaのネームスペース。ローカル変数とクラスの名前については、SQLJ固有の制限もあります。

- SQLJのネームスペース。

- SQLのネームスペース。

- ソース・ファイル名。

ここでは、次の項目について説明します。

- Javaのネームスペース: ローカル変数およびクラスのネーミングに関する制限事項

- SQLJのネームスペース

- SQLのネームスペース

- ファイル名の要件と制限

Javaのネームスペース: ローカル変数およびクラスのネーミングに関する制限事項

Javaのネームスペースは、Javaのクラスやローカル変数のネーミングなど、標準Javaのすべての文および宣言に適用されます。標準Javaのネーミングに関するすべての制限が適用されるため、Javaの予約語は使用しないでください。

また、ローカル変数とクラスのネーミングには、SQLJ固有の制限も若干伴います。

注意:
ホスト変数名固有の制約については、「ホスト式の制限事項」を参照してください。

ローカル変数のネーミングに関する制限

ローカル変数のネーミングの際は、SQLJトランスレータの一部の機能に起因する制限が若干伴います。SQLJトランスレータは各SQLJ実行文を文ブロックに置き換えますが、このブロックでは、次のように標準構文に基づくSQLJ実行文が使用されます。

#sql { SQL operation };

SQLJでは、生成された文ブロック内に一時変数を宣言できます。この一時変数の名前には、次の接頭辞が付きます。

__sJT_

注意:
アンダースコアが先頭に2つ、末尾に1つ付きます。

SQLJで生成した文ブロックでは、次のような宣言が使用されます。

int __sJT_index;
Object __sJT_key;
java.sql.PreparedStatement __sJT_stmt;

文字列__sJT_は、SQLJで生成される変数名の接頭辞として予約されています。SQLJのプログラミングの際は、この文字列を次の名前の接頭辞としては使用しないでください。

- SQL実行文を含むブロックで宣言した変数名

- SQL実行文を含むメソッドのパラメータ名

- SQL実行文を含むクラスのフィールド名、あるいはサブクラスまたは被包含クラスにSQL実行文があるクラスのフィールド名

クラスのネーミングに関する制限

SQLJアプリケーションのクラスのネーミングには、次のような制限が伴います。

- SQLJの内部クラスと競合する可能性のあるクラス名は宣言しないでください。具体的には、SQLJアプリケーション内の既存クラスの名前がaの場合、最上位クラスに次の形式の名前を付けることはできません。

a_SJb

aとbは正当なJava識別子です。

たとえば、ファイルFoo.sqlj内のアプリケーション・クラスがFooである場合、SQLJはFoo_SJProfileKeysというプロファイルキー・クラスを生成します。この名前と競合するクラス名は宣言しないでください。

- SQLJ実行文を含むクラスの名前が、アプリケーションで使用されるJava型を格納するどのパッケージの名前の先頭部分とも同じにならないようにしてください。たとえば、java、sqljおよびoracle(大/小文字の区別あり)は、クラス名としては使用しないでください。また、SQLJ文に使用するホスト変数の型がabc.def.MyClassである場合、このホスト変数を使用するクラスの名前にはabcを使用できません。
こうした制限を回避するには、Javaのネーミング規則に従い、パッケージ名の先頭を小文字にし、クラス名の先頭を大文字にすることをお薦めします。

SQLJのネームスペース

SQLJのネームスペースは、#sqlクラス宣言と#sql実行文の中カッコの外側の部分です。

注意:
イテレータ列のネーミングに伴う特別な制限については、「名前付きイテレータの使用」を参照してください。

SQLJの次の予約語は、宣言する接続コンテキスト・クラスまたはイテレータ・クラスのクラス名として、with句またはimplements句で使用できません。イテレータ列の型宣言リストでも使用できません。

- iterator

- context

- with

たとえば、イテレータ・クラスまたはインスタンスの名前をiteratorにしたり、接続コンテキスト・クラスまたはインスタンスの名前をcontextにしないでください。

ただし、ストアド・ファンクションからの戻り値を格納する変数の名前には、これらのどのワードでも使用できます。

SQLのネームスペース

SQLのネームスペースは、SQLJ実行文の中カッコ内の部分です。このネームスペースには、標準SQLのネーミングに関する制限事項が適用されます。

関連項目:
『Oracle Database SQL言語リファレンス』

ただし、ホスト式は、SQLのネームスペースの規則ではなく、Javaのネームスペースの規則に従います。これは、ホスト変数の名前にも、ホスト式の外部のカッコで囲まれたすべての部分にも適用されます。

ファイル名の要件と制限

SQLJソース・ファイルのファイル名拡張子は.sqljです。ソース・ファイルでPublicクラスを宣言した場合(最大1つ)、ソース・ファイルのベース名がこのクラス名と一致する必要があります(大/小文字の区別あり)。ソース・ファイルでPublicクラスが宣言されていない場合、ファイル名はJava識別子として有効である必要があるため、ファイル名を最初に定義されたクラスの名前と同じにすることをお薦めします。

たとえば、ソース・ファイルにPublicクラスMySourceが定義されている場合は、次に示すファイル名を付けてください。

MySource.sqlj

注意:
これらのファイル・ネーミング要件は、Java言語仕様(JLS)準拠であり、SQLJ固有のものではありません。これらの要件は、Oracle Database 11gには直接適用されませんが、それらに従うことをお薦めします。

中間層のSQLJに関する考慮事項

Oracle9i Application Server Containers for J2EE(OC4J)環境など、中間層でSQLJを実行する場合は特別に考慮する事項があります。

Oracle JDBCドライバでは、oracle.jdbcパッケージにOracle固有のインタフェースが提供されます。Oracle SQLJライブラリ(runtime12.jarおよびruntime12ee.jar)は、これらのインタフェースを最大限に活用しますが、これらのライブラリには、Oracle9i Application Serverより前のOracle JDBC実装との互換性がありません。

Oracle9i Application Serverの場合、接続はデータ・ソースを介して確立され、通常は旧式のoracle.jdbc.driver.OracleConnectionクラスではなく、oracle.jdbc.OracleConnectionインタフェースのインスタンスを戻します。これは分散トランザクション(XA)などの特定の接続機能に必要です。このような機能をサポートするには、接続オブジェクトが新規インタフェースを実装する必要があります。

この結果、Oracle9i Application Server中間層環境またはデータ・ソースが使用される他の環境について、次のような処理が必要となります。

- コードの移植性と柔軟性を最大限にするには、oracle.jdbc.driver.OracleXXX型ではなくoracle.jdbc.OracleXXX型を使用します。

- カスタムJava型(通常はSQLオブジェクトとコレクション)については、非推奨のoracle.sql.CustomDatumインタフェースではなくoracle.sql.ORADataを実装します。

データ・ソースおよび接続JavaBeansへのSQLJサポートの概要は、次の項を参照してください。

- 「標準データ・ソースのサポート」

- 「SQLJ固有のデータ・ソース」

- 「JavaServer Pages用のSQLJ固有の接続JavaBeans」

4 基本的な言語機能

SQLJ文は常に#sqlトークンで開始し、主に次の2つのカテゴリに分割できます。

- 宣言: イテレータまたは接続コンテキストのJavaクラスを作成します。イテレータは、Java Database Connectivity (JDBC)の結果セットのようなもので、接続コンテキストは、使用されるSQLエントリに応じて強い型指定の接続を作成するために使用するものです。

- 実行文: 埋込みのSQL操作の実行に使用します。

この章では、次の項目について説明します。

- SQLJ宣言の概要

- SQLJ実行文の概要

- Javaホスト式、コンテキスト式および結果式

- 単一行の問合せ結果: SELECT INTO文

- 複数行の問合せ結果: SQLJイテレータ

- 代入文(SET)

- ストアド・プロシージャおよびストアド・ファンクションのコール

SQLJ宣言の概要

SQLJ宣言は#sqlトークンで開始され、その後にクラスの宣言が続きます。SQLJ宣言により、アプリケーションに専用Java型が導入されます。現行では、SQLJ宣言にはイテレータ宣言と接続コンテキスト宣言の2種類があり、次のようにJavaクラスを定義します。

- イテレータ宣言はイテレータ・クラスを定義します。イテレータは、概念的にJDBC結果セットと似ていて、複数行の問合せデータの受取りに使用されます。イテレータは、イテレータ・クラスのインスタンスとして実装されます。

- 接続コンテキスト宣言は、接続コンテキスト・クラスを定義します。通常、各接続コンテキスト・クラスは、操作の際に特定のSQLエンティティ(表、ビュー、ストアド・プロシージャなど)を使用する接続に使用されます。すなわち、名前と特性が同じSQLエンティティを持つスキーマへの接続には、特定の接続コンテキスト・クラスのインスタンスが使用されています。SQLJでは、各データベース接続が、接続コンテキスト・クラスのインスタンスとして実装されます。
SQLJには、事前定義されたsqlj.runtime.DefaultContext接続コンテキスト・クラスがあります。必要な接続コンテキスト・クラスが1つのみである場合は、接続コンテキスト宣言の必要がないDefaultContextを使用できます。

イテレータ宣言や接続コンテキスト宣言には、必要に応じて次の句を挿入できます。

- implements句: 生成されたクラスによって実装されるインタフェースを1つ以上指定します。

- with句: 生成されたクラスに含める初期化済定数を1つ以上指定します。

ここでは、次の項目について説明します。

- SQLJ宣言の規則

- イテレータ宣言

- 接続コンテキスト宣言

- IMPLEMENTS句宣言

- WITH句宣言

SQLJ宣言の規則

SQLJソース・コード中には、標準Javaでクラスを定義できる場所であればどこにでもSQLJ宣言を記述できます。次に例を示します。

SQLJ declaration;   // OK (top level scope)

class Outer
{
SQLJ declaration; // OK (class level scope)

class Inner
{
SQLJ declaration; // OK (nested class scope)
}

void func()
{
SQLJ declaration; // OK (method block)
}
}

注意:
標準Javaの場合と同様に、Publicクラスは、次のいずれかの方法で宣言する必要があります。

- 別個のソース・ファイル中に宣言する方法。ファイルのベース名はクラス名と同じにします。

- クラスレベルの有効範囲またはネストされたクラスレベルの有効範囲に宣言する方法。この方法の場合、public static修飾子を使用することをお薦めします。

Sun社のJDKの標準javacコンパイラを使用する場合は、これが要件となります。

イテレータ宣言

イテレータ宣言では、問合せデータの受取り用に、イテレータの一種を定義するクラスを作成します。この宣言でイテレータ・インスタンスの列型を指定しますが、この列型はデータベース表から選択され列型と同じである必要があります。

基本的なイテレータ宣言では、次の構文が使用されます。

#sql <modifiers> iterator iterator_classname (type declarations);

修飾子の使用は任意で、publicやstaticなどの標準Javaクラス修飾子を使用できます。型宣言はカンマで区切ります。

イテレータには、名前付きイテレータと位置イテレータの2種類があります。名前付きイテレータには、列名と型を指定する必要があります。位置イテレータには、型のみを指定する必要があります。

次に、名前付きイテレータ宣言の例を示します。

#sql public iterator EmpIter (String ename, double sal);

この文を実行すると、SQLJトランスレータによって、String属性のenameおよびdouble属性のsalで、public EmpIterクラスが作成されます。このイテレータを使用して、データベース表の従業員名と給料の各列から、名前(ENAMEおよびSAL)とデータ型(CHARおよびNUMBER)が一致するデータを選択できます。

EmpIterを名前付きイテレータではなく位置イテレータとして宣言すると、次のようになります。

#sql public iterator EmpIter (String, double);

関連項目:
「複数行の問合せ結果: SQLJイテレータ」

接続コンテキスト宣言

接続コンテキスト宣言により、接続コンテキスト・クラスが作成されます。通常、このクラスのインスタンスは、特定のSQLエンティティ・セットを使用するデータベース接続に使用されます。基本的な接続コンテキスト宣言では、次の構文を使用します。

#sql <modifiers> context context_classname;

イテレータ宣言の場合、修飾子は任意で、標準Javaのどのクラス修飾子でも使用できます。次に例を示します。

#sql public context MyContext;

この文を実行すると、SQLJトランスレータによってpublic MyContextクラスが作成されます。SQLJコード中にこのクラスのインスタンスを使用すると、目的のエンティティ・セット(表、ビュー、ストアド・プロシージャなど)を含むスキーマへのデータベース接続を作成できます。MyContextの複数のインスタンスを使用して、様々なスキーマに接続することができますが、それぞれのスキーマに、たとえばEMP表、DEPT表およびTRANSFER_EMPLOYEEストアド・プロシージャが含まれることが前提になります。

宣言済の接続コンテキスト・クラスは高度なトピックであり、1つの相互に関係するSQLエンティティ・セットのみを使用する基本的なSQLJアプリケーションについては、これを使用する必要はありません。また、基本的には、sqlj.runtime.ref.DefaultContextクラスのインスタンスをいくつか作成することで複数の接続を使用できるため、接続コンテキストを宣言する必要はありません。

関連項目:
「接続の際の考慮事項」および「接続コンテキスト」

IMPLEMENTS句宣言

イテレータ・クラスや接続コンテキスト・クラスを宣言する場合、生成されたクラスが実装するインタフェースを1つ以上指定できます。

イテレータ・クラスには次の構文を使用します。

#sql <modifiers> iterator iterator_classname implements intfc1,..., intfcN
(type declarations);

implements intfc1,..., intfcN の部分は、implements句と呼ばれます。イテレータ宣言では、implements句に続いてイテレータ型宣言をします。

接続コンテキスト宣言には次の構文を使用します。

#sql <modifiers> context context_classname implements intfc1,..., intfcN;

implements句は、イテレータ宣言または接続コンテキスト宣言のいずれにおいても有効ですが、特にsqlj.runtime.Scrollableまたはsqlj.runtime.ForUpdateインタフェースの実装時のイテレータ宣言で有効な場合が多くあります。スクロール可能なイテレータはOracle SQLJ実装でサポートされています。

注意:
SQLJのimplements句は、Javaのimplements句に相当します。

次の例では、名前付きイテレータ・クラスの宣言にimplements句を使用しています。この例では、イテレータ・インタフェースのMyIterIntfcを含むmypackageパッケージが作成されていることを前提とします。

#sql public iterator MyIter implements mypackage.MyIterIntfc
(String ename, int empno);

クラスMyIterの宣言によって、mypackage.MyIterIntfcインタフェースが実装されます。

次の例では、MyConnCtxtIntfcという名前のインタフェースを実装した接続コンテキスト・クラスを宣言しています。ここでも、mypackageパッケージを前提とします。

#sql public context MyContext implements mypackage.MyConnCtxtIntfc;

関連項目:
「イテレータ宣言でのIMPLEMENTS句の使用」および「接続コンテキスト宣言でのIMPLEMENTS句の使用」

WITH句宣言

接続コンテキスト・クラスやイテレータ・クラスの宣言時には、with句を使用して、生成されたクラスの定義に含める定数を1つ以上指定し初期化できます。Oracle実装ではいくつかの拡張機能をイテレータ宣言に追加していますが、この使用例の大部分は標準です。

ここでは、次の項目について説明します。

- 標準WITH句の使用例

- Oracle固有のWITH句の使用例

- returnabilityの例

標準WITH句の使用例

with句を使用する場合、生成される定数は必ずpublic static finalです。イテレータ・クラスには次の構文を使用します。

#sql <modifiers> iterator iterator_classname with (var1=value1,..., varN=valueN)
(type declarations);

with (var1=value1,..., varN=valueN )の部分がwith句と呼ばれます。イテレータ宣言では、with句に続けてイテレータ型宣言をします。

with句とimplements句の両方がある場合は、implements句を最初にする必要があります。withリストはカッコで囲みますが、implementsリストはカッコで囲みません。

次に、with句を使用する接続コンテキスト宣言の構文を示します。

#sql <modifiers> context context_classname with (var1=value1,..., varN=valueN);

注意:
事前に定義された標準SQLJ定数は、with句に定義できます。ただし、この定数すべてがOracle Database 11g またはOracle SQLJランタイムでサポートされるわけではありません。
Oracle Database 11gでは、標準定数以外の定数を定義できますが、他のSQLJ実装に移植できない可能性があるうえ、-warn=portableフラグが有効になっていると警告が生成されます。このフラグの詳細は、「トランスレータからの警告(-warn)」を参照してください。

サポートされているWITH句の定数

Oracle SQLJ実装では、接続コンテキスト宣言内で、次の標準定数の使用がサポートされています。

- typeMap: 型マップ・プロパティ・リソース名を定義するStringリテラル
イテレータ宣言内でのtypeMapの使用もサポートされています。

関連項目:
「Oracle固有のWITH句の使用例」

- dataSource: InitialContextでデータ・ソースを検索する名前を定義するStringリテラル

関連項目:
「標準データ・ソースのサポート」

Oracle SQLJ実装では、イテレータ宣言内で、次の標準定数の使用がサポートされています。

- sensitivity: SENSITIVE/ASENSITIVE/INSENSITIVEで、スクロール可能なイテレータの機密性を定義する

関連項目:
「スクロール可能なイテレータの更新検出」

- returnability: true/falseで、イテレータがJavaストアド・プロシージャまたはファンクションから戻されるかどうかを定義する

関連項目:
「returnabilityの例」

サポートされていないWITH句の定数

サポートされていない定数を使用するSQLJコードを使用した場合、エラーは発生しませんが、何の操作も実行されません。Oracle SQLJ実装では、接続コンテキスト宣言内で次の標準定数を使用することはできません。

- path: Javaストアド・プロシージャおよびファンクションを解決するために先頭に付加するPATHの名前を定義するStringリテラル

- transformGroup: SQL型に適用するSQL変換グループ名を定義するStringリテラル

Oracle SQLJ実装では、イテレータ宣言内で、カーソルの状態に関連する次の標準定数を使用することはできません。

- holdability: true/falseで、カーソルを保持できるかどうかを指定する
保持できるかどうかの概念は、SQL仕様で定義されています。保持可能なカーソルは、トランザクションが完了した場合でも、アプリケーション・リクエストに従って、オープン状態かつ現在の行の位置で保持できます。そのカーソルは同じSQLセッションの次のトランザクションで継続して使用できますが、いくつかの制限があります。

- updateColumns: 列名のカンマ区切りリストを含むStringリテラル
updateColumnsを指定するwith句を持つイテレータ宣言には、sqlj.runtime.ForUpdateインタフェースを指定するimplements句も含める必要があります。updateColumnsは現在サポートされていませんが、Oracle SQLJ実装ではこれに従う必要があります。

次に、typeMapを使用した接続コンテキスト宣言の例を示します。

#sql public context MyContext with (typeMap="MyPack.MyClass");

宣言されたクラスMyContextではString属性のtypeMapが定義され、これはpublic static finalになってMyPack.MyClass値に初期化されます。この値は、MyContextクラスのインスタンス上で実行される文のSQL型とJava型のマッピングを提供するListResourceBundle実装の完全修飾クラス名です。

次に、sensitivityを使用したイテレータ宣言の例を示します。

#sql public iterator MyAsensitiveIter with (sensitivity=ASENSITIVE)
(String ename, int empno);

この宣言では、MyAsensitiveIter名前付きイテレータ・クラスに対してカーソルsensitivityにASENSITIVEが設定されます。

次に、implements句とwith句の両方を使用した例を示します。

#sql public iterator MyScrollableIterator implements sqlj.runtime.Scrollable
with (holdability=true) (String ename, int empno);

このように宣言すると、インタフェースsqlj.runtime.Scrollableが実装され、カーソルholdabilityが名前付きイテレータ・クラスに対して使用可能になります。

注意:
holdabilityは、現在サポートされていません。

Oracle固有のWITH句の使用例

型マップを接続コンテキスト・クラスに対応付けるために、標準with句を接続コンテキスト宣言で使用する方法の他に、Oracle SQLJ実装では、型マップをイテレータ宣言内でイテレータ・クラスに対応付けるために、with句を使用できます。次に例を示します。

#sql iterator MyIterator with (typeMap="MyTypeMap") (Person pers, Address addr);

Oracle固有コード生成を使用して、型マップをアプリケーションで使用する場合、イテレータと接続コンテキスト宣言で同じ型マップを使用する必要があります。

関連項目:
「Oracle固有コード生成でのコード上の考慮事項と制限事項」

returnabilityの例

SQLJイテレータ宣言のwith句にreturnability=trueを使用すると、イテレータがJavaストアド・プロシージャからSQLまたはPL/SQL文にREF CURSORとして戻されます。デフォルトのreturnability=false設定では、イテレータはこの方法で戻されず、戻そうとすると、実行時にSQL例外が発生します。

次のデータベース表を作成します。

create table sqljRetTab(str varchar2(30));
insert into sqljRetTab values ('sqljRetTabCol');

次のように、RefCursorSQLJ.sqljソース・ファイル内にRefCursorSQLJクラスを定義します。イテレータ型MyIterにreturnability=trueが使用されていることに注意してください。

public class RefCursorSQLJ
{
#sql static public iterator MyIter with (returnability=true) (String str);

static public MyIter sqljUserRet() throws java.sql.SQLException
{
MyIter iter=null;
try {
#sql iter = {select str from sqljRetTab};
} catch (java.sql.SQLException e)
{
e.printStackTrace();
throw e;
}
System.err.println("iter is " + iter);
return iter;
}
}

データベース内のOracle Java Virtual Machine(JVM)にRefCursorSQLJ.sqljをロードします。

% loadjava -u scott -r -f -v RefCursorSQLJ.sqlj
Password: password

sqljUserRet()メソッドに定義されたJavaストアド・プロシージャを起動します。

create or replace package refcur_pkg as
type refcur_t is ref cursor;
end;
/
create or replace function sqljUserRet
return refcur_pkg.refcur_t as
language java
name 'RefCursorSQLJ.sqljUserRet() return
RefCursorSQLJ.MyIter';
/
select scott.sqljUserRet from dual;

SELECT文の結果を次に示します。

SQLJRET1
--------------------
CURSOR STATEMENT : 1

STR
------------------------------
sqljRetTabCol

SQLJ実行文の概要

SQLJ実行文は#sqlトークンと、後に続くSQLJ句で構成されます(実行可能なSQL文をJavaコードに埋め込むために、指定された規格に従った構文を使用します)。SQLJ実行文の埋込みSQL操作は、JDBCドライバでサポートされる任意のSQL操作にできます。

ここでは、次の項目について説明します。

- SQLJ実行文の規則

- SQLJ句

- 接続コンテキスト・インスタンスと実行コンテキスト・インスタンスの指定

- 実行文の例

- 実行文のPL/SQLブロック

SQLJ実行文の規則

SQLJ実行文には次の規則があります。

- Javaコードでは、Javaブロック文が許可される場合は常に、SQLJ実行文も許可されます。つまり、メソッド定義や静的な初期化ブロック内では許可されています。

- 埋込みSQL操作は、中カッコ{...}で囲む必要があります。

- 最後にセミコロン(;)を指定する必要があります。

注意:

- セミコロンは、SQL操作の終了を示す符号としては使用しないことをお薦めします。パーサーが操作の終了を認識するのは、SQLJ句の内部に右中カッコが現れた場合です。

- SQLJ実行文の中カッコに囲まれた部分はすべてSQL構文として扱われ、SQL規則に従います。ただし、Javaホスト式の場合は例外です。

- SQL操作のオフライン解析では、すべてのSQL構文がチェックされます。ただし、オンラインのセマンティクス・チェックでは、データ操作言語(DML)操作のみを解析およびチェックできます。データ定義言語(DDL)操作、トランザクション制御操作またはSQL操作については解析またはチェックされません。

SQLJ句

SQLJ句とは、文の実行可能部分であり、#sqlトークンの後に続く内容すべてを指します。この句では埋込みSQLを中カッコで囲んで指定し、必要に応じて、この句の前にJava結果式を指定します(たとえば、次の例のresult)。

#sql { SQL operation };   // For a statement with no output, like INSERT
...
#sql result = { SQL operation };   // For a statement with output, like SELECT

1番目のSQLJ文の例のように結果式のないものは、ステートメント句と呼ばれます。2番目のSQLJ文の例のように結果式のあるものは、代入句と呼ばれます。

結果式には、ストアド・ファンクションの戻り値が代入される単純な変数から、複数行SELECTからの複数列のデータが代入されるイテレータまで、任意のものを使用できます(イテレータは、イテレータ・クラスまたはイテレータ・サブクラスのインスタンスになります)。

SQLJ文のSQL操作には、標準SQL構文のみを使用するか、SQLJ固有の構文を持つ句を使用できます。

サポートされているSQLJステートメント句を表4-1に、サポートされているSQLJ代入句を表4-2に示します。表4-1の最後にあげた2つの項目は、SQLJ固有の構文ではなく、標準SQL構文またはOracle PL/SQL構文を使用するステートメント句の一般カテゴリの項目です。

表4-1 SQLJステートメント句

カテゴリ

機能

参照先

SELECT INTO句

Javaホスト式にデータを取り込みます。

「単一行の問合せ結果: SELECT INTO文」

FETCH句

位置イテレータからデータをフェッチします。

「位置イテレータの使用」

COMMIT句

データへの変更をコミットします。

「手動COMMITまたはROLLBACKの使用方法」

ROLLBACK句

データへの変更を取り消します。

「手動COMMITまたはROLLBACKの使用方法」

SAVEPOINT RELEASE SAVEPOINT ROLLBACK TO句

以後のロールバックのためのセーブポイントの設定、指定したセーブポイントの解放、セーブポイントのロールバックを行います。

「セーブポイントの使用」

SET TRANSACTION句

アクセス・モードや分離レベルなど、詳細トランザクション制御を使用します。

「詳細なトランザクション制御」

プロシージャ句

ストアド・プロシージャをコールします。

「ストアド・プロシージャのコール」

代入句

Javaホスト式に値を代入します。

「代入文(SET)」

SQL句

UPDATE、INSERT、DELETEの標準SQL構文および機能を使用します。

『Oracle Database SQL言語リファレンス』

PL/SQLブロック

SQLJ文内部のBEGIN..ENDまたはDECLARE..BEGIN..END無名ブロックを使用します。

「実行文のPL/SQLブロック」

『Oracle Database PL/SQL言語リファレンス』

表4-2 SQLJ代入句

カテゴリ

機能

参照先

問合せ句

SQLJイテレータにデータを取り込みます。

「複数行の問合せ結果: SQLJイテレータ」

ファンクション句

ストアド・ファンクションをコールします。

「ストアド・ファンクションのコール」

イテレータ変換句

JDBC結果セットをSQLJイテレータに変換します。

「結果セットから名前付きイテレータまたは位置イテレータへの変換」

注意:
SQLJ文は、その文の本体を構成する句と同じ名前になります。たとえば、#sqlの後にSELECT INTO句が続く実行文は、SELECT INTO文になります。

接続コンテキスト・インスタンスと実行コンテキスト・インスタンスの指定

複数のデータベース接続が定義されているときに、実行文に特定の接続コンテキスト・インスタンスを指定する場合は、次の構文を使用します。

#sql [conn_context_instance] { SQL operation };

関連項目:
「接続の際の考慮事項」

実行コンテキスト・インスタンス(sqlj.runtime.ExecutionContextクラス)を1つ以上定義していて、その1つを実行文用に指定する場合、次の構文を使用します。

#sql [exec_context_instance] { SQL operation };

実行コンテキスト・インスタンスを使用して、SQLJ実行文のSQL操作の実行状態や実行制御を定義できます。たとえば、同一の接続で複数の操作が行われるマルチスレッド状況で、実行コンテキスト・インスタンスを使用できます。

関連項目:
「実行コンテキスト」

また、接続コンテキスト・インスタンスと実行コンテキスト・インスタンスの両方を指定することも可能です。

#sql [conn_context_instance, exec_context_instance] { SQL operation };

注意:

- 接続コンテキスト・インスタンスと実行コンテキスト・インスタンスは大カッコで囲みます。これらは構文の一部になります。

- 接続コンテキスト・インスタンスと実行コンテキスト・インスタンスの両方を指定する場合は、接続コンテキスト・インスタンスを先にする必要があります。

実行文の例

ここでは、基本的なSQLJ実行文の例を示します。

基本的なINSERT

次の例は、基本的なINSERTです。ステートメント句は、SQLJ固有の構文を必要としません。

次の行を持つ従業員表EMPを想定します。

CREATE TABLE EMP (
ENAME VARCHAR2(10),
SAL NUMBER(7,2) );

標準SQL構文のSQLJ実行文を使用し、EMP表に新しい従業員Joeを挿入し、名前と給料を指定します。

#sql { INSERT INTO emp (ename, sal) VALUES ('Joe', 43000) };

接続コンテキスト・インスタンスまたは実行コンテキスト・インスタンスを指定する基本的なINSERT

次の例では、接続コンテキスト・インスタンスとして、デフォルトのsqlj.runtime.ref.DefaultContextのインスタンスまたは接続コンテキスト宣言で宣言したクラスのインスタンスであるctxを使用しています。また、実行コンテキスト・インスタンスとしては、execctxを使用しています。

#sql [ctx] { INSERT INTO emp (ename, sal) VALUES ('Joe', 43000) };

#sql [execctx] { INSERT INTO emp (ename, sal) VALUES ('Joe', 43000) };

#sql [ctx, execctx] { INSERT INTO emp (ename, sal) VALUES ('Joe', 43000) };

単純なSQLJメソッド

この例は、SQLJコードを使用した単純なメソッドを示し、SQLJ文とJava文の関係およびコード中での場所を表しています。このSQLJ文は、Oracle SQL実装でサポートされている標準のINSERT INTO table VALUES構文を使用しています。また、この文では、コロン(:)でマークされたJavaホスト式を使用して値を定義しています。ホスト式は、JavaコードとSQL命令の間でのデータの受渡しに使用されます。

public static void writeSalesData (int[] itemNums, String[] itemNames)
throws SQLException
{
for (int i =0; i < itemNums.length; i++)
#sql { INSERT INTO sales VALUES(:(itemNums[i]), :(itemNames[i]), SYSDATE) };
}

注意:

- throws SQLExceptionが必要です。

- SQLJファンクション・コールでもVALUESトークンが使用されますが、使用目的が異なります。

実行文のPL/SQLブロック

PL/SQLブロックは、SQL操作と同様に、SQLJ実行文の中カッコ内で使用できます。次にその例を示します。

#sql {
DECLARE
n NUMBER;
BEGIN
n := 1;
WHILE n <= 100 LOOP
INSERT INTO emp (empno) VALUES(2000 + n);
n := n + 1;
END LOOP;
END
};

この例では、新しい従業員をemp表に挿入するループに入り、従業員番号の2001から2100を作成します。従業員番号以外のデータは、後で埋められるとします。

単純なPL/SQLブロックは、次のように1行のコードでも完結します。

#sql { <DECLARE ...> BEGIN ... END; };

SQLJ文中での無名PL/SQLブロックの使用は、アプリケーション内で動的SQLを使用する1つの方法です。動的SQLは、OracleのSQLJ拡張機能を使用するか、またはSQLJアプリケーション内部のJDBCコードを使用することによっても直接使用できます。

関連項目:
「動的SQLのサポート」および「SQLJとJDBCの連係動作」

注意:
PL/SQLはOracle固有なので、PL/SQLをSQLJコードで使用すると、他のプラットフォームへの移植性が失われます。

Javaホスト式、コンテキスト式および結果式

ここでは、SQLJコードで使用されるJava式の3つのカテゴリ(ホスト式、コンテキスト式および結果式)について説明します。ホスト式は、最も頻繁に使用されるJava式です。メタ・バインド式と呼ばれる別のカテゴリの式は、特に動的SQL操作に使用され、ホスト式と同様の構文を使用します。

関連項目:
「動的SQLのサポート」

SQLJは、JavaコードとSQL操作の間の引数の受渡しにホスト式を使用します。これが、JavaとSQLの間で情報を通信する方法です。ホスト式は、SQLJソース・コードの埋込みSQL操作内に間隔をおいて配置されます。

Java識別子のみで構成される最も基本的なホスト式は、ホスト変数と呼ばれます。コンテキスト式には、SQLJ文で使用される接続コンテキスト・インスタンスまたは実行コンテキスト・インスタンスを指定します。結果式には、問合せ結果やファンクションの戻り値の出力変数を指定します。

ここでは、次の項目について説明します。

- ホスト式の概要

- 基本的なホスト式の構文

- ホスト式の例

- 結果式とコンテキスト式の概要

- Java式の実行時評価

- Java式の実行時評価の例(ISOコード生成)

- ホスト式の制限事項

ホスト式の概要

有効なJava式はすべて、ホスト式として使用できます。最も単純なホスト式は、単一のJava変数のみで構成されます。それ以外のホスト式には、次の式があります。

- 算術式

- Javaメソッドのコールと戻り値

- Javaクラス・フィールド値

- 配列の要素

- 条件式(a ? b : c)

- 論理式

- ビット単位式

ホスト変数として使用されたJava識別子、またはホスト式で使用されたJava識別子は、次のいずれかを表します。

- ローカル変数

- 宣言したパラメータ

- クラス・フィールド

- staticメソッド・コールまたはインスタンス・メソッド・コール

ホスト式で使用されたローカル変数は、他のJava変数を宣言できる場所で宣言できます。フィールドは、スーパークラスから継承できます。

SQLJ実行文があるJavaスコープ内で有効なJava変数は、SQL文のホスト式で使用できますが、Java変数の型がSQLデータ型と相互に変換可能であることが前提になります。ホスト式は、入力、出力または入出力のいずれにもなります。

関連項目:
「ホスト式での型サポート」

基本的なホスト式の構文

ホスト式の前にはコロン(:)が付きます。使用するホスト式のモードがデフォルトでない場合は、コロンに続けてIN、OUTまたはINOUTを付け、その後にホスト式を置きます。これらはモード指定子と呼ばれます。ホスト式がINTOリストである場合、またはホスト式がSET文中の代入式である場合は、デフォルトのモード指定子がOUTになります。それ以外の場合は、デフォルトがINになります。すべてのOUTまたはINOUTホスト式は、代入可能である必要があります。

注意:
デフォルトを使用している場合でも、必要に応じてモード指定子を設定できます。

ホスト式を取り巻くSQLコードには、任意のベンダー固有SQL構文を使用できます。このため、SQL操作の解析およびホスト式の判断を行うときに、構文を想定できません。不明確にならないよう、単純なホスト変数ではないホスト式、つまりドットで区切られていないJava識別子より複雑なホスト式は、カッコで囲んでください。

基本的な構文を要約すると次のようになります。

- モード指定子のない単純なホスト変数の場合は、次の例のように、コロンの後にホスト変数を置きます。

:hostvar

- モード指定子付きの単純なホスト変数の場合は、次の例のように、コロンの後にモード指定子を付け、続けて空白(スペース、タブ、改行またはコメント)を挿入してからホスト変数を指定します。

:INOUT hostvar

モード指定子と変数名を区別するために、空白が必要です。

- その他のホスト式の場合は、次の例のように、式をカッコで囲んでモード指定子の後に置きます。モード指定子がない場合はコロンの後に置きます。

:IN(hostvar1+hostvar2)
:(hostvar3*hostvar4)
:(index--)

この例では、カッコをセパレータとしているので、モード指定子の後に空白を置く必要はありません。ただし、モード指定子の後に空白を置くことはできます。

次の例のように、式が左カッコで始まる場合でも、全体を囲む左カッコがもう1つ必要です。

:((x+y).z)
:(((y)x).myOutput())

構文上の注意

ホスト式の構文には、次の注意事項があります。

- コロンやモード指定子の後には、どんな場合にも空白を挿入できます。空白を挿入できる場所には、コメントも記述できます。
次のいずれかのSQLネームスペースにSQLコメントを記入できます。

- コロンの後とモード指定子の前

- モード指定子がない場合は、コロンの後とホスト式の前

- モード指定子の後とホスト式の前

次のJavaネームスペースにJavaコメントを記述できます。

- ホスト式内部(小カッコの中)

- ホスト変数およびホスト式に使用されるIN、OUTおよびINOUT構文には、大/小文字の区別がありません。これらのトークンには、大文字、小文字またはその両方使用できます。

- SQLJホスト式のIN、OUTおよびINOUT構文は、PL/SQL宣言でのIN、OUTおよびIN OUT構文と似ていますが、混同しないようにしてください。PL/SQL宣言でのこの構文は、PL/SQLストアド・ファンクションおよびプロシージャに渡されるパラメータのモードの指定に使用されます。

使用上の注意

ホスト式の使用には、次の注意事項があります。

- 同じSQLJ文中に単純なホスト変数が複数回出現する場合があります。

- ホスト変数を入力変数としてのみ使用する場合は、制約や煩雑な操作は伴いません。

- PL/SQLブロック内の出力変数としてホスト変数が少なくとも1回現れた場合、トランスレータの-warn=portabilityフラグが設定されていると、移植性に関する警告が出されます。こうした状況では、各ベンダーのSQLJランタイムは、それぞれ固有の動作をします。OracleのSQLJランタイムの場合、ホスト変数が出現するたびに値構文が使用されます(参照セマンティクスと対照)。

- ホスト変数が、ストアド・プロシージャ・コール、ストアド・ファンクション・コール、SET文またはINTOリスト中の出力変数として1回以上出現した場合、警告は出力されません。こうした場合にSQLJランタイムでは値構文を使用し、それぞれに対して共通の処理をします。

注意:
出力とは、OUTまたはINOUT変数のことです。

- 単純なホスト変数のホスト式がSQLJ文中に複数回出現した場合は、(デフォルトで)値構文を使用し、それぞれを完全に別個のものとして処理します。ただし、SQLJトランスレータで-bind-by-identifier=true設定を使用している場合は、処理が異なります。trueに設定されている場合、指定されたSQLJ文またはPL/SQLブロック内に同じホスト変数が複数回出現しても、単一のバインドとして処理されます。

関連項目:
「識別子によるホスト式のバインド(-bind-by-identifier)」

- CHAR型データと比較するために文字列のホスト式をWHERE句にバインドする場合は、SQLJに-fixedcharオプションがあることに注意してください。このオプションは、比較時にCHAR列の空白埋めを考慮します。

関連項目:
「空白埋めを考慮したCHAR比較(-fixedchar)」

ホスト式の例

次に、構文の説明を明確にするために、いくつかの例をあげます。

注意:
次に示すいくつかの例ではSELECT INTO文を使用しています。この文については、「単一行の問合せ結果: SELECT INTO文」を参照してください。

例1

この例では、2つの入力ホスト変数を、一方はWHERE句のテスト値として、もう一方はデータベースに送られる新しいデータを含むものとして使用しています。

データベースの従業員表empに、従業員名の列enameおよび従業員の給料の列salがあるとします。次に、ホスト変数を定義する関連Javaコードを示します。

String empname = "SMITH";
double salary = 25000.0;
...
#sql { UPDATE emp SET sal = :salary WHERE ename = :empname };

INはデフォルトですが、明示的に示すことも可能です。

#sql { UPDATE emp SET sal = :IN salary WHERE ename = :IN empname };

ここに示すとおり、INトークンを使用しない場合は、コロン(:)のすぐ後ろに変数を置けるのに対し、:INの場合はすぐ後ろに空白を置き、その後にホスト変数を置く必要があります。

例2

この例では、SELECT INTO文で出力ホスト変数を使用し、従業員番号が28959の従業員名を検索します。

String empname;
...
#sql { SELECT ename INTO :empname FROM emp WHERE empno = 28959 };

OUTはINTOリストのデフォルトですが、明示的に示すことも可能です。

#sql { SELECT ename INTO :OUT empname FROM emp WHERE empno = 28959 };

この文では、emp表のempno列で従業員番号28959を検索し、その行のename列から名前を選択し、それをempnameホスト変数に出力します。この場合、Java Stringで出力されます。

例3

この例では、入力ホスト式として算術式を使用しています。Java変数のbalanceとminPmtRatioが乗算され、その結果は口座番号537845についてcreditacct表のminPayment列を更新する際に使用されます。

float balance = 12500.0;
float minPmtRatio = 0.05;
...
#sql { UPDATE creditacct SET minPayment = :(balance * minPmtRatio)
WHERE acctnum = 537845 };

INトークンを使用すると次のようになります。

#sql { UPDATE creditacct SET minPayment = :IN (balance * minPmtRatio)
WHERE acctnum = 537845 };

例4

この例では、入力ホスト式としてメソッドのコールの出力を使用し、さらに入力ホスト変数も使用しています。この文では、getNewSal()からの戻り値を使用して、Java変数empnameで指定された従業員について、emp表のsal列を更新します。ホスト変数に初期値を設定するJavaコードも示されています。

String empname = "SMITH";
double raise = 0.1;
...
#sql {UPDATE emp SET sal = :(getNewSal(raise, empname))
WHERE ename = :empname};

結果式とコンテキスト式の概要

コンテキスト式は、SQLJ実行文で使用される接続コンテキスト・インスタンスまたは実行コンテキスト・インスタンスの名前を指定する入力式です。式を評価し、そのような名前を生成するJava式を使用できます。

結果式は、問合せ結果やファンクションの戻り値に使用する出力式です。代入可能、つまり論理的に等号の左辺に置くことが可能な正当なJava式を使用できます。これは、左辺値ともいいます。

次に示す例は、結果式とコンテキスト式のいずれにも使用できます。

- ローカル変数

- 宣言したパラメータ

- クラス・フィールド

- 配列の要素

構文上、ホスト式はSQL領域(SQLJ実行文の中カッコ内)に置きますが、結果式とコンテキスト式はSQLJ領域に置きます。このため、結果式またはコンテキスト式の前には、コロンを付けないようにする必要があります。

Java式の実行時評価

ここでは、アプリケーションの実行時の、Javaホスト式、接続コンテキスト式、実行コンテキスト式および結果式の評価について説明します。

これらの式をすべて使用する、単純化されたSQLJ実行文を次に示します。

#sql [connctxt_exp, execctxt_exp] result_exp = { SQL with host expression };

Java式には、必要に応じて次の用途があります。

- 接続コンテキスト式: 使用する接続コンテキスト・インスタンスの指定のために評価されます。

- 実行コンテキスト式: 使用する実行コンテキスト・インスタンスの指定のために評価されます。

- 結果式: 結果を受け取ります(たとえば、ストアド・ファンクションから)。

- ホスト式

ISO標準コード生成では、式が評価される順序に応じた副作用を使用する場合でも、Java式の評価は明確です。

Oracle固有コード生成では、-bind-by-identifierオプションが使用可能な場合を除き、副作用がない場合、Java式の評価はISO標準に従います。副作用がある場合、Java式の評価は実装ごとに固有で、変更される可能性があります。

注意:
以降の説明および関連する例は、Oracle固有コード生成には当てはまりません。ここに説明されているような副作用を使用する場合は、変換でISOコードを生成する必要があります。

次に、ISOコードの場合の実行時に実行される文に対するJava式の評価、実行および代入の順序の概要を示します。

1. 接続コンテキスト式がある場合は、他のJava式が評価される前に、即座に評価されます。

2. 実行コンテキスト式がある場合は、接続コンテキスト式の後で、結果式の前に評価されます。

3. 結果式がある場合は、コンテキスト式の後で、ホスト式の前に評価されます。

4. コンテキスト式や結果式の評価後に、ホスト式は、SQL操作での出現順に従って左から右へ評価されます。各ホスト式が出現してそれが評価されると、その値が保存されSQLに渡されます。
各ホスト式の評価は1度のみです。

5. INおよびINOUTパラメータがSQLに渡され、SQL操作が実行されます。

6. SQL操作の実行後、出力パラメータ、つまりJavaのOUTおよびINOUTホスト式に、SQL操作の結果の出力内容が代入されます。このとき、出力パラメータがSQL操作で出現する順序に従って、左から右に代入が行われます。
各出力ホスト式は1度のみ代入されます。

7. 結果式がある場合は、最後に出力内容が代入されます。

注意:
PL/SQLブロック内のホスト式はすべて、ブロック内の文が実行される前に、一度に評価されます。ホスト式は、ブロック内のコントロール・フローにかかわらず、出現順に評価されます。

文中の式が評価された後、入力および入出力ホスト式がSQLに渡され、SQL操作が実行されます。SQL操作の実行後、Javaの出力ホスト式、入出力ホスト式および結果式に対して、次のように代入が行われます。

1. OUTおよびINOUTホスト式は、左から右の順に出力内容が代入されます。

2. 結果式がある場合は、最後に出力内容が代入されます。

実行時には、すべてのホスト式が別々の値として扱われます。これは、ホスト式が同じ名前を共有する場合、または同じオブジェクトを参照する場合でも同様です。それぞれのSQL操作の実行はリモート・メソッドの起動と同様に処理され、各ホスト式は別々のパラメータとして使用されます。各入力または入出力パラメータは、最初の出現時に評価されて渡された後に、その文に対して出力の代入が行われます。各出力パラメータも別々のものとして扱われ、1度だけ代入されます。

各ホスト式の評価が1度のみであることにも注意してください。INOUT式は最初に出現したときに評価されます。出力の代入時に、式そのものは再評価されず、副作用も繰り返されません。

Java式の実行時評価の例(ISOコード生成)

ここでは、ISOコード生成でのアプリケーション実行時のJava式の評価方法について説明します。

注意:
Oracle固有コード生成を使用する場合、これらの作用を頼りにしないでください。これらの作用を利用する場合は、変換時にISOコード生成を要求してください。

前置演算子および後置演算子の評価

Java式にJavaの後置の増分演算子または減分演算子が含まれる場合、Java式が評価された後に、増分または減分が行われます。同様に、Java式にJavaの前置の増分演算子または減分演算子が含まれる場合、式が評価される前に、増分または減分が行われます。この動作は、標準のJavaコードでのこれらの演算子の処理方法と同じです。

後置演算子の例を次に示します。

int indx = 1;
...
#sql { ... :OUT (array[indx]) ... :IN (indx++) ... };

この例では、式が次のように評価されます。

#sql { ... :OUT (array[1]) ... :IN (1) ... };

indx変数は2に増やされ、:IN (indx++)が評価された後で次に出現するときはこの値になります。

この後置演算子の例を次に示します。

int indx = 1;
...
#sql { ... :OUT (array[indx++]) ... :IN (indx++) ... };

この例では、式が次のように評価されます。

#sql { ... :OUT (array[1]) ... :IN (2) ... };

変数indxは、最初の式が評価された後、2番目の式が評価される前に、2に増分されます。この変数は、2番目の式が評価されると3に増分され、次に出現するときはこの値になります。

前置演算子と後置演算子の両方を含む例を次に示します。

int indx = 1;
...
#sql { ... :OUT (array[++indx]) ... :IN (indx++) ... };

この例では、式が次のように評価されます。

#sql { ... :OUT (array[2]) ... :IN (2) ... };

変数indxは、最初の式が評価される前に、2に増分されます。この変数は、2番目の式が評価されると3に増分され、次に出現するときはこの値になります。

IN、INOUTおよびOUTホスト式の評価の順序

ホスト式は左から右に評価されます。式がIN、INOUTまたはOUTのいずれであるかは、評価の順序に影響しません。評価の順序を決めるのは、式が置かれる位置です。

次に示す例で確認してください。

int[5] arry;
int n = 0;
...
#sql { SET :OUT (arry[n]) = :(++n) };

この例では、式が次のように評価されます。

#sql { SET :OUT (arry[0]) = 1 };

入力式が出力式の前に評価されることを期待するかもしれませんが、この場合は異なります。式:OUT (arry[n])が最も左端の式であるため、最初に評価されます。前置演算子がnに作用するため、nが増分されてから++nが評価されます。そのため、++nは1と評価されます。nが最初に出現したときの値が0 (ゼロ)であったため、結果はarry[0]に代入されます(arry[1]ではありません)。

文の実行前に評価されるPL/SQLブロック内の式

PL/SQLブロック内のホスト式はすべて、いずれかが実行される前に、一度に評価されます。次に示す例で確認してください。

int x=3;
int z=5;
...
#sql { BEGIN :OUT x := 10; :OUT z := :x; END };
System.out.println("x=" + x + ", z=" + z);

この例では、式が次のように評価されます。

#sql { BEGIN :OUT x := 10; :OUT z := 3; END };

このため、出力はx=10、z=3となります。

PL/SQLブロック内の式はすべて、いずれかが実行される前に評価されます。この例では、2番目の文のホスト式、つまり:OUT zおよび:xが、最初の文が実行される前に評価されます。2番目の文が評価されるのは、xが元の値の3である場合で、式が評価された後にこのxに値10が代入されます。

ここでは、PL/SQLブロック内で式が評価される方法について、例を挙げて説明します。

int x=1, y=4, z=3;
...
#sql { BEGIN
:OUT x := :(y++) + 1;
:OUT z := :x;
END };

この例では、式が次のように評価されます。

#sql { BEGIN
:OUT x := 4 + 1;
:OUT z := 1;
END };

後置増分演算子は、:(y++)が評価された後に実行されます。このため、式はyの初期値である4と評価されます。2番目の文:OUT z := :xは、最初の文が実行される前に評価されます。そのため、xは、初期値の1のままです。このブロックの実行後、xの値は5、zの値は1になります。

次の例では、1つのSQLJ実行文のPL/SQLブロックに出現する2つの文と、個別の(連続した)SQLJ実行文に出現する同じ2つの文との違いについて説明します。

まず、PL/SQLブロック内に2つの文がある場合を考えます。

int y=1;
...
#sql { BEGIN :OUT y := :y + 1; :OUT x := :y + 1; END };

この例では、式が次のように評価されます。

#sql { BEGIN :OUT y := 1 + 1; :OUT x := 1 + 1; END };

2番目の文の:yは、いずれかの文が実行される前に評価されます。このため、yは最初の文からその出力をまだ受け取っていません。このブロックの実行後、xとyの両方の値が2になります。

次に、個別のSQLJ実行文のPL/SQLブロック内に、前の例と同じ2つの文がある場合を考えます。

int y=1;
#sql { BEGIN :OUT y := :y + 1; END };
#sql { BEGIN :OUT x := :y + 1; END };

最初の文は次のように評価されます。

#sql { BEGIN :OUT y := 1 + 1; END };

この式が実行された後で、 yに値2が代入されます。

最初の文の実行後、2番目の文が次のように評価されます。

#sql { BEGIN :OUT x := 2 + 1; END };

この場合、前述のPL/SQLブロックの例とは異なり、前の文の実行によりyはすでに値2を受け取っています。このため、2番目の文の実行後、xに値3が代入されます。

常に1度のみ評価されるPL/SQLブロック内の文

ホスト式の評価は、プログラム・フローやプログラム・ロジックにかかわらず、1度のみです。

次に示すループでのホスト式の評価の例を考えます。

int count = 0;
...
#sql {
DECLARE
n NUMBER
BEGIN
n := 1;
WHILE n <= 100 LOOP
:IN (count++);
n := n + 1;
END LOOP;
END
};

Java変数countがSQLに渡されるときの値は0 (ゼロ)になります。これは、この変数が前置演算子ではなく後置演算子で操作されるためです。その後、値は1に増分され、このPL/SQLブロックの実行中はその値を維持します。この変数は、SQLJ実行文の解析時に一度だけ評価され、SQLの実行前に値1で置き換えられます。

次に示す条件ブロック内のホスト式の評価の例を考えます。この例では、プログラム・フローに左右されずに式が評価される方法について説明します。ブロックの実行では、IF...THEN...ELSEコンストラクトの1つのブランチのみが実行可能です。ただし、ブロックの実行前に、そのブロック内のすべての式が文の出現順序に従って評価されます。

int x;
...
(operations on x)
...
#sql {
DECLARE
n NUMBER
BEGIN
n := :x;
IF n < 10 THEN
n := :(x++);
ELSE
n := :x * :x;
END LOOP;
END
};

xに対して実行された操作の結果、xの値が15になったとします。PL/SQLブロックの実行時には、ELSEブランチは実行されますがIFブランチは実行されません。ただし、PL/SQLブロック内の式はすべて、プログラム・ロジックやプログラム・フローにかかわらず、実行前に評価されます。このため、x++が評価されてからxが増分された後、各xが(x * x)式で評価されます。IF...THEN...ELSEブロックは次のように評価されます。

IF n < 10 THEN
n := 15;
ELSE
n := :16 * :16;
END LOOP;

xの初期値が15として、このブロックの実行後nの値が256になります。

結果式の前に左から右へ代入が行われる出力ホスト式

前述のように、OUTおよびINOUTホスト式がその出現順に従って左から右に代入され、結果式がある場合は最後に代入されます。同じ変数に対して複数回代入が行われた場合は、この順序に従って、最後に代入された内容で上書きされます。

同じ変数を参照する複数の出力ホスト式の例を次に示します。

#sql { CALL foo(:OUT x, :OUT x) };

foo()が、値2および3を出力する場合、SQLJ実行文の実行が終了すると、xの値は3になります。右端の代入が最後に行われるため、その値が優先されます。

同じオブジェクトを参照する複数の出力ホスト式の例を次に示します。

MyClass x = new MyClass();
MyClass y = x;
...
#sql { ... :OUT (x.field):=1 ... :OUT (y.field):=2 ... };

SQLJ実行文の実行後、x.fieldの値は、1ではなく2になります。これは、xがyと同じオブジェクトであり、fieldにまず値1が代入された後、値2が代入されたためです。

次の例は、ファンクションの出力結果が結果式に代入される場合と、結果がOUTホスト式に代入される場合の相違を示します。次に、invar入力パラメータ、outvar出力パラメータおよび戻り値を使用するファンクションを考えてみます。

CREATE FUNCTION fn(invar NUMBER, outvar OUT NUMBER)
RETURN NUMBER AS BEGIN
outvar := invar + invar;
return (invar * invar);
END fn;

次に、ファンクションの出力結果が結果式に代入される例を考えてみます。

int x = 3;
#sql x = { VALUES(fn(:x, :OUT x)) };

このファンクションは、入力パラメータとして3をとり、出力パラメータとして6を代入し、また戻り値として9を戻します。実行後、まず:OUT xに対して代入が行われ、xの値が6になります。ただし、最後には結果式に代入が行われ、xに代入されていた値6が、戻り値の9で上書きされます。このため、xが次に出現するとき、その値は9になります。

次の例では、ファンクションの出力結果が、結果式ではなくOUTホスト変数に代入されます。

int x = 3;
#sql { BEGIN :OUT x := fn(:x, :OUT x); END };

この場合は結果式がなく、OUT変数は単純に左から右へ代入されます。実行後、数式の左側にある最初の:OUT xに代入が行われ、xの値がファンクション戻り値の9になります。ただし、左から右へ進むと、数式の右側にある2番目の:OUT xに最後に代入が行われて、xが出力値の6になり、前にxに代入された値9がこの値6で上書きされます。このため、xが次に出現するとき、その値は6になります。

注意:
ここでは、ホスト式の評価方法の概念を説明するために、通常では使用しない例をいくつか示しています。実際のコードでは、1つの文またはPL/SQLブロック内で、OUTとINOUTまたはINホスト式に同じ変数を使用することはお薦めしません。このように記述した場合の動作は、Oracle SQLJ実装では明確に定義されていますが、SQLJ仕様では定義されていません。このため、この方法で記述されたコードは移植できません。セマンティクス・チェックの際にportableフラグに設定されていると、このようなコードに対してSQLJトランスレータからの警告が生成されます。

ホスト式の制限事項

ホスト式でin、outおよびinoutを識別子として使用する場合は、必ずカッコで囲みます。カッコで囲まないと、モード指定子と間違われる可能性があります。ホスト式の識別子には、大/小文字の区別がありません。

たとえば、inという入力ホスト変数を次のように指定したとします。

:(in)

または

:IN(in)

単一行の問合せ結果: SELECT INTO文

戻り値がデータ1行のみの場合、SQLJでは、選択項目をSQL構文内のJavaホスト式に直接代入できます。これは、SELECT INTO文を使用して行います。ここでは、次の項目について説明します。

- SELECT INTO構文

- SELECT INTO文の例

- SELECTリストにホスト式を使用する例

- SELECT INTOエラー状態

SELECT INTO構文

SELECT INTO文の構文を次に示します。

#sql { SELECT expression1,..., expressionN  INTO :host_exp1,..., :host_expN
FROM table <optional_clauses> };

次の注意事項があります。

- expression1 からexpressionN までは、データベースから選択するデータを指定する式です。すべてのSELECT文に有効な式を使用します。この式のリストは、SELECTリストと呼ばれます。単純な場合は、データベース表の列名になります。SELECTリストにはホスト式も記述できます。

- host_exp1 からhost_expN までは、変数や配列要素などのターゲット・ホスト式です。このホスト式のリストは、INTOリストと呼ばれます。

- table は、データを選択するデータベースの表、ビューまたはスナップショットの名前です。

- optional_clauses は、WHERE句など、SELECT文に追加する任意の句です。

SELECT INTO文の戻り値は、必ず1行のデータのみとします。それ以外の場合は、実行時にエラーが発生します。

デフォルトでは、INTOリストのホスト式はOUTですが、これを明示的に指定することも可能です。

#sql { SELECT column_name1, column_name2  INTO :OUT host_exp1, :OUT host_exp2
FROM table WHERE condition };

INTOリストでINまたはINTOトークンを使用すると、変換時にエラーが発生します。

注意:

- expression1 からexpressionN 、table およびオプションの句で使用できる構文は、SQL SELECT文の場合と同じです。

- 任意の数のSELECTリスト項目およびINTOリスト項目を使用できます。ただし、SELECTリスト項目ごとに、互換性のある型のINTOリスト項目を使用するようにします。

SELECT INTO文の例

この項の例では、次の行を持つ従業員表EMPを使用します。

CREATE TABLE EMP (
EMPNO NUMBER(4),
ENAME VARCHAR2(10),
HIREDATE DATE );

次に、INTOリストにホスト式1つを使用したSELECT INTO文の例を示します。

String empname;
#sql { SELECT ename INTO :enpname FROM emp WHERE empno=28959 };

次に、INTOリストに複数のホスト式を使用したSELECT INTO文の例を示します。

String empname;
Date hdate;
#sql { SELECT ename, hiredate INTO :empname, :hdate FROM emp
WHERE empno=28959 };

SELECTリストにホスト式を使用する例

INTOリストと同様に、SELECTリストにもJavaホスト式を使用できます。たとえば、次のように、1つのホスト式から他のホスト式に直接データを取り込むことも可能です(ただし、用途は限られています)。

...
#sql { SELECT :name1 INTO :name2 FROM emp WHERE empno=28959 };
...

次の例のように、選択されたデータに対して操作または連結を行う方がより現実的です。ここでは、必要に応じてJava変数がすでに宣言および代入されていることを前提としています。

...
#sql { SELECT sal + :raise INTO :newsal FROM emp WHERE empno=28959 };
...

...
#sql { SELECT :(firstname + " ") || emp_last_name INTO :name FROM myemp
WHERE empno=28959 };
...

2番目の例では、emp表に類似したmyempという表に、ename列ではなくemp_last_name列があるとします。SELECT文で、Javaホスト式とJavaの文字列連結演算子(+)を使用して、firstnameの後に空白1つ(" ")を追加します。この結果はSQLエンジンに渡され、SQLエンジンはSQLの文字列連結演算子(||)を使用して姓を追加します。

SELECT INTOエラー状態

SELECT INTO文は、1行のデータのみを戻す問合せ用です。0(ゼロ)行または複数の行を検索すると、SELECT INTO問合せは例外を戻します。

- 0(ゼロ)行を検索しているSELECT INTOは、「no data」状態を表す2000というSQL状態で例外を戻します。

- 複数行を検索しているSELECT INTOは、制約違反を表す21000というSQL状態で例外を戻します。

java.sql.SQLExceptionクラスのgetSQLState()メソッドによって、SQL状態を取得できます。

関連項目:
「SQLの状態およびエラー・コードの取出し」

これは、ISO SQLJ規格で指定されたベンダーに依存しない動作です。この場合、ベンダー固有エラー・コードはありません。エラー・コードは常に0(ゼロ)になります。

複数行の問合せ結果: SQLJイテレータ

多数のSQL操作は複数行の問合せです。SQLJで複数行の問合せ結果を処理するには、SQLJイテレータが必要です。SQLJイテレータは、強い型指定のJDBC結果セットであり、基になるデータベース・カーソルに対応付けられています。最初にSQLJイテレータが使用され、SELECT文からの問合せ結果を取得します。

Oracle SQLJでは、次の目的でSQLJイテレータと結果セットを使用できます。

- SQL実行文のOUTホスト変数として使用

- SELECT INTO文などのINTOリストのターゲットとして使用

- ストアド・ファンクション・コールからの戻り型として使用

- イテレータ宣言の列型として使用(基本的にはネストされたイテレータ)

注意:
前述の目的でSQLJイテレータを使用するには、そのクラスがpublicとして宣言されていることが必要です。クラスレベルまたはネストされたクラスレベルで宣言したイテレータは、public staticとして宣言することをお薦めします。

ここでは、次の項目について説明します。

- イテレータの概念

- イテレータの使用手順

- 名前付きイテレータ、位置イテレータおよび結果セット・イテレータ

- 名前付きイテレータの使用

- 位置イテレータの使用

- ホスト変数としてのイテレータおよび結果セットの使用

- イテレータ列としてのイテレータおよび結果セットの使用

関連項目:
「イテレータ・クラスの実装と高度な機能」

イテレータの概念

SQLJイテレータ宣言を使用すると、強い型指定のイテレータになります。これは、一般的なイテレータの使用方法で、SQLJセマンティクス・チェック機能のメリットを変換時に活用します。また、弱い型指定のイテレータを使用することも可能であり、利便性が高いこともあります。弱い型指定のイテレータを使用するために、インスタンス化できる汎用クラスがあります。

ここでは、次の項目について説明します。

- 強い型指定のイテレータの概要

- 弱い型指定のイテレータの概要

強い型指定のイテレータの概要

強い型指定のイテレータ・オブジェクトを使用する前に、イテレータ・クラスを宣言する必要があります。イテレータ宣言には、SQLJで生成されるJavaクラスを指定し、このクラス属性にはデータ列の型(および必要に応じて名前)を定義します。

SQLJイテレータ・オブジェクトは、事前定義された一定の列数で、前述のとおり個々に宣言されるイテレータ・クラスのインスタンスです。これに対して、JDBC結果セット・オブジェクトは、標準のjava.sql.ResultSetのインスタンスで、原則的には任意の型の列をいくつも持つことが可能です。

イテレータを宣言する際には、選択された列のデータ型のみを指定するか、選択された列のデータ型と名前の両方を指定します。

- 名前とデータ型を指定すると、名前付きイテレータ・クラスが定義されます。

- データ型のみを指定すると、位置イテレータ・クラスが定義されます。

宣言するデータ型(および名前)により、そのクラスからインスタンス化するイテレータ・オブジェクトへの問合せ結果の格納方法が決まります。イテレータ・オブジェクトに取り込まれたSQLデータは、イテレータ宣言で指定されたJava型に変換されます。

名前付きのイテレータ・オブジェクトに問合せ結果を代入する場合は、SELECT文内の列の名前やデータ型と、イテレータの列名や列型を一致させる必要があります。ただし、大/小文字の区別はありません。SELECT文内の列は、どのような順序でもかまいません。重要なことは、SELECT文の各列名をイテレータの列名に一致させることだけです。最も単純な例では、データベース列とイテレータ列とを同じ名前にすることです。

たとえば、データベース表のENAME列からのデータの選択や、イテレータename列への取込みができるようにしてください。また、データベースの列名とイテレータの列名とが異なる場合には、別名を使用して列名どうしをマッピングできるようにする必要があります。より複雑な問合せでは、2つの列の間で操作を実行し、その結果取得された列名が、対応するイテレータの列名と同じになるように変更できることが重要です。

SQLJイテレータは強い型指定であるため、SQLJのセマンティクス・チェック・フェーズで、Javaの型チェックを実行できます。

ここで示す例は、次のように定義された表を前提とします。

CREATE TABLE EMPSAL (
EMPNO NUMBER(4),
ENAME VARCHAR2(10),
OLDSAL NUMBER(10),
RAISE NUMBER(10) );

この表を使用すると、名前付きイテレータを宣言できます。

#sql iterator SalNamedIter (int empno, String ename, float raise);

宣言したら、次のように名前付きイテレータを使用できます。

class MyClass {
void func() throws SQLException {
...
SalNamedIter niter;
#sql niter = { SELECT ename, empno, raise FROM empsal };

... process niter ...
}
}

前述の例は、イテレータの列名と表の列名を同じにした場合の簡単な例です。名前付きイテレータを使用した場合は、SELECT文中にある項目はどのような順序でもかまいません。データは位置でなく名前で照合されます。

問合せを行い、位置イテレータ・オブジェクトにその結果を取り込む場合は、列の選択順に従ってデータが取り込まれます。データベース表から最初に選択された列のデータはイテレータの最初の列に、2番目に選択された列のデータはイテレータの2番目の列に、順を追って配置されます。表の列のデータ型は、イテレータ列のデータ型に変換可能である必要がありますが、イテレータ列には名前がないため、データベース列はどのような名前でもかまいません。

EMPSAL表では、次のように位置イテレータを宣言できます。

#sql iterator SalPosIter (int, String, float);

この位置イテレータは、次のように使用できます。

class MyClass {
void func() throws SQLException {
...
SalPosIter piter;
#sql piter = { SELECT empno, ename, raise FROM empsal };

... process piter ...
}
}

SELECT文でのデータ項目の順序は、イテレータでの順序と同じです。名前付きイテレータと位置イテレータとでは処理が異なります。

イテレータの注意事項

前のコンセプトで述べたことの他に、イテレータ全般に関しては次のような注意事項に留意してください。

- イテレータにデータを移入する際にSELECT *構文を使用することはお薦めしません。位置イテレータにこの構文を使用する場合、表の列数とイテレータの列数が一致し、データ型も一致する必要があります。また、名前付きイテレータにこの構文を使用する場合は、表の列数をイテレータの列数と同じかそれより多くなるようにし、各イテレータ列の名前とデータ型をデータベース表と同じにする必要があります。ただし、トランスレータの-warn=nostrictフラグが設定されていないと、表の列数がイテレータの列数より多い場合には、警告が生成されます。

関連項目:
「トランスレータからの警告(-warn)」

- 位置イテレータと名前付きイテレータは、互換性のない別々のJavaクラスです。ある種類のイテレータ・オブジェクトから別の種類のイテレータ・オブジェクトへのキャストはできません。

- SQLカーソルとは異なり、イテレータ・インスタンスはファーストクラスのJavaオブジェクトです。そのため、イテレータ・インスタンスは、たとえばメソッド・パラメータとして受け渡すことができます。また、イテレータ・インスタンスは、publicやprivateなどのJavaクラス修飾子を使用して宣言することもできます。

- SQLJでは、SQLJイテレータとJDBC結果セットとの連係性および変換がサポートされています。

関連項目:
「SQLJイテレータとJDBC結果セットの連係動作」

- 一般に、イテレータを設定したSELECT文が実行された時点でのデータベースの状態のみによって、そのイテレータの内容が決まります。それ以降にUPDATE、INSERT、DELETE、COMMIT、ROLLBACKなどの操作を行っても、イテレータやその内容には反映されません。これに対する例外は、イテレータがスクロール可能で、データの変更に対してsensitiveであると宣言する場合です。

関連項目:
「イテレータおよび結果セットに対するコミットおよびロールバックの影響」、「スクロール可能なイテレータの宣言」および「スクロール可能なイテレータの更新検出」

弱い型指定のイテレータの概要

イテレータ・クラスを宣言しない場合は、Oracle SQLJ実装で弱い型指定のイテレータを使用できます。このようなイテレータを結果セット・イテレータと呼びます。簡単な(スクロール不可能)結果セット・イテレータを使用するには、sqlj.runtime.ResultSetIteratorクラスをインスタンス化します。スクロール可能な結果セット・イテレータを使用するには、sqlj.runtime.ScrollableResultSetIteratorクラスをインスタンス化します。

結果セット・イテレータを使用する場合のデメリットは、強い型指定のイテレータと比較すると、SQLJでは問合せへのセマンティクス・チェックを同じように実行できないことです。

関連項目:
「スクロール可能なイテレータ」および「結果セット・イテレータ」

イテレータの使用手順

SQLJ名前付きイテレータまたは位置イテレータを使用する場合は、次の手順に従ってください。

1. SQLJ宣言を使用して、イテレータ・クラス、つまりイテレータの種類を定義します。

2. イテレータ・クラスの変数を宣言します。

3. SELECT文を使用した後、イテレータ変数にSQL問合せ結果を取り込みます。

4. イテレータの問合せ列にアクセスします。名前付きイテレータと位置イテレータではアクセス方法が異なります。

5. 問合せ結果の処理が終了した後、イテレータを閉じてそのリソースを解放します。

名前付きイテレータ、位置イテレータおよび結果セット・イテレータ

名前付きイテレータと位置イテレータには、それぞれのメリットがあり、使用目的も異なります。

名前付きイテレータは、より柔軟に使用できます。選択されたデータを名前付きイテレータに取り込むときは、SELECT文内の列とイテレータ列との整合チェックは名前で判定されるため、問合せの順序は判定基準にはなりません。この場合、データが誤った列に取り込まれることがないため、エラーが少なくなります。名前が一致しない場合は、データベースに対してSQL文をチェックするときに、SQLJトランスレータがエラーを生成します。

位置イテレータの場合は、他の埋込みSQL言語と同様のパラダイムや構文を使用できます。たとえば、名前付きイテレータではデータの取込みにnext()メソッドを使用しますが、位置イテレータではPro*Cの場合と似たFETCH INTO構文を使用します。各フェッチが暗黙的にイテレータを次の行へ進め、その後で次の値が取り出されます。

また、位置イテレータの場合は、イテレータ列に選択するデータを名前ではなく位置によって識別するため、柔軟性に欠けます。SELECT文では、項目の順序に注意する必要があるからです。また、イテレータのすべての列にデータを選択する必要もあります。このとき、表で選択されている列のデータ型に偶然一致した他のイテレータ列に、データが誤って書き込まれる可能性もあります。

位置イテレータでは、個々のデータ要素へのアクセスも不便です。名前付きイテレータではデータを名前に基づいて格納するため、各列に対して便利なアクセッサ・メソッドを使用できます。たとえば、enameイテレータ列からのデータの取出しには、ename()メソッドを使用できます。位置イテレータでは、FETCH INTO文でデータを直接Javaホスト式にフェッチする必要があるうえ、ホスト式を正しい順序で記述することが必要です。

問合せに対して強い型指定のイテレータ・クラスを宣言しない場合は、弱い型指定の結果セット・イテレータを使用できます。結果セット・イテレータは、JDBCコードからSQLJコードへの変換時に最も便利です。この考慮事項は、結果セット・イテレータ(ResultSetIteratorインスタンスまたはScrollableResultSetIteratorインスタンス)では、変換時に完全なSQLJセマンティクス・チェックができないという点と比較する必要があります。名前付きイテレータまたは位置イテレータの場合、SQLJによって、SELECT文内の列のデータ型が、生成されたデータのJava型と一致していることが検証されます。結果セット・イテレータの場合は、このことは検証できません。

関連項目:
「結果セット・イテレータ」

イテレータの比較についての注意

SQLJイテレータについて、次の点を注意してください。

- 位置イテレータに移入する際、データベースから選択する列の数は、イテレータの列の数と同じである必要があります。名前付きイテレータへの移入では、データベースから選択する列数が、イテレータの列数より少なくなることはありませんが、トランスレータ-warn=nostrictフラグを設定すると、イテレータの列数より多くなる可能性があります。この場合、一致しない列は無視されます。

関連項目:
「トランスレータからの警告(-warn)」

- フェッチの一般的な意味は、データベースからのデータのフェッチのことですが、位置イテレータに対してFETCH INTO文を実行した場合は、サーバーへのラウンドトリップが必要であるとは限りません。これは、行プリフェッチの値によって異なります。これは、データベースではなくイテレータからデータをフェッチするためです。行プリフェッチの値が1であるときは、各フェッチのたびにデータベースへのトリップが1回行われます。データベースへの1回のトリップで取り出される行の数は、行プリフェッチの値によって判断されます。

関連項目:
「行プリフェッチ」

- 結果セット・イテレータでは、位置イテレータと同じFETCH INTO構文が使用され、実行時に同じ制限を受けます。つまり、SELECTリスト内のデータ項目の数とFETCH文の代入されたデータである変数の数が一致する必要があります。

名前付きイテレータの使用

名前付きイテレータ・クラスを宣言する場合は、イテレータの各列のデータ型と名前を宣言します。データを名前付きイテレータに取り出す場合、SELECT文内の列とイテレータ列とを次の2つの面で同じにしておく必要があります。

- SELECT文内の各データ項目の名前(表の列名または別名)が、イテレータ列と同じ名前である必要があります。ただし、大/小文字の区別はありません。そのため、enameおよびEnameのいずれもENAMEと一致します。

- 各イテレータ列のデータ型は、標準のJDBC型マッピングに従って、SELECT文内の対応するデータ項目のデータ型との互換性を持つ必要があります。

名前付きイテレータ・クラスの宣言では、属性の宣言はどのような順序で行ってもかまいません。データは、名前に基づいてイテレータに選択されます。

名前付きイテレータの場合は、next()メソッドでデータを行ごとに取り出し、それぞれの列のアクセッサ・メソッドで個々のデータ項目を取り込みます。アクセッサ・メソッド名は列名と同じです。ほとんどのJavaのアクセッサ・メソッド名とは異なり、名前付きイテレータの場合、アクセッサ・メソッド名がgetで始まることはありません。たとえば、sal列を持つ名前付きのイテレータ・オブジェクトの場合は、使用するアクセッサ・メソッドがsal()という名前になります。

注意:
名前付きイテレータの列のネーミングには、次の制約事項が適用されます。

- 列名にJavaの予約語は使用できません。

- 列名には、next()、close()、getResultSet()およびisClosed()など、名前付きイテレータ・クラスのユーティリティ・メソッドと同じ名前は使用できません。スクロール可能な名前付きイテレータの場合、previous()、first()およびlast()などのメソッドも使用できません。

名前付きイテレータ・クラスの宣言

名前付きイテレータ・クラスの宣言には、次の構文を使用します。

#sql <modifiers> iterator classname <implements clause> <with clause>
( type-name-list );

この構文のmodifiers は正当なJavaクラス修飾子の順序で、その使用は任意です。classname はイテレータのクラス名です。また、type-name-list は、Javaの型と名前のリストです。これは、データベース表の列型と列名に相当します。

implements句とwith句の使用は任意です。前者は実装するインタフェースを、後者は定義および初期化する変数を指定します。

関連項目:
「IMPLEMENTS句宣言」および「WITH句宣言」

次のような表について考えてみます。

CREATE TABLE PROJECTS (
ID NUMBER(4),
PROJNAME VARCHAR(30),
START_DATE DATE,
DURATION NUMBER(3) );

この表で使用する名前付きイテレータは、次のように宣言できます。

#sql public iterator ProjIter (String projname, int id, Date deadline);

この結果、アクセッサ・メソッドprojname()、id()およびdeadline()でアクセス可能なデータ列を持つ、イテレータ・クラスが生成されます。

注意:
標準Javaの場合と同様に、Publicクラスは、次のいずれかの方法で宣言する必要があります。

- 別個のソース・ファイル中に宣言する方法。ファイルのベース名はクラス名と同じにします。

- public static修飾子を使用して、クラスレベルの有効範囲またはネストされたクラスレベルの有効範囲に宣言する方法。

Sun社のJDKの標準javacコンパイラを使用する場合は、これが要件となります。

名前付きイテレータのインスタンス化と移入

前の項で定義したPROJECTS表とProjIterイテレータを引き続き使用します。表にはイテレータのid列とprojname列と同じ名前とデータ型の列があります。ただし、別名を使用して、イテレータのdeadline列への移入操作を実行する必要があります。次に例を示します。

ProjIter projsIter;

#sql projsIter = { SELECT start_date + duration AS deadline, projname, id
FROM projects WHERE start_date + duration >= sysdate };

この例では、開始日に期間を加算してプロジェクトの最終期限を算出し、deadlineイテレータ列と同じdeadlineという名前をその結果に別名として付けます。また、WHERE句を使用して、現行のシステムの日付より先の最終期限のみが処理されるようにしています。

同様に、ファンクション・コールを使用する場合も、別名を作成する必要があります。MAXIMUM()というファンクションがあると仮定し、このファンクションでは入力としてDURATIONエントリおよび整数をとり、この2つのうち大きい方を戻すとします。たとえば、使用しているアプリケーションで各プロジェクトの期間が3か月以上になるようにするには、値3を入力します。

ここでは、イテレータを次のように宣言したとします。

#sql public iterator ProjIter2 (String projname, int id, float duration);

問合せに使用するMAXIMUM()ファンクションには、次のように問合せ結果に対して別名を指定できます。

ProjIter2 projsIter2;

#sql projsIter2 = { SELECT id, projname, maximum(duration, 3) AS duration
FROM projects };

通常、正当なJava識別子ではない名前、またはイテレータの列名とは異なる名前の付いたSELECT文内のデータ項目の問合せには、別名を使用してください。

前述のように、名前付きイテレータを使用した場合、通常はデータベースから選択できる列数が、イテレータの列数より少なくなることはありません。一致しない列は無視されるため、イテレータの列数を上回る数の列を選択することも不可能ではありません。ただし、SQLJの-warn=nostrictオプションが設定されていないと、警告が生成されます。

名前付きイテレータへのアクセス

名前付きイテレータ・オブジェクトのnext()メソッドを使用すると、選択されて入力されたデータを1行ずつ取得できます。各行の各列にアクセスするには、SQLJで生成されるアクセッサ・メソッドを使用します(通常は、whileループ内で使用します)。

next()がコールされると、次の処理が行われます。

- イテレータから取り出す行がまだ他にも存在するときは、next()のコールでその行を取り出し、trueを戻り値とします。

- イテレータから取り出す行がもう存在しないときは、next()のコールでfalseを戻り値とします。

次に、名前付きイテレータのデータにアクセスする方法の例を示します。この例では、前の項に示した宣言、インスタンス化および移入を再び使用します。

注意:
イテレータからのデータの取出しが終了した後に、各イテレータのclose()メソッドを必ずコールしてください。このコールは、イテレータを閉じてリソースを解放するために必要です。

次に示すようにイテレータ・クラスを宣言するとします。

#sql public iterator ProjIter (String projname, int id, Date deadline);

次に示すように、このイテレータ・クラスのインスタンスを定義してからアクセスします。

// Declare the iterator variable
ProjIter projsIter;

// Instantiate and populate iterator; order of SELECT doesn't matter
#sql projsIter = { SELECT start_date + duration AS deadline, projname, id
FROM projects WHERE start_date + duration >= sysdate };

// Process the results
while (projsIter.next()) {
System.out.println("Project name is " + projsIter.projname());
System.out.println("Project ID is " + projsIter.id());
System.out.println("Project deadline is " + projsIter.deadline());
}

// Close the iterator
projsIter.close();
...

前述に示したデータの取出しでは、projname()、id()およびdeadline()アクセッサ・メソッドが簡単に使用できます。SELECT項目の順序やアクセッサ・メソッドを使用する順序は、あまり関係ありません。

ただし、アクセッサ・メソッド名は、イテレータ・クラスの宣言で大文字を使用した場合は大文字で、小文字を使用した場合は小文字で生成されます。コンパイル・エラーが発生する例を、次に示します。

次のイテレータを宣言するとします。

#sql iterator Cursor1 (String NAME);

イテレータを使用するためのコードは次のようになります。

...
Cursor1 c1;
#sql c1 = { SELECT NAME FROM TABLE };
while (c1.next()) {
System.out.println("The name is " + c1.name());
}
...

Cursor1クラスのメソッドはNAME()であり、name()ではありません。System.out.println文では、c1.NAME()を使用する必要があります。

位置イテレータの使用

位置イテレータの宣言では、各列のデータ型は宣言しますが、列名は定義しません。SQL問合せ結果の列が取り出されるJava型は、SQLデータのデータ型との互換性があることが必要です。データベースの列やSELECT文内のデータ項目の名前は、関係がありません。名前が使用されないため、位置イテレータのJava型を宣言する順序と、データを選択する順序が完全に一致する必要があります。

位置イテレータにデータが選択された後、位置イテレータからデータを取り出すには、FETCH INTO文を使用します。さらに、endFetch()メソッドをコールして、データの終わりに到達したかどうかを確認します。

位置イテレータ・クラスの宣言

位置イテレータ・クラスの宣言には、次の構文を使用します。

#sql <modifiers> iterator classname <implements clause> <with clause>
( position-list );

この構文のmodifiers は正当なJavaクラス修飾子の順序で、その使用は任意です。また、position-list は、データベース表の列型に変換可能なJava型のリストです。

implements句とwith句の使用は任意です。前者は実装するインタフェースを、後者は定義および初期化する変数を指定します。

関連項目:
「IMPLEMENTS句宣言」および「WITH句宣言」

ここでは、次の行を持つ従業員表EMPを想定します。

CREATE TABLE EMP (
EMPNO NUMBER(4),
ENAME VARCHAR2(10),
SAL NUMBER(7,2) );

次のような位置イテレータを宣言します。

#sql public iterator EmpIter (String, int, float);

前述の例では、JavaクラスEmpIterの定義に、匿名のString、intおよびfloatが使用されています。実際には、String型がENAMEに対応し、int型がEMPNOに対応しますが、この表とイテレータとでは、それぞれの列の順序が対応していないことに注意してください。イテレータ列の順序によって、データを選択する順序が決まります。

注意:
標準Javaの場合と同様に、Publicクラスは、次のいずれかの方法で宣言する必要があります。

- 別個のソース・ファイル中に宣言する方法。ファイルのベース名はクラス名と同じにします。

- public static修飾子を使用して、クラスレベルの有効範囲またはネストされたクラスレベルの有効範囲に宣言する方法。

Sun社のJDKの標準javacコンパイラを使用する場合は、これが要件となります。

位置イテレータのインスタンス化と移入

位置イテレータのインスタンス化と移入は、名前付きイテレータの場合と同じです。ただし、SELECT文内のデータ項目の順序が適切であるかどうかを確認する必要があります。

EmpIterイテレータ・クラスの3つのデータ型は、EMP表の型と互換性がありますが、それぞれの順序は対応していないため、データの選択方法には注意が必要です。次の例は、SELECT文内のデータ項目がイテレータの列と同じ順序であるため、正常に実行できます。

EmpIter empsIter;

#sql empsIter = { SELECT ename, empno, sal FROM emp };

前述のように、位置イテレータを使用する場合は、データベースから選択する列の数と、イテレータの列の数を同じにする必要があります。

位置イテレータへのアクセス

位置イテレータで定義された列にアクセスするには、SQLのFETCH INTO構文を使用します。コマンドのINTO部分には、結果列を受け取るJavaホスト変数を指定します。ホスト変数の順序は、対応するイテレータ列の順序と同じにする必要があります。endFetch()メソッドを使用して、最後のフェッチがデータの末尾に達したかどうかを確認します(このメソッドは、すべての位置イテレータ・クラスで使用できます)。

注意:

- endFetch()メソッドの行のフェッチ開始前の初期戻り値はtrueで、行の取出しが正常に行われると戻り値がfalseになり、FETCHがすべての行の取出しが終了したとみなした時点で戻り値は再びtrueになります。このため、endFetch()テストは、FETCH INTO文の後に行う必要があります。FETCH INTO文の前にendFetch()テストを行うと、行を取り出せなくなります。これは、最初のFETCHの前にendFetch()がTRUEになり、すぐにwhileループから抜けてしまうためです。

- ただし、endFetch()テストは、結果が処理される前に行う必要があります。FETCHは、データの最後に達してもSQL例外をスローすることはなく、単に次のendFetch()コールをトリガーしてtrueを戻すためです。結果が処理される前にendFetch()テストをしておかないと、データの最後に到達した後に、コード中の最初のFETCHでの戻り値(NULLまたは無効なデータ)に対して処理が試みられます。

- イテレータからのデータの取出しが終了した後に、各イテレータのclose()メソッドを必ずコールしてください。このコールは、イテレータを閉じてリソースを解放するために必要です。

次に例では、前の項に示した宣言、インスタンス化および移入を再度示します。SELECT文中のJavaホスト変数の順序は、位置イテレータの列の順序と同じです。これは必須条件です。

最初に、次のようにイテレータ・クラスを宣言するとします。

#sql public iterator EmpIter (String, int, float);

次に示すように、このイテレータ・クラスのインスタンスを定義してからアクセスします。

// Declare and initialize host variables
int empnum=0;
String empname=null;
float salary=0.0f;

// Declare an iterator instance
EmpIter empsIter;

#sql empsIter = { SELECT ename, empno, sal FROM emp };

while (true) {
#sql { FETCH :empsIter INTO :empnum, :empname, :salary };
if (empsIter.endFetch()) break;  // This test must be AFTER fetch,
// but before results are processed.
System.out.println("Name is " + empname);
System.out.println("Employee number is " + empnum);
System.out.println("Salary is " + salary);
}

// Close the iterator
empsIter.close();
...

empname、empnumおよびsalary変数は、Javaホスト変数です。これらの変数の型は、イテレータ列の型と対応させる必要があります。

位置イテレータでは、next()メソッドを使用しないでください。このメソッドは、FETCH操作が次の行に進むときに暗黙的にコールされます。

注意:
FETCH INTO文のホスト変数は、条件文の1つのブランチで代入されるため、必ず初期化する必要があります。初期化しないと、ホスト変数の代入が行われないことを通知するコンパイル・エラーが表示されます。フェッチ対象の行がある場合にのみ、FETCHで変数が代入されます。

next()メソッドによる位置イテレータ・ナビゲーション

前の項で説明した位置イテレータFETCH句では、ホスト変数(ある場合)に移入する前に、暗黙的なnext()コールによって移動が実行されています。この方法のかわりに、Oracle SQLJ実装では、JDBC結果セットおよびSQLJ名前付きイテレータと同じ移動ロジックを使用するために、特別なFETCH構文を明示的なnext()コールと併用する方法がサポートされています。この特別なFETCH構文を使用すると、セマンティクスが変化します。INTOリストに移入される前の暗黙的なnext()コールがなくなります。

関連項目:
「FETCH CURRENT構文: JDBC結果セットからSQLJイテレータへ」

ホスト変数としてのイテレータおよび結果セットの使用

SQLJでは、ホスト変数としてのSQLJイテレータおよびJDBC結果セットの使用がサポートされています。イテレータと結果セットの使用方法は基本的には同じですが、宣言やデータを取り出すアクセッサ・メソッドが異なります。

注意:

- また、SQLJでは、ストアド・ファンクションの戻り値としてイテレータおよび結果セットを使用できます。

- Oracle JDBCドライバでは、現在、入力ホスト変数としての結果セットの使用がサポートされていません。OraclePreparedStatementクラスにはsetCursor()メソッドがありますが、これをコールすると、実行時に例外が発生します。

ここでの例は、次の部門表および従業員表を想定します。

CREATE TABLE DEPT (
DEPTNO NUMBER(2),
DNAME VARCHAR2(14) );

CREATE TABLE EMP (
EMPNO NUMBER(4),
ENAME VARCHAR2(10),
SAL NUMBER(7,2),
DEPTNO NUMBER(2) );

OUTホスト変数としての結果セットの使用の例

この例では、JDBC結果セットを出力ホスト変数として使用しています。

...
ResultSet rs;
...
#sql { BEGIN
OPEN :OUT rs FOR SELECT ename, empno FROM emp;
END };

while (rs.next())
{
String empname = rs.getString(1);
int empnum = rs.getInt(2);
}
rs.close();
...

この例では、結果セットrsをPL/SQLブロックでオープンしてSELECT文からのデータを受け取り、EMP表のENAME列とEMPNO列のデータを選択し、結果セットをループしてデータをローカル変数に取り出します。

OUTホスト変数としてのイテレータの使用の例

この例では、名前付きイテレータを出力ホスト変数として使用しています。

イテレータは、次のように宣言できます。

#sql public <static> iterator EmpIter (String ename, int empno);

public修飾子は必須です。クラスレベルまたはネストされたクラスレベルでの宣言ではstatic修飾子も使用することをお薦めします。

このイテレータは、次のように使用できます。

...
EmpIter iter;
...
#sql { BEGIN
OPEN :OUT iter FOR SELECT ename, empno FROM emp;
END };

while (iter.next())
{
String empname = iter.ename();
int empnum = iter.empno();

...process/output empname and empnum...
}
iter.close();
...

この例では、イテレータiterをPL/SQLブロックでオープンしてSELECT文からのデータを受け取り、EMP表のENAME列とEMPNO列のデータを選択し、イテレータをループさせてデータをローカル変数に取り出します。

SELECT INTOのOUTホスト変数としてのイテレータの使用の例

この例では、名前付きイテレータを出力ホスト変数として使用し、SELECT INTO文を介してデータを取得しています。INTOリスト内のホスト変数のデフォルトは、OUTです。

イテレータは、次のように宣言できます。

#sql public <static> iterator ENameIter (String ename);

public修飾子は必須です。クラスレベルまたはネストされたクラスレベルでの宣言ではstatic修飾子も使用することをお薦めします。

このイテレータは、次のように使用できます。

...
ENameIter enamesIter;
String deptname;
...

#sql { SELECT dname, cursor
(SELECT ename FROM emp WHERE deptno = dept.deptno)
INTO :deptname, :enamesIter FROM dept WHERE deptno = 20 };

System.out.println(deptname);
while (enamesIter.next())
{
System.out.println(enamesIter.ename());
}
enamesIter.close();
...

この例では、ネストされたSELECT文を使用して次の処理を行います。

- DEPT表から従業員番号20の名前を選択し、出力ホスト変数deptnameに取り込みます。

- EMP表を問い合せ、部門番号が20の従業員をすべて選択した後で、カーソルに格納された結果を、出力ホスト変数enamesIter(名前付きイテレータ)に取り込みます。

- 部門名を出力します。

- 従業員名を出力する名前付きイテレータを、ループさせます。こうして、この部門の全従業員の名前が出力されます。

大抵の場合、外部のSELECT内にある1行を取り出すときはSELECT INTOを使用した方が、ネストされたイテレータよりも便利です。また、ネストされたイテレータを使用した場合は、データを処理して外部のSELECT中にある行数を求める必要があります。これに対し、SELECT INTOを使用すると、1行のみで済みます。

イテレータ列としてのイテレータおよび結果セットの使用

Oracle SQLJ実装では、イテレータ宣言で、ResultSet型の列、または現在のスコープで宣言されたその他のイテレータ型の列を指定することが可能です。つまり、イテレータ内で他のイテレータや結果セットを使用できます。これらの列型は、カーソルで列を取得するのに使用されます。この機能は、ネストした表の情報を戻り値とするネストされたSELECT文に便利です。

次に、機能的には同じ例をいくつか示します。これらの例では、ネストされた結果セットまたはイテレータ(他のイテレータ内の列にある結果セットまたはイテレータ)を使用して、DEPT表から各部門に所属する従業員をすべて出力します。最初の例では名前付きイテレータ内の結果セットを、2番目の例では名前付きイテレータ内の名前付きイテレータを、3番目の例では位置イテレータ内の名前付きイテレータを使用します。

手順を次に示します。

1. DEPT表で各部門名(DNAME)を問い合せます。

2. ネストされたSELECTを実行し、各部門のEMP表から取得した全従業員数をカーソルに取り込みます。

3. 取得した部門名と部門別従業員数を、名前列とイテレータ列を持つ外部イテレータ(iter)に取り込みます。特定部門の従業員情報を持つカーソルは、外部イテレータの当該部門の行に対応するイテレータ列に移動します。

4. ネステッド・ループを巡回することによって、部門別に部門名を出力し、その後、内部イテレータ内で部門別の全従業員の名前を出力します。

名前付きイテレータ内の結果セット列の例

この例では、名前付きイテレータでResultSet型の列を使用します。

イテレータは、次のように宣言できます。

#sql iterator DeptIter (String dname, ResultSet emps);

イテレータを使用するコードは次のようになります。

...
DeptIter iter;
...
#sql iter = { SELECT dname, cursor
(SELECT ename FROM emp WHERE deptno = dept.deptno)
AS emps FROM dept };

while (iter.next())
{
System.out.println(iter.dname());
ResultSet enamesRs = iter.emps();
while (enamesRs.next())
{
String empname = enamesRs.getString(1);
System.out.println(empname);
}
enamesRs.close();
}
iter.close();
...

名前付きイテレータ内の名前付きイテレータ列の例

この例では、前に定義された名前付きイテレータ(ネストされたイテレータ)と同じ型の列を持つ、名前付きイテレータを使用します。

イテレータの宣言は、次のようになります。

#sql iterator ENameIter (String ename);
#sql iterator DeptIter (String dname, ENameIter emps);

このイテレータを使用するコードは次のようになります。

...
DeptIter iter;
...
#sql iter = { SELECT dname, cursor
(SELECT ename FROM emp WHERE deptno = dept.deptno)
AS emps FROM dept };

while (iter.next())
{
System.out.println(iter.dname());
ENameIter enamesIter = iter.emps();
while (enamesIter.next())
{
System.out.println(enamesIter.ename());
}
enamesIter.close();
}
iter.close();
...

位置イテレータ内の名前付きイテレータ列の例

この例では、前に定義された名前付きイテレータ(ネストされたイテレータ)と同じ型の列を持つ、位置イテレータを使用します。ここでは、位置イテレータのFETCH INTO構文を使用します。この例は、機能的には前述の2つの例と同じです。

外部イテレータは位置イテレータです。このため、外部指定イテレータが名前付きイテレータである前の例とは異なり、列名を一致させる場合に別名は必要ありません。

イテレータの宣言は、次のようになります。

#sql iterator ENameIter (String ename);
#sql iterator DeptIter (String, ENameIter);

このイテレータを使用するコードは次のようになります。

...
DeptIter iter;
...
#sql iter = { SELECT dname, cursor
(SELECT ename FROM emp WHERE deptno = dept.deptno)
FROM dept };

while (true)
{
String dname = null;
ENameIter enamesIter = null;
#sql { FETCH :iter INTO :dname, :enamesIter };
if (iter.endFetch()) break;
System.out.println(dname);
while (enamesIter.next())
{
System.out.println(enamesIter.ename());
}
enamesIter.close();
}
iter.close();
...

代入文(SET)

SQLJでは、SQL操作内のJavaホスト式に値を代入できます。これは代入文と呼ばれ、次の構文で記述されます。

#sql { SET :host_exp = expression };

host_exp は、変数や配列索引などのターゲット・ホスト式です。expressionには、数字、ホスト式、算術式、ファンクション・コール、または有効な結果を生成してターゲット・ホスト式に入力するその他のコンストラクトを使用できます。

代入文のターゲット・ホスト式のデフォルトはOUTですが、これを明示的に記述することも可能です。

#sql { SET :OUT host_exp = expression };

代入文でINまたはINOUTトークンを使用すると、変換時にエラーが発生します。

前述の2つの文は、機能的には次のPL/SQLコードと同じです。

#sql { BEGIN :OUT host_exp := expression; END };

次に、代入文の単純な例を示します。

#sql { SET :x = foo1() + foo2() };

この文では、foo1()とfoo2()の戻り値の合計をxに代入し、xの型が、ファンクションの出力合計の型と互換性がある場合を想定しています。

次の例についても考えてみます。

int i2;
java.sql.Date dat;
...
#sql { SET :i2 = TO_NUMBER(substr('750 etc.', 1, 3)) +
TO_NUMBER(substr('250 etc.', 1, 3)) };
...
#sql { SET :dat = sysdate };
...

最初の文では、値1000をi2に代入します。substr()コールでは、文字列の最初の3文字(750と250)を使用します。TO_NUMBER()コールでは、文字列が数値750と250に変換されます。

2番目の文では、データベース・システムの日付が読み取られ、それがdatに代入されます。

データベースに格納されているファンクションから戻される変数に対して操作を実行する場合、代入文を使用すると便利です。単にファンクションの結果を変数に代入する場合は、標準のファンクション・コールの構文で実現できるため、代入文は必要ありません。Javaファンクションの出力を操作する場合も、一般的なJava文で実現できるため、代入文は必要ありません。したがって、foo1()およびfoo2()は、Javaファンクションではなく、データベース内のストアド・ファンクションと仮定することもできます。

ストアド・プロシージャおよびストアド・ファンクションのコール

SQLJには、データベース内のストアド・プロシージャやストアド・ファンクションのコールに便利な構文があります。ストアド・プロシージャやストアド・ファンクションは、Java、PL/SQLまたはデータベースでサポートされるその他の言語のいずれでも記述できます。

ストアド・ファンクションの場合、戻り値を受け取るために、SQLJ実行文内に結果式が必要です。また、必要に応じて入力パラメータ、出力パラメータおよび入出力パラメータも使用できます。

ストアド・プロシージャの場合、戻り値はありません。オプションで、入力パラメータ、出力パラメータおよび入出力パラメータを使用できます。ストアド・プロシージャでは、任意の出力または入出力パラメータを介して、出力が戻されます。

注意:
ここで説明するプロシージャ・コールやファンクション・コールの構文を使用するかわりに、JPublisherでPL/SQLストアド・プロシージャおよびストアド・ファンクション用のJavaラッパーを作成し、他のJavaメソッドの場合と同様に、Javaラッパーをコールすることも可能です。JPublisherの詳細は、「JPublisherとカスタムJavaクラスの作成」で説明します。詳細は、『Oracle Database JPublisherユーザーズ・ガイド』を参照してください。

ここでは、次の項目について説明します。

- ストアド・プロシージャのコール

- ストアド・ファンクションのコール

- ストアド・ファンクションの戻り値としてのイテレータおよび結果セットの使用

ストアド・プロシージャのコール

ストアド・プロシージャには戻り値がありませんが、入力パラメータ、出力パラメータおよび入出力パラメータとしてリストを使用できます。ストアド・プロシージャのコールでは、CALLトークンを使用します。CALLトークンのすぐ後に空白を1つ挿入した後に、プロシージャ名を記述します。プロシージャ名と区別するため、CALLトークンの後には空白が必要です。プロシージャ・コールをカッコで囲むことはできません。これは、ファンクション・コールの構文とは異なります。CALLトークンの構文は次のとおりです。

#sql { CALL PROC(<PARAM_LIST>) };

PROC はストアド・プロシージャ名で、入力パラメータ、出力パラメータおよび入出力パラメータを使用できます。PROC には、スキーマ名またはパッケージ名を含めることも可能で、たとえば、SCOTT.MYPROC()となります。

次のPL/SQLストアド・プロシージャを定義するとします。

CREATE OR REPLACE PROCEDURE MAX_DEADLINE (deadline OUT DATE) IS
BEGIN
SELECT MAX(start_date + duration) INTO deadline FROM projects;
END;

この例では、PROJECTS表を読み込み、START_DATE列とDURATION列を検索し、各行のstart_date + durationを計算した後で、START_DATE + DURATIONの合計の最大値がDEADLINEに割り当てられます。これはDATE型の出力パラメータです。

SQLJでは、このMAX_DEADLINEプロシージャを次のようにコールできます。

java.sql.Date maxDeadline;
...
#sql { CALL MAX_DEADLINE(:out maxDeadline) };

どのパラメータに対しても、ホスト式のトークンIN、OUTおよびINOUTを使用して、ストアド・プロシージャの入力先、出力先および入出力先のパラメータと対応させてください。また、パラメータ・リストで使用するホスト変数の型も、ストアド・プロシージャのパラメータ型に対応させる必要があります。

注意:
アプリケーションにOracle7データベースとの互換性を確保する場合は、プロシージャがパラメータをとらないときに、パラメータ・リストに空のカッコを含めないでください。次に例を示します。

#sql { CALL MAX_DEADLINE };

次のようには定義できません。

#sql { CALL MAX_DEADLINE() };

ストアド・ファンクションのコール

ストアド・ファンクションには戻り値があり、入力パラメータ、出力パラメータおよび入出力パラメータのリストを指定することもできます。ストアド・ファンクションのコールでは、VALUESトークンを使用します。VALUESトークンの後にファンクション・コールを記述します。標準のSQLJでは、ファンクション・コールをカッコで囲むことが必要です。Oracle SQLJ実装の場合、カッコの使用は任意です。カッコで囲む場合は、VALUESトークンと左カッコの間に空白があってもかまいません。VALUESトークンの構文は次のとおりです。

#sql result = { VALUES(FUNC(PARAM_LIST)) };

この構文でresult は結果式で、ファンクション戻り値を使用します。FUNC はストアド・ファンクション名で、必要に応じて入力パラメータ、出力パラメータおよび入出力パラメータの並びを取ることが可能です。FUNC には、スキーマ名またはパッケージ名も含めることも可能で、たとえば、SCOTT.MYFUNC()となります。

注意:
Oracle SQL実装でサポートされているINSERT INTO table VALUES構文でもVALUESトークンを使用できますが、意味的にも構文的にも関連がありません。

次に、「ストアド・プロシージャのコール」の例を再び使用します。ここでは、ストアド・プロシージャのかわりにストアド・ファンクションを定義します。

CREATE OR REPLACE FUNCTION GET_MAX_DEADLINE RETURN DATE IS
deadline DATE;
BEGIN
SELECT MAX(start_date + duration) INTO deadline FROM projects;
RETURN deadline;
END;

SQLJでは、このGET_MAX_DEADLINEファンクションを次のようにコールできます。

java.sql.Date maxDeadline;
...
#sql maxDeadline = { VALUES(GET_MAX_DEADLINE) };

結果式の型は、ファンクションの戻り値の型と同じであることが必要です。

Oracle SQLJ実装では、次のような構文を使用することも可能です。

#sql maxDeadline = { VALUES GET_MAX_DEADLINE };

カッコが省略されていることに注意してください。

ストアド・ファンクションのコールでは、ストアド・プロシージャの場合と同様に、ホスト式のトークンIN、OUTおよびINOUTを使用して、ストアド・ファンクションの入力先、出力先および入出力先のパラメータと対応させる必要があります。また、パラメータ・リストで使用するホスト変数の型を、ストアド・プロシージャのパラメータ型に対応させる必要もあります。

注意:
ストアド・ファンクションをOracle以外の環境にも移植可能にするには、コールで入力パラメータのみを使用し、出力または入出力パラメータは使用しないでください。

ストアド・ファンクションの戻り値としてのイテレータおよび結果セットの使用

SQLJでは、ファンクションの戻り値がREF CURSOR型の場合は、ストアド・ファンクションの戻り値をイテレータまたは結果セット変数に代入できます。

次の例では、イテレータを使用してストアド・ファンクションの戻り値を取得します。結果セットを使用する場合も同じです。

ストアド・ファンクションの戻り値としてのイテレータの例

この例では、ストアド・ファンクションの戻り型として、イテレータを使用します。この処理ではREF CURSOR型を使用します。

ファンクションが次のように定義されているとします。

CREATE OR REPLACE PACKAGE sqlj_refcursor AS
TYPE EMP_CURTYPE IS REF CURSOR;
FUNCTION job_listing (j varchar2) RETURN EMP_CURTYPE;
END sqlj_refcursor;

CREATE OR REPLACE PACKAGE BODY sqlj_refcursor AS
FUNCTION job_listing (j varchar) RETURN EMP_CURTYPE IS
DECLARE
rc EMP_CURTYPE;
BEGIN
OPEN rc FOR SELECT ename, empno FROM emp WHERE job = j;
RETURN rc;
END;
END sqlj_refcursor;

次のようにイテレータを宣言します。

#sql public <static> iterator EmpIter (String ename, int empno);

public修飾子は必須です。クラスレベルまたはネストされたクラスレベルでの宣言ではstatic修飾子も使用することをお薦めします。

イテレータおよびファンクションを使用するコードは次のようになります。

EmpIter iter;
...
#sql iter = { VALUES(sqlj_refcursor.job_listing('SALES')) };

while (iter.next())
{
String empname = iter.ename();
int empnum = iter.empno();

... process empname and empnum ...
}
iter.close();
...

この例では、job_listing()ファンクションのコールにより、役職がSALESであるすべての従業員の名前と従業員番号を含むイテレータが戻されます。その後、イテレータからこのデータが取り出されます。

5 型のサポート

この章では、Oracle SQLJ実装でサポートされているデータ型について説明し、サポートされているSQL型とそれに対応するJava型を示します。さらに、ストリームとOracle拡張型のサポートについても詳しく説明します。SQLJでサポートされるJava型とは、ホスト式で使用できる型のことです。

この章では、次の項目について説明します。

- ホスト式での型サポート

- ストリームのサポート

- JDBC 2.0 LOB型とOracle拡張型のサポート

関連項目:
第6章「オブジェクト、コレクションおよびOPAQUE型」

ホスト式での型サポート

ここでは、Oracle SQLJ実装でサポートされている型について概説します。具体的には、Java Database Connectivity(JDBC)2.0の型に関して新規にサポートされた点について説明します。

関連項目:
各Oracle SQL型ごとの正当なJavaマッピングに関するすべてのリストは、『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

注意:
SQLJでは、SQL型とJava型との変換が暗黙的に実行されるようになっています。この型変換は、一般的には便利ですが、予想と異なる結果を招く場合もあります。コードが正確かどうかの確認は、変換時の型チェックのみに頼らないでください。

ここでは、次の項目について説明します。

- サポートされている型の概要

- JDBC 2.0でサポートされている型と要件

- PL/SQLのBOOLEAN型、RECORD型およびTABLE型の使用

サポートされている型の概要

Oracle JDBCドライバを使用した場合にホスト式で使用できるJava型を、表5-1に示します。また、Java型、SQL型(oracle.jdbc.OracleTypesクラスに型コードが定義されている)およびOracle Database 11g のデータ型との相関関係もこの表からわかります。

注意:
OracleTypesクラスは、各Oracleデータ型の型コード(整数の定数)のみを定義します。標準JDBC型のOracleTypesの値は、標準java.sql.Typesの値と同じです。

Java変数に出力されるSQLデータは、該当するJava型に変換されます。SQLに入力されるJava変数は、該当するOracleデータ型に変換されます。

表5-1 ホスト式でサポートされている型の対応

Java型

Oracle型定義

Oracle SQLデータ型

標準JDBC 1.x型

boolean

BIT

NUMBER

byte

TINYINT

NUMBER

short

SMALLINT

NUMBER

int

INTEGER

NUMBER

long

BIGINT

NUMBER

float

REAL

NUMBER

double

FLOAT、DOUBLE

NUMBER

java.lang.String

CHARVARCHARLONGVARCHAR

CHARVARCHAR2LONG

byte[]

BINARYVARBINARYLONGVARBINARY

RAWRAWLONGRAW

java.sql.Date

DATE

DATE

java.sql.Time

TIME

DATE

java.sql.Timestamp

TIMESTAMPTIMESTAMP

DATETIMESTAMP

java.math.BigDecimal

NUMERICDECIMAL

NUMBERNUMBER

標準JDBC 2.0型

java.sql.Blob

BLOB

BLOB

java.sql.Clob

CLOB

CLOB

java.sql.Struct

STRUCT

オブジェクト型

java.sql.Ref

REF

参照型

java.sql.Array

ARRAY

コレクション型

java.sql.SQLDataを実装したカスタム・オブジェクト・クラス

STRUCT

オブジェクト型

Javaラッパー・クラス

java.lang.Boolean

BIT

NUMBER

java.lang.Byte

TINYINT

NUMBER

java.lang.Short

SMALLINT

NUMBER

java.lang.Integer

INTEGER

NUMBER

java.lang.Long

BIGINT

NUMBER

java.lang.Float

REAL

NUMBER

java.lang.Double

FLOAT、DOUBLE

NUMBER

SQLJストリーム・クラス

sqlj.runtime.BinaryStream

LONGVARBINARY

LONG RAW

sqlj.runtime.CharacterStream

LONGVARCHAR

LONG

sqlj.runtime.AsciiStream(非推奨。CharacterStreamを使用)

LONGVARCHAR

LONG

sqlj.runtime.UnicodeStream(非推奨。CharacterStreamを使用)

LONGVARCHAR

LONG

Oracle拡張型

oracle.sql.NUMBER

NUMBER

NUMBER

oracle.sql.CHAR

CHAR

CHAR

oracle.sql.RAW

RAW

RAW

oracle.sql.DATE

DATE

DATE

oracle.sql.TIMESTAMP

TIMESTAMP

TIMESTAMP

oracle.sql.TIMESTAMPTZ

TIMESTAMPTZ

TIMESTAMP-WITH- TIMEZONE

oracle.sql.TIMESTAMPLTZ

TIMESTAMPLTZ

TIMESTAMP-WITH- LOCAL-TIMEZONE

oracle.sql.ROWID

ROWID

ROWID

oracle.sql.BLOB

BLOB

BLOB

oracle.sql.CLOB

CLOB

CLOB

oracle.sql.BFILE

BFILE

BFILE

oracle.sql.STRUCT

STRUCT

オブジェクト型

oracle.sql.REF

REF

参照型

oracle.sql.ARRAY

ARRAY

コレクション型

oracle.sql.OPAQUE

OPAQUE

OPAQUE型

oracle.sql.ORADataを実装したカスタム・オブジェクト・クラス

STRUCT

オブジェクト型

oracle.sql.ORADataを実装したカスタム参照クラス

REF

参照型

oracle.sql.ORADataを実装したカスタム・コレクション・クラス

ARRAY

コレクション型

OPAQUE型のoracle.sql.ORADataを実装したカスタム・クラス(例: oracle.xdb.XMLType)

OPAQUE

OPAQUE型

oracle.sql.ORADataを実装したカスタムJavaクラス(任意のoracle.sql型をラッピングするクラス)

任意

任意

SQLJオブジェクトJava型(SQLDataまたはORADataを実装可能)

JAVA_STRUCT

SQLJオブジェクトSQL型(背後で使用されるJAVA_STRUCT。適切なJavaクラスに自動変換される)

Java型(PL/SQL型用)

スカラーの索引付き表で、Java数値配列またはString、oracle.sql.CHARまたはoracle.sql.NUMBERの配列表現

なし

なし

注意: PLSQL_INDEX_TABLE型がありますが、外部的には使用されません。

グローバリゼーション・サポート

oracle.sql.NCHAR

CHAR

CHAR

oracle.sql.NString

CHARVARCHARLONGVARCHAR

CHARVARCHAR2LONG

oracle.sql.NCLOB

CLOB

CLOB

oracle.sqlj.runtime.NcharCharacterStream

LONGVARCHAR

LONG

oracle.sqlj.runtime. NcharAsciiStream (非推奨。NcharCharacterStreamを使用)

LONGVARCHAR

LONG

oracle.sqlj.runtime. NcharUnicodeStream (非推奨。NcharCharacterStreamを使用)

LONGVARCHAR

LONG

問合せ結果オブジェクト

java.sql.ResultSet

CURSOR

CURSOR

SQLJイテレータ・オブジェクト

CURSOR

CURSOR

関連項目:
Oracle型のサポートの詳細は、『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

標準機能での型のサポートについては、次に要点を示します。

- Java char型とCharacter型は、JDBCおよびSQLJではサポートされていません。文字データを表現するときは、かわりにJavaのString型を使用してください。

- サポートされているjava.sql.Date型と、直接にはサポートされていないjava.util.Date型とを混同しないようにしてください。java.sql.Dateクラス(java.util.Dateのラッパー)を使用すると、JDBCの日付値に関して、SQLのDATEデータを識別したり、JDBCエスケープ構文をサポートする書式設定操作および解析操作を加えたりできるようになります。

- Oracle Database 11gでは、すべての数値型がNUMBERとして格納されます。表作成時にNUMBERを宣言すると、さらに詳細に精度を指定できますが、Oracle JDBCドライバを介してデータを取得する場合、データの受取りに使用するJava型によっては、この精度が失われることがあります。oracle.sql.NUMBERインスタンスであれば、すべての情報が保持されます。

- Javaのラッパー・クラス(IntegerやFloatなど)を使用すると、SQL文からNULLが戻された場合に役立ちます。基本型(intやfloatなど)には、NULL値を格納できないためです。

関連項目:
「NULLの処理」

- ストリームをホスト変数として使用するときは、SQLJストリーム・クラスが必要です。

関連項目:
「ストリームのサポート」

- 弱い型指定は、OUTパラメータまたはINOUTパラメータには使用できません。対応するOracle拡張型と同様に、これはStruct、RefおよびArrayの標準的なJDBC 2.0型に適用されます。

- 一連の新しいインタフェースは、oracle.jdbcパッケージにあり、oracle.jdbc.driverパッケージに代わり、Oracle9i JDBC実装で最初に追加されました。これらのインタフェースには、ユーザーがOracle JDBCドライバによってOracle固有機能を利用するためのより汎用的な方法が用意されています。特に、中間層のプログラムを作成する場合は、oracle.jdbc Application Program Interface(API)を使用してください。ただし、SQLJプログラマは通常これらのインタフェースを直接使用しません。これらのインタフェースは、SQLJランタイムまたはOracle固有生成コードで透過的に使用されます。

関連項目:
「カスタムJavaクラスのインタフェース指定」

- 結果セットおよびイテレータのホスト変数に対するSQLJのサポートの詳細は、「ホスト変数としてのイテレータおよび結果セットの使用」を参照してください。

次に、Oracleの拡張型について要点を示します。

- Oracle SQLJ実装でOracleTypesクラスに定義されている値に応じて静的_SQL_TYPECODEパラメータを設定するには、oracle.sql.ORADataを実装するクラスが必要です。場合によっては、これ以外にも、オブジェクト用の_SQL_NAMEやオブジェクト参照用の_SQL_BASETYPEなどのパラメータ設定が必要になることがあります。Oracle JPublisherユーティリティを使用すれば、必要なクラスを自動的に生成できます。

関連項目:
「ORADataを実装したクラスに対するOracleの要件」

- oracle.sqlクラスはSQLデータのラッパーであり、各Oracleデータ型に対応しています。ARRAY、STRUCT、REF、BLOBおよびCLOBクラスは、標準JDBC 2.0インタフェースに対応します。

関連項目:
これらのクラスとOracle拡張型の詳細は、『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

- カスタムJavaクラスでマッピングの対象となるのは、Oracleオブジェクト(ORADataまたはSQLDataを実装)、参照(ORADataのみを実装)、コレクション(ORADataのみを実装)、OPAQUE型(ORADataのみを実装)またはその他のカスタマイズ処理に使用するSQL型(ORADataのみを実装)です。Oracle JPublisherユーティリティを使用すれば、カスタムJavaクラスを自動的に生成できます。

関連項目:
「カスタムJavaクラス」および「JPublisherとカスタムJavaクラスの作成」

- Oracle SQLJ実装では、文字列をWHERE句のCHAR列値と比較するときに、自動的に空白埋めを考慮する機能があります。この機能がない場合は、データベース列の文字数と一致させるために文字列に対する埋込みが必要です。この機能は、Oracle固有コード生成ではSQLJトランスレータ・オプション、ISO標準コード生成ではOracleカスタマイザ・オプションとして使用できます。

関連項目:
「空白埋めを考慮したCHAR比較(-fixedchar)」および「Oracleカスタマイザによる空白埋めを考慮したCHAR比較(fixedchar)」

- 弱い型指定は、OUTパラメータまたはINOUTパラメータには使用できません。Oracle OPAQUE型と同様に、これはSTRUCT、REFおよびARRAYのOracle拡張型および対応する標準的なJDBC 2.0型に適用されます。

- 次に、Oracle拡張機能の使用に必要な項目を示します。

- Oracle JDBCドライバ

- 変換時のOracle固有コード生成またはOracleのカスタマイズ

- アプリケーション実行時のOracle SQLJランタイム

JDBC 2.0でサポートされている型と要件

表5-1に示したとおり、Oracle JDBCおよびSQLJの実装で標準java.sqlパッケージのJDBC 2.0型がサポートされています。ここでは、JDBC 2.0でサポートされている型および関連するOracleの拡張機能について説明します。

Oracle SQLJ実装でサポートされているJDBC 2.0型を、表5-2に示します。このJDBC 2.0型とそれに対応するOracle拡張型については、この表を参照してください。

Oracle拡張型は、以前のリリースから提供されていたもので、引き続き現行のリリースでも利用できます。これらのoracle.sql.*クラスでは、SQLのRAWデータをラップする機能が用意されています。

関連項目:
『Oracle Database JDBC開発者ガイドおよびリファレンス』

表5-2 Oracle拡張型とJDBC 2.0型との相関関係

JDBC 2.0型

Oracle拡張型

java.sql.Blob

oracle.sql.BLOB

java.sql.Clob

oracle.sql.CLOB

java.sql.Struct

oracle.sql.STRUCT

java.sql.Ref

oracle.sql.REF

java.sql.Array

oracle.sql.ARRAY

java.sql.SQLData

なし

なし

oracle.sql.ORAData (_SQL_TYPECODE = OracleTypes.STRUCT)

ORAData機能は、ユーザー定義型のJavaサポートの標準SQLData機能に対するOracle固有の代替機能です。

関連項目:
「カスタムJavaクラス」、「BLOB、CLOBおよびBFILEのサポート」および「弱い型指定のオブジェクト、参照およびコレクションのサポート」

次に示すJDBC 2.0型は、現在のOracle JDBCやSQLJの実装ではサポートされていません。

- JAVA_OBJECT: SQL列のJava型のインスタンスを表す型。

- DISTINCT: 基本SQL型と区別して表現や取出しが可能なSQL型。たとえば、SHOESIZE --> NUMBERなど。

注意:
Oracle Database 11g からは、Oracle SQLJ実装でイテレータ列に配列型を使用できるISO SQLJの機能がサポートされています。java.sql.Arrayまたはoracle.sql.ARRAY列を使用するイテレータを宣言できます。たとえば、次のデータベース表が定義されているとします。

CREATE OR REPLACE TYPE arr_type IS VARRAY(20) OF NUMBER;
CREATE TABLE arr_type (arr_col1 arr_type, arr_col2
arr_type);

次のように対応するイテレータ型を定義できます。

#sql static iterator MyIter (oracle.sql.ARRAY arr_col1,
java.sql.Array arr_col2);

PL/SQLのBOOLEAN型、RECORD型およびTABLE型の使用

Oracle SQLJおよびJDBCの実装では、コール用引数または戻り値として、PL/SQLのBOOLEAN型またはRECORD型をサポートしていません。

TABLE型のサポート

Oracle JDBCドライバでは、PL/SQLのスカラー索引付き表がサポートされています。

関連項目:
『Oracle Database JDBC開発者ガイドおよびリファレンス』

Oracle SQLJ実装によって、スカラー索引付き表でのデータのやりとりが簡素化されます。次の配列型がサポートされます。

- 数値型: int[]、long[]、float[]、double[]、short[]、java.math.BigDecimal[]、oracle.sql.NUMBER[]

- 文字型: java.lang.String[]、oracle.sql.CHAR[]

次に、索引付き表のデータをデータベースに書き込む例を示します。

int[] vals = {1,2,3};
#sql { call procin(:vals) };

次に、索引付き表のデータをデータベースから取り出す例を示します。

oracle.sql.CHAR[] outvals;
#sql { call procout(:OUT outvals/*[111](22)*/) };

このように/*...*/内の[xxx]構文を使用して、取得する出力配列の最大長を指定する必要があります。また、文字などのバインドの場合は、オプションで(xx)構文を指定し、例のように配列要素の最大長をバイト単位で指定できます。

注意:
oracle.sql.Datumクラスは、直接サポートされません。oracle.sql.CHARまたはoracle.sql.NUMBERなどの適切なサブクラスを使用する必要があります。

サポートされない型に対する次善策

サポートされない型の問題を回避するには、ラッパー・プロシージャを作成し、サポートされている型を使用してデータを処理します。たとえば、PL/SQLのブール値を使用するストアド・プロシージャをラッピングするには、JDBCから文字または数値を受け取って、これを元のプロシージャにBOOLEANとして渡すストアド・プロシージャを作成するか、出力パラメータの場合は元のプロシージャからBOOLEAN引数を受け取って、これをCHARまたはNUMBERとしてJDBCに渡すストアド・プロシージャを作成することができます。同様に、PL/SQLレコードを使用するストアド・プロシージャをラッピングするには、レコードをその個々のコンポーネント(CHARやNUMBERなど)で処理するストアド・プロシージャを作成できます。PL/SQLのTABLE型を使用するストアド・プロシージャをラッピングするには、データを複数のコンポーネントに分解するか、またはOracleのコレクション型を使用します。

次に、PL/SQLのラッパー・プロシージャMY_PROCの例を示します。このプロシージャは、入力としてBOOLEANをとるストアド・プロシージャPROCをラップします。

PROCEDURE MY_PROC (n NUMBER) IS
BEGIN
IF n=0
THEN proc(false);
ELSE proc(true);
END IF;
END;

PROCEDURE PROC (b BOOLEAN) IS
BEGIN
...
END;

注意:
PL/SQLパッケージまたはSQLオブジェクトで、メソッドとしてサポートされないPL/SQL型のシグネチャを使用する場合は、Oracle Database 11g JPublisherユーティリティを使用することを検討してください。このユーティリティによって、そのようなメソッドをコールするJava型の作成が容易になります。JPublisherの概要は、「JPublisherとカスタムJavaクラスの作成」、JPublisherの詳細は、『Oracle Database JPublisherユーザーズ・ガイド』を参照してください。

ストリームのサポート

標準SQLJには、ロング・データをストリームとして処理する次の2つの専用クラスがあります。

- sqlj.runtime.BinaryStream

- sqlj.runtime.CharacterStream

イテレータ列でデータベースからデータを取り出すとき、または入力ホスト変数を使用してデータをデータベースに送信するときに、これらのストリーム型を使用します。一般のJavaストリームと同じように、これらのクラスでは、大きなデータ項目を扱いやすい大きさの塊に分割して処理し、転送できます。

ここでは、これらのクラス、Oracle固有のSQLJ拡張機能およびストリーム・クラスのメソッドの一般的な使用方法について説明します。次の項目について説明します。

- SQLJストリームの一般的な使用方法

- ストリームをサポートするクラスの主な特長

- データ送信時のSQLJストリームの使用

- ストリームへのデータの取出し: 注意

- データ取得時のSQLJストリームの使用

- ストリーム・クラスのメソッド

- ストリーム・データの取出しおよび処理例

- 出力パラメータおよびファンクションの戻り値としてのSQLJストリーム・オブジェクト

注意:
JDBC 2.0では、AsciiStreamクラスおよびUnicodeStreamクラスは、CharacterStreamクラスに置換されています。CharacterStreamによって、ユーザーはエンコーディングに関する不要なロジスティクスから解放されます。

SQLJストリームの一般的な使用方法

通常、表5-1のデータ型をこれらのストリーム・クラスで処理します。つまり、

- BinaryStreamは通常、LONG RAW(Types.LONGVARBINARY)で使用されますが、RAW(Types.BINARYまたはTypes.VARBINARY)でも使用されます。

- CharacterStreamは通常、LONG(java.sql.Types.LONGVARCHAR)で使用されますが、VARCHAR2(Types.VARCHAR)でも使用されます。

ストリームの使用方法は自由です。ホスト変数にSQLJストリーム型を使用して、データの送信または取出しが実行できます。

表5-1に示したように、LONGデータとVARCHAR2データはJavaのStringでも使用可能であり、RAWデータとLONGRAWデータはJavaのbyte[]配列でも使用可能です。また、データベースでBLOBやCLOBなどのラージ・オブジェクト型がサポートされる場合は、これらを使用する方がLONGやLONG RAWなどの型よりも便利な場合もあります。ラージ・オブジェクトからのデータの抽出には、ストリームも使用できます。Oracle SQLJおよびJDBC実装では、ラージ・オブジェクト型がサポートされます。

関連項目:
「BLOB、CLOBおよびBFILEのサポート」

SQLJストリーム・クラスは両方ともに標準Javaクラスのサブクラス(BinaryStreamのjava.io.InputStreamおよびCharacterStreamのjava.io.Reader)で、SQLJに必要な機能を提供するラッパーとして動作します。つまり、基になるデータが適切に処理および変換されるように、データのデータ型とデータ長をSQLJに通知します。

ストリームをサポートするクラスの主な特長

次の略記されたコードは、BinaryStreamクラスの主な特長(拡張される内容、コンストラクタのシグネチャ、および主要メソッドのシグネチャなど)を示しています。

public class sqlj.runtime.BinaryStream extends sqlj.runtime.StreamWrapper
{   public sqlj.runtime.BinaryStream(java.io.InputStream);
public sqlj.runtime.BinaryStream(java.io.InputStream,int);
public java.io.InputStream getInputStream();
public int getLength();
public void setLength(int);
}

次の略記されたコードは、CharacterStreamクラスの主な特長を示しています。

public class sqlj.runtime.CharacterStream extends java.io.FilterReader
{   public sqlj.runtime.CharacterStream(java.io.Reader);
public sqlj.runtime.CharacterStream(java.io.Reader,int);
public int getLength();
public java.io.Reader getReader();
public void setLength(int);
}

注意:

- コンストラクタのintパラメータは、データ長をバイト数または文字数の適切な値で指定します。

- java.io.InputStreamオブジェクトを入力に使用するメソッドの場合は、かわりにBinaryStreamオブジェクトを使用できます。同様に、java.io.Readerオブジェクトを入力に使用するメソッドの場合は、かわりにCharacterStreamオブジェクトを使用できます。

- 現在推奨されていないAsciiStreamクラスおよびUnicodeStreamクラスにも、BinaryStreamと同じ主な特長とシグネチャがあります。

データ送信時のSQLJストリームの使用

標準SQLJでは、ストリームをホスト変数として使用して、データベースを更新できます。SQLJストリームをデータベースに送信するときは、データの長さを特定し、この長さをSQLJストリームのコンストラクタに対して指定する必要があります。

次の手順で、SQLJストリームを使用して、データをデータベースに送信します。

1. データの長さを特定します。

2. 入力として適切な標準Javaデータ・オブジェクトを作成します。BinaryStreamの場合は、入力ストリーム(java.io.InputStreamまたはいくつかのサブクラスのインスタンス)を作成します。CharacterStreamの場合は、Readerオブジェクト(java.io.Readerまたはいくつかのサブクラスのインスタンス)を作成します。

3. データ型に応じたSQLJストリーム・クラスのインスタンスを作成するには、データ・オブジェクトと長さをコンストラクタに渡します。

4. このSQLJのストリーム・インスタンスは、SQLJ実行文のSQL操作用のホスト変数として使用します。

5. ストリームを終了します。

注意:
ストリームを使用した後に終了することは必須ではありませんが、終了することをお薦めします。

ファイルからのLONGまたはLONG RAWの更新

ここでは、FileオブジェクトからCharacterStreamオブジェクトまたはBinaryStreamオブジェクトを作成し、そのオブジェクトをデータベースの更新に使用する方法を示します。この項の最後にあるコード例では、LONG列にCharacterStreamを使用しています。

データベース列をファイルから更新するときは、長さを特定する必要があります。この作業を行うには、入力ストリームを作成する前に、java.io.Fileオブジェクトを作成します。

次の手順で、ファイルからデータベースを更新します。

1. ファイルからjava.io.Fileオブジェクトを作成します。このためには、Fileクラスのコンストラクタへのファイル・パス名を指定してください。

2. Fileオブジェクトのlength()メソッドで、データの長さを特定します。このメソッドから戻される値はlong値なので、この値をSQLJストリーム・クラスのコンストラクタに入力するには、int値にキャストする必要があります。

注意:
このキャストを行う前に、long値がint変数に収まることを確認してください。クラスjava.lang.Integerの静的定数MAX_VALUEは、Javaの最大許容値intを示します。

3. 文字データの場合は、Fileオブジェクトからjava.io.FileReaderオブジェクトを作成します。このためには、FileオブジェクトをFileReaderコンストラクタに渡してください。
バイナリ・データの場合は、Fileオブジェクトからjava.io.FileInputStreamオブジェクトを作成します。このためには、FileオブジェクトをFileInputStreamコンストラクタに渡してください。

4. 該当するSQLJストリーム・オブジェクトを作成します。テキスト・ファイルの場合はCharacterStreamオブジェクト、バイナリ・ファイルの場合はBinaryStreamオブジェクトを作成します。FileReaderまたはFileInputStreamの該当するオブジェクトとデータ長(int値)をSQLJのストリーム・クラスのコンストラクタに渡します。

5. SQLJのストリーム・オブジェクトは、SQLJ実行文中でSQL操作用のホスト変数として使用します

次に、ファイルからデータベースにLONGデータを書き込む例を示します。ここでは、/private/mydir/myfile.htmlにあるHTMLファイルの内容をfiletableデータベース表のLONG列chardataに挿入します。

import java.io.*;
import sqlj.runtime.*;

...
File myfile = new File ("/private/mydir/myfile.html");
int length = (int)myfile.length();     // Must cast long output to int.
FileReader filereader = new FileReader(myfile);
CharacterStream charstream = new CharacterStream(filereader, length);
#sql { INSERT INTO filetable (chardata) VALUES (:charstream) };
charstream.close();
...

バイト配列からのLONG RAWの更新

ここでは、バイト配列からBinaryStreamオブジェクトを作成し、そのオブジェクトをデータベースの更新に使用する方法を示します。

バイト配列からデータベースを更新する場合は、あらかじめデータの長さを特定する必要があります。Javaの配列はすべて、データ長を戻す機能を備えているため、配列の方がファイルの場合より簡単です。

次の手順で、バイト配列からデータベースを更新します。

1. 配列のlength機能を使用して、データの長さを特定します。int値が戻されますが、この値はすべてのSQLJストリーム・クラスのコンストラクタで必要になります。

2. 配列からjava.io.ByteArrayInputStreamオブジェクトを作成します。このためには、バイト配列をByteArrayInputStreamコンストラクタに渡してください。

3. BinaryStreamオブジェクトを作成します。ByteArrayInputStreamオブジェクトとデータ長(int値)をBinaryStreamクラスのコンストラクタに渡してください。
コンストラクタのシグネチャは、次のように指定します。

BinaryStream (InputStream in, int length)

このシグネチャには、java.io.InputStreamクラスまたは任意のサブクラス(ByteArrayInputStreamなど)のインスタンスを指定してください。

4. SQLJのストリーム・オブジェクトは、SQLJ実行文中でSQL操作用のホスト変数として使用します

次に、バイト配列からLONG RAWデータをデータベースに書き込む例を示します。ここでは、バイト配列bytearray[]の内容をBINTABLEデータベース表にあるLONG RAW型の列BINDATAに挿入するとします。

import java.io.*;
import sqlj.runtime.*;

...
byte[] bytearray = new byte[100];

(Populate bytearray somehow.)
...
int length = bytearray.length;
ByteArrayInputStream arraystream = new ByteArrayInputStream(bytearray);
BinaryStream binstream = new BinaryStream(arraystream, length);
#sql { INSERT INTO bintable (bindata) VALUES (:binstream) };
binstream.close();
...

注意:
この例に示したように、ストリームは必ずしも必要ではありません。かわりに、バイト配列から直接データベースを更新することも可能です。

ストリームへのデータの取出し: 注意

データの取出しにSQLJストリーム・クラスも使用できますが、一部のデータベース製品に関しては、ストリーム使用時に注意事項があります。ロング・データの読取りおよびストリームへの書込みにOracle Database 11gとOracle JDBCドライバを使用する場合は、ストリーム・データへのアクセス方法およびデータの処理方法に注意する必要があります。

Oracle JDBCドライバはイテレータ行からデータにアクセスするため、通信パイプからストリーム項目をフラッシュした後で次のデータ項目にアクセスするようになっています。イテレータ行の処理時にストリーム・データがローカル・ストリームに書き込まれる場合でも、JDBCドライバが次のデータ項目にアクセスする前にローカル・ストリームからデータを読み取らないと、ストリーム・データが失われます。このようなストリーム処理は、ストリームの特性である大型化と長さが不明な点を考慮したものです。

したがって、Oracle JDBCドライバでストリーム項目にアクセスし、ローカル・ストリーム変数への書込みが完了した時点で、このローカル・ストリームの読取りと処理を行い、その後で、イテレータから別のアクセスを行う必要があります。

特に、位置イテレータの場合は必須のFETCH INTO構文があるため、注意が必要です。各回のフェッチでは、すべての列の読取りが完了した後で、処理が開始されます。したがって、ストリーム項目は1つのみ、つまり最後にアクセスした項目のみとなります。

次に、注意点をまとめます。

- 位置イテレータを使用する場合、使用できるのは1つのストリーム列のみで、最後の列である必要があります。イテレータの各行をフェッチしたらすぐに、ストリーム項目をプロセスのローカル入力ストリーム変数に書き込み、イテレータの次の行に進む前にそのローカル・ストリーム変数を読み取って処理する必要があります。

- 名前付きイテレータを使用すると、複数のストリーム列を操作できます。ただし、各イテレータ行を処理するときは、ストリーム・フィールドにアクセスするたびに、そのデータをプロセスのローカル・ストリーム変数に書き込み、ただちにローカル・ストリームを読み取って処理してから、イテレータの他のデータを読み取る必要があります。
また、名前付きイテレータの各行を処理するときは、イテレータ設定時の問合せでデータベース列を選択したときと同じ順番で、列のアクセッサ・メソッドをコールする必要があります。前述のように、問合せ後の通信パイプにストリーム・データが残っているためです。列へのアクセス順が異なると、ストリーム・データがスキップされ、他の列へのアクセス時に失われることがあります。

注意:

- Oracle Database 11g およびOracle JDBCドライバの場合は、SELECT INTO文でストリームを使用できません。

- デフォルトで、markメソッドおよびresetメソッドは、入力ストリームでサポートされていません。任意の入力ストリームをコンストラクタに渡すと、InputStreamクラスのresetメソッドがIOExceptionをスローします。このため、NcharAsciiStreamコンストラクタに渡す場合は常に、入力ストリームが適切な状態であることを確認します。たとえば、ストリームにデータが存在しない場合やストリームが終了している場合は、NcharAsciiStreamに渡す前にストリームをリセットします。

データ取得時のSQLJストリームの使用

データをストリームとして取り出すとき、標準SQLJでは、名前付きまたは位置イテレータのSQLJストリーム型列へのデータの読込みができます。

ここでは、位置イテレータまたは名前付きイテレータを使用してデータをSQLJストリームに取り出す基本的な手順を示します。前の項で述べた注意事項に留意してください。

関連項目:
「ストリーム・クラスのメソッド」および「ストリーム・データの取出しおよび処理例」

位置イテレータのSQLJストリーム列の使用方法

次の手順で、位置イテレータを使用して、データをSQLJストリームに取り出します。

1. 位置イテレータ・クラスを宣言します。最終列を該当するSQLJストリーム型として指定します。

2. イテレータ型のローカル変数を宣言します。

3. 該当するSQLJストリーム型のローカル変数を宣言します。これをホスト変数として、イテレータのSQLJストリーム列の各行からデータを取得します。

4. 問合せを実行して、手順2で宣言したイテレータにデータを設定します。

5. 通常どおり、イテレータを処理します。FETCH INTO文のINTOリスト内のホスト変数は、位置イテレータの列順に記述する必要があるので、ローカル入力ストリーム変数をリストの最後のホスト変数にします。

関連項目:
「位置イテレータの使用」

6. イテレータの処理ループでは、各イテレータ行にアクセスした時点でローカル入力ストリームの読取りと処理を行い、必要に応じてストリーム・データの格納や出力を行います。

7. イテレータ処理ループが一巡するたびに、ローカル入力ストリームを終了します。

8. イテレータを終了します。

名前付きイテレータのSQLJストリーム列の使用方法

次の手順で、名前付きイテレータを使用して、データを1つ以上のSQLJストリームに取り出します。

1. 該当するSQLJストリーム型の列を1つ以上指定して、名前付きイテレータ・クラスを宣言します。

2. イテレータ型のローカル変数を宣言します。

3. イテレータの各SQLJストリーム列に対して、入力ストリーム型またはリーダー型のローカル変数を宣言します。ストリーム列のアクセッサ・メソッドからデータを受け取るときに、この変数を使用します。これらのローカル・ストリーム変数は、SQLJのストリーム型にする必要はありません。標準のjava.io.InputStreamまたはjava.io.Readerの該当する型でもかまいません。

注意:
ローカル・ストリーム変数は、SQLJのストリーム型にする必要はありません。イテレータ列をSQLJのストリーム型にすると、データの型も正しく変換されます。

4. 問合せを実行して、手順2で宣言したイテレータにデータを設定します。

5. 通常どおり、イテレータを処理します。イテレータの各行の処理では、各ストリーム列のアクセッサ・メソッドがストリーム・データを戻すたびに、手順3で宣言したローカル入力ストリーム変数にデータが書き込まれます。
ストリーム・データの欠損を防ぐには、手順4の問合せで列を選択したときと同じ順番で、列のアクセッサ・メソッドをコールする必要があります。

関連項目:
「位置イテレータの使用」

6. イテレータの処理ループで、ストリーム列のアクセッサ・メソッドをコールし、データをローカル入力ストリーム変数に書き込んでから、ただちにローカル入力ストリームを読み取って処理し、ストリーム・データを格納または出力します。

7. イテレータ処理ループが一巡するたびに、ローカル入力ストリームを終了します。

8. イテレータを終了します。

注意:

- SQLJストリーム・オブジェクトにデータを移入した場合は、ストリームのデータ長属性は意味を持ちません。この属性が意味を持つのは、データ長を明示的に設定した場合、つまり各SQLJストリーム・クラスのsetLength()メソッドを使用したか、またはコンストラクタにデータ長を指定した場合です。

- 必須ではありませんが、イテレータ処理ループが一巡するたびにローカル入力ストリームを終了することをお薦めします。

ストリーム・クラスのメソッド

名前付きまたは位置イテレータのSQLJストリーム列を処理するときは、ストリーム・データを受け取るローカル・ストリーム変数をSQLJのストリーム型または標準のjava.io.InputStreamまたはjava.io.Readerのいずれか該当する型にできます。いずれの場合も、入力データ・オブジェクトの標準のメソッドを使用できます。

ローカル・ストリーム変数をSQLJのストリーム型、つまりBinaryStreamまたはCharacterStreamにすると、データをSQLJのストリーム・オブジェクトから直接読み取ることも、基になるInputStreamオブジェクトまたはReaderオブジェクトを取得し、このオブジェクトからデータを読み取ることも可能です。

注意:
どちらの方法をとるかは、好みの問題です。最初の方法の方が簡単です。ただし、2番目の方法は、データへのアクセスがより直接的で効率的です。

バイナリ・ストリームのメソッド

BinaryStreamクラスは、sqlj.runtime.StreamWrapperクラスのサブクラスです。StreamWrapperクラスには、次の主なメソッドがあります。

- InputStream getInputStream(): このメソッドを使用して、基になるjava.io.InputStreamオブジェクトを取得することもできます。SQLJのストリーム・オブジェクトは、このメソッドを使用せずに、直接処理できます。

- void setLength(int length): SQLJストリーム・オブジェクトのlength属性を設定できます。ストリーム・オブジェクトの作成時に設定したlengthの値をそのまま使用する場合は、このメソッドを使用する必要はありません。
SQLJストリームをデータベースに送信する場合は、あらかじめlength属性の値を設定する必要があります。

- int getLength(): SQLJストリームのlength属性の値を戻します。ストリーム・オブジェクトのコンストラクタまたはsetLength()メソッドで明示的にデータ長を設定すると、この属性値が有効になります。データをストリームに取り出すときは、length属性が自動的に設定されません。

sqlj.runtime.StreamWrapperクラスはjava.io.FilterInputStreamクラスのサブクラスであり、このjava.io.FilterInputStreamはjava.io.InputStreamクラスのサブクラスです。InputStreamクラスの次の主要メソッドは、SQLJのBinaryStreamクラスでもサポートされています。

- int read(): 入力ストリームから次のバイト・データを読み取ります。このバイト・データはint値(0から255)で戻されます。ストリームの終端に達した場合の戻り値は、-1です。次のいずれかの状態になるまで、このメソッドはプログラムを実行しません。

- 入力データが用意されたとき

- ストリームの終端に達したとき

- 例外がスローされたとき

- int read (byte b[]): 入力ストリームから最大b.lengthバイトのデータを読み取り、指定されたb[]バイト配列に書き込みます。戻り値として、読み取ったバイト数を示すint値が戻されますが、ストリームの終端に達した場合は-1が戻されます。入力が用意されるまで、このメソッドはプログラムをブロックします。

- int read (byte b[], int off, int len): 入力ストリームのオフセットoffで指定されたバイト位置から最大lenバイトのデータを読み取り、指定されたb[]バイト配列に書き込みます。戻り値として、読み取ったバイト数を示すint値が戻されますが、ストリームの終端に達した場合は-1が戻されます。入力が用意されるまで、このメソッドはブロックします。

- long skip (long n): 入力ストリームのnバイトのデータをスキップし、破棄します。実際にスキップするバイト数が、指定値より少ない場合もあります。実際にスキップしたバイト数は、long値で戻されます。

- void close(): ストリームを終了し、関連リソースを解放します。

文字ストリームのメソッド

CharacterStreamクラスには、次の主なメソッドがあります。

- Reader getReader(): このメソッドを使用して、基になるjava.io.Readerオブジェクトを取得することもできます。SQLJのストリーム・オブジェクトは、このメソッドを使用せずに、直接処理できます。

- void setLength(int length): このメソッドを使用して、ストリーム・オブジェクトの長さを設定できます。

- int getLength(): このメソッドを使用して、ストリーム・オブジェクトの長さを取得できます。

sqlj.runtime.CharacterStreamクラスはjava.io.FilterReaderクラスのサブクラスであり、このjava.io.FilterReaderはjava.io.Readerクラスのサブクラスです。Readerクラスの次の主要メソッドは、SQLJのCharacterStreamクラスでもサポートされています。

- int read(): リーダーから次の文字データを読み取ります。このデータはint値(0から65535)で戻されます。データの終端に達した場合の戻り値は、-1です。次のいずれかの状態になるまで、このメソッドはプログラムを実行しません。

- 入力データが用意されたとき

- データの終端に達したとき

- 例外がスローされたとき

- int read (char cbuf[]): 文字を配列に読み取り、データを指定されたcbuf[] char配列に書き込みます。戻り値として、読み取った文字数を示すint値が戻されますが、データの終端に達した場合は-1が戻されます。入力が用意されるまで、このメソッドはプログラムをブロックします。

- int read (char cbuf[], int off, int len): 入力のオフセットoffで指定された文字位置から最大len文字数のデータを読み取り、指定されたchar[] 文字配列に書き込みます。戻り値として、読み取った文字数を示すint値が戻されますが、データの終端に達した場合は-1が戻されます。入力が用意されるまで、このメソッドはブロックします。

- long skip (long n): 入力のn文字のデータをスキップし、破棄します。実際にスキップする文字数が、指定値より少ない場合もあります。実際にスキップした文字数は、long値で戻されます。

- void close(): ストリームを終了し、関連リソースを解放します。

ストリーム・データの取出しおよび処理例

ここでは、ストリーム・データを取り出す例を示します。

- 例5-1では、SELECT文でLONG列からデータを選択し、名前付きイテレータのSQLJ CharacterStream列に設定します。

- 例5-2では、SELECT文でLONG RAW列からデータを選択し、位置イテレータのSQLJ BinaryStream列に設定します。

例5-1: 名前付きイテレータのCharacterStream列へのLONGデータの格納

この例では、データベースのLONG列からデータを選択し、名前付きイテレータのSQLJ CharacterStream列に格納します。

表FILETABLEのVARCHAR2型の列FILENAMEにファイル名が格納されており、LONG型の列FILECONTENTSにファイルの内容が文字形式で格納されているものとします。このコードを次に示します。

import sqlj.runtime.*;
import java.io.*;
...
#sql iterator MyNamedIter (String filename, CharacterStream filecontents);

...
MyNamedIter namediter = null;
String fname;
CharacterStream charstream;
#sql namediter = { SELECT filename, filecontents FROM filetable };
while (namediter.next()) {
fname = namediter.filename();
charstream = namediter.filecontents();
System.out.println("Contents for file " + fname + ":");
printStream(charstream);
charstream.close();
}

namediter.close();
...
public void printStream(Reader in) throws IOException
{
int character;
while ((character = in.read()) != -1) {
System.out.print((char)character);
}
}

すでに述べたように、入力パラメータとして標準java.io.Readerをとるメソッドには、SQLJ文字ストリームを渡すことが可能です。

例5-2: 位置イテレータのBinaryStream列へのLONG RAWの格納

この例では、LONG RAW列からデータを選択し、位置イテレータのSQLJ BinaryStream列に移入します。

前の項で説明したように、位置イテレータには1つの入力ストリームのみ可能で、必ず最終列の必要があります。表BINTABLEにはNUMBER型の列IDENTIFIERとLONG RAW型の列BINDATAがあり、識別子に該当するバイナリ・データがBINDATA列に格納されているものとします。このコードを次に示します。

import sqlj.runtime.*;
...
#sql iterator MyPosIter (int, BinaryStream);

...
MyPosIter positer = null;
int id=0;
BinaryStream binstream=null;
#sql positer = { SELECT identifier, bindata FROM bintable };
while (true) {
#sql { FETCH :positer INTO :id, :binstream };
if (positer.endFetch()) break;

(...process data as desired...)

binstream.close();
}
positer.close();
...

出力パラメータおよびファンクションの戻り値としてのSQLJストリーム・オブジェクト

前述のように、標準SQLJでは、sqlj.runtimeパッケージのBinaryStreamおよびCharacterStreamクラスを使用して、ストリーム・データを取り出し、イテレータ列に格納できます。

また、Oracle SQLJ実装では、Oracle9i 以上のデータベース、Oracle JDBCドライバ、Oracle固有コード生成またはOracleカスタマイザ、およびOracle SQLJランタイムを使用すると、SQLJのストリーム型を次のように使用できます。

- ストアド・プロシージャまたはストアド・ファンクションのコールからのOUTまたはINOUTホスト変数として

- ストアド・ファンクションのコールの戻り値として

ストアド・プロシージャの出力パラメータとしてのストリーム

BinaryStreamおよびCharacterStream型は、ストアド・プロシージャまたはストアド・ファンクションのOUTまたはINOUTパラメータの代入型として使用できます。

次の表定義を想定します。

CREATE TABLE streamexample (name VARCHAR2 (256), data LONG);
INSERT INTO streamexample (data, name)
VALUES
('0000000000111111111112222222222333333333344444444445555555555',
'StreamExample');

また、次のストアド・プロシージャ定義を想定します。この定義には、STREAMEXAMPLE表が使用されています。

CREATE OR REPLACE PROCEDURE out_longdata
(dataname VARCHAR2, longdata OUT LONG) IS
BEGIN
SELECT data INTO longdata FROM streamexample WHERE name = dataname;
END out_longdata;

次のサンプル・コードでは、out_longdataストアド・プロシージャをコールして、ロング・データを読み取ります。

import sqlj.runtime.*;

...
CharacterStream data;
#sql { CALL out_longdata('StreamExample', :OUT data) };
int c;
while ((c = data.read ()) != -1)
System.out.print((char)c);
System.out.flush();
data.close();
...

注意:
ストリームを必ずしも終了する必要はありませんが、終了することをお薦めします。

ストアド・ファンクションの結果としてのストリーム

BinaryStream型およびCharacterStream型は、ストアド・ファンクションの戻り値の代入型として使用できます。

前述のストアド・プロシージャの例と同じSTREAMEXAMPLE表定義を想定します。また、次のストアド・ファンクション定義を想定し、STREAMEXAMPLE表を使用します。

CREATE OR REPLACE FUNCTION get_longdata (dataname VARCHAR2) RETURN long
IS longdata LONG;
BEGIN
SELECT data INTO longdata FROM streamexample WHERE name = dataname;
RETURN longdata;
END get_longdata;

次のサンプル・コードでは、get_longdataストアド・ファンクションをコールして、ロング・データを読み取ります。

import sqlj.runtime.*;

...
CharacterStream data;
#sql data = { VALUES(get_longdata('StreamExample')) };
int c;
while ((c = data.read ()) != -1)
System.out.print((char)c);
System.out.flush();
data.close();
...

注意:
ストリームを必ずしも終了する必要はありませんが、終了することをお薦めします。

JDBC 2.0 LOB型とOracle拡張型のサポート

Oracle SQLJ実装では、次に示したようにJDBC 2.0のデータ型とOracle固有のデータ型に対して拡張機能が用意されています。

- JDBC 2.0ラージ・オブジェクト(LOB)型(BLOBおよびCLOB)

- Oracle BFILE型

- Oracle ROWID型

- Oracle REF CURSOR型

- その他のOracle Database 11g データ型(NUMBERやRAWなど)

ここであげたデータ型は、oracle.sqlパッケージ中のクラスでサポートされています。LOBとバイナリ・ファイル(BFILE)は多くの点で同様に処理されるため、まとめて説明します。Oracle SQLJ実装では、標準BigDecimal JDBC型に対するサポートも強化されています。

ユーザー定義のSQLオブジェクト、オブジェクト参照およびコレクションについては、JDBC 2.0機能もサポートされています。

関連項目:
第6章「オブジェクト、コレクションおよびOPAQUE型」

コード中にOracle拡張型を使用する場合は、次の要件が伴うので注意してください。

- Oracle JDBCドライバを使用する必要があります。

- Oracle固有コード生成を使用するか、またはISOコード生成の場合は必要に応じてプロファイルをカスタマイズします。カスタマイザはデフォルトのカスタマイザoracle.sqlj.runtime.util.OraCustomizerをお薦めします。

- アプリケーションの実行時にOracle SQLJランタイムを使用します。

Oracle SQLJランタイムとOracle JDBCドライバは、Oracle拡張型をコード中に使用しない場合であっても、Oracleカスタマイザを使用する場合は常に必要です。

Oracle固有のセマンティクス・チェックを行うには、適切なチェッカを使用する必要があります。デフォルトのチェッカoracle.sqlj.checker.OracleCheckerは、フロントエンドとして機能し、環境に応じたチェッカを起動します。JDBCドライバを使用すると、Oracle固有のチェッカが起動されます。

ここでは、次の項目について説明します。

- パッケージoracle.sql

- BLOB、CLOBおよびBFILEのサポート

- Oracle ROWIDのサポート

- OracleのREF CURSOR型のサポート

- その他のOracle Database 11g データ型のサポート

- BigDecimalのサポート強化

パッケージoracle.sql

oracle.sqlパッケージは、SQLJユーザーにもJDBCユーザーにも重要であり、このパッケージ内のクラスによって、Oracle Database 11gのすべてのデータ型(oracle.sql.ROWID、oracle.sql.CLOB、oracle.sql.NUMBERなど)がサポートされます。oracle.sqlクラスは、SQLのrawデータ用のラッパーであり、Java形式への適切なマッピングと変換メソッドを提供します。oracle.sql.*オブジェクトは、対応するSQLデータのバイナリ表現をバイト配列の形式で保持しています。各oracle.sql.*データ型クラスは、oracle.sql.Datumクラスのサブクラスです。

Oracle固有のセマンティクス・チェックを行うには、適切なチェッカを使用する必要があります。デフォルトのチェッカoracle.sqlj.checker.OracleCheckerは、フロントエンドとして機能し、環境に応じたチェッカを起動します。JDBCドライバを使用すると、Oracle固有のチェッカが起動されます。

関連項目:

- 「接続オプション」

- 「セマンティクス・チェックとオフライン解析のオプション」

- 『Oracle Database JDBC開発者ガイドおよびリファレンス』

BLOB、CLOBおよびBFILEのサポート

Oracle SQLJおよびJDBC実装では、JDBC 2.0 LOB型がサポートされており、このサポート内容はOracle固有のBFILE型(データベースの外部に格納されている読取り専用バイナリ・ファイル)と似ています。これらのデータ型は、次のクラスでサポートされています。

- oracle.sql.BLOB

- oracle.sql.CLOB

- oracle.sql.BFILE

これらのクラスは、Oracle固有のSQLJアプリケーションで次のように使用できます。

- SQLJ実行文およびINTOリスト中のIN、OUTまたはINOUTホスト変数として

- ストアド・ファンクション・コールの戻り値として

- イテレータ宣言での列型として

関連項目:
LOBとBFILEの詳細およびサポートされているストリームAPIの使用方法は、『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

LOBの操作には、BLOBおよびCLOBクラスで定義したメソッドを使用するか(推奨)、DBMS_LOB PL/SQLパッケージで定義したプロシージャおよびファンクションを使用できます。このパッケージで定義されているプロシージャとファンクションはすべて、SQLJプログラムからコールできます。

BFILEの操作には、BFILEクラスで定義したメソッドを使用することをお薦めします。DBMS_LOBパッケージのファイル処理ルーチンも使用できます。

Javaアプリケーションでは、BLOB、CLOBおよびBFILEクラスのメソッドの方がDBMS_LOBパッケージより便利です。実行時間が短縮される場合もあります。

読取りまたは書込み対象のチャンクの型は、操作対象のLOBの種類によって異なります。たとえば、キャラクタ・ラージ・オブジェクト(CLOB)の内容は文字データであるため、データ・チャンクをJava文字列で保持します。バイナリ・ラージ・オブジェクト(BLOB)の内容はバイナリ・データであるため、チャンク・データをJavaバイト配列で保持します。

注意:
DBMS_LOBパッケージでは、サーバーへのラウンドトリップが必要になります。BLOB、CLOBおよびBFILEクラスのメソッドも、サーバーへのラウンドトリップが必要になることがあります。

BFILEでBFILEクラスを使用した場合とDBMS_LOB機能を使用した場合の比較

例5-3および例5-4では、BFILEでoracle.sqlのメソッドを使用した場合とDBMS_LOBパッケージを使用した場合を比較します。

例5-3: BFILEでのoracle.sql.BFILEファイル処理メソッドの使用

この例では、oracle.sql.BFILEクラスのファイル処理メソッドでBFILEを操作します。

BFILE openFile (BFILE file) throws SQLException
{
String dirAlias, name;
dirAlias = file.getDirAlias();
name = file.getName();
System.out.println("name: " + dirAlias + "/" + name);

if (!file.isFileOpen())
{
file.openFile();
}
return file;
}

BFILEのgetDirAlias()およびgetName()メソッドは、フルパスとファイル名を取得するためのメソッドです。openFile()メソッドは、ファイルをオープンするためのメソッドです。操作するBFILEは、あらかじめオープンしておく必要があります。

例5-4: BFILEでのDBMS_LOBファイル処理ルーチンの使用

この例では、DBMS_LOBパッケージのファイル処理ルーチンを使用してBFILEを操作します。

BFILE openFile(BFILE file) throws SQLException
{
String dirAlias, name;
#sql { CALL dbms_lob.filegetname(:file, :out dirAlias, :out name) };
System.out.println("name: " + dirAlias + "/" + name);

boolean isOpen;
#sql isOpen = { VALUES(dbms_lob.fileisopen(:file)) };
if (!isOpen)
{
#sql { CALL dbms_lob.fileopen(:inout file) };
}
return file;
}

openFile()メソッドは、ファイル・オブジェクトの名前を出力し、その後で、そのファイルのオープンしているバージョンを戻すためのメソッドです。BFILEを操作するには、あらかじめDBMS_LOB.FILEOPENまたはBFILEクラスの該当メソッドをコールし、ファイルをオープンにしておく必要があります。

LOBでBLOBおよびCLOBクラスを使用した場合とDBMS_LOB機能を使用した場合の比較

例5-5および例5-6では、BLOBでoracle.sqlメソッドを使用した場合とDBMS_LOBパッケージを使用した場合を比較します。例5-7および例5-8では、CLOBでoracle.sqlメソッドを使用した場合とDBMS_LOBパッケージを使用した場合を比較します。

例5-5: CLOBに対するoracle.sql.CLOB読取りメソッドの使用

oracle.sql.CLOBクラスのメソッドを使用して、CLOBからデータを読み取ります。

void readFromClob(CLOB clob) throws SQLException
{
long clobLen, readLen;
String chunk;

clobLen = clob.length();

for (long i = 0; i < clobLen; i+= readLen) {
chunk = clob.getSubString(i, 10);
readLen = chunk.length();
System.out.println("read " + readLen + " chars: " + chunk);
}
}

このメソッドには、CLOBからJava文字列を10文字ずつ読み取って戻すループがあります。CLOB全体を読み取るまで、ループが繰り返されます。

例5-6: CLOBでのDBMS_LOB読取りルーチンの使用

DBMS_LOBパッケージのルーチンを使用してCLOBからの読取りを行います。

void readFromClob(CLOB clob) throws SQLException
{
long clobLen, readLen;
String chunk;

#sql clobLen = { VALUES(dbms_lob.getlength(:clob)) };

for (long i = 1; i <= clobLen; i += readLen) {
readLen = 10;
#sql { CALL dbms_lob.read(:clob, :inout readLen, :i, :out chunk) };
System.out.println("read " + readLen + " chars: " + chunk);
}
}

このメソッドはCLOBの内容を10文字ずつ読み取ります。チャンクのホスト変数の型は、Stringです。

例5-7: BLOBでのoracle.sql.BLOB書込みルーチンの使用

oracle.sql.BLOBクラスのメソッドを使用して、BLOBへデータを書き込みます。BLOBと指定の長さを入力します。

void writeToBlob(BLOB blob, long blobLen) throws SQLException
{
byte[] chunk = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
long chunkLen = (long)chunk.length;

for (long i = 0; i < blobLen; i+= chunkLen) {
if (blobLen < chunkLen) chunkLen = blobLen;
chunk[0] = (byte)(i+1);
chunkLen = blob.putBytes(i, chunk);
}
}

指定されたBLOB長に達するまで、このメソッドはBLOBに10バイトずつ書き込むループを繰り返します。

例5-8: BLOBでのDBMS_LOB書込みルーチンの使用

この例では、DBMS_LOBパッケージのルーチンを使用してBLOBへの書込みを行います。

void writeToBlob(BLOB blob, long blobLen) throws SQLException
{
byte[] chunk = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
long chunkLen = (long)chunk.length;

for (long i = 1; i <= blobLen; i += chunkLen) {
if ((blobLen - i + 1) < chunkLen) chunkLen = blobLen - i + 1;
chunk[0] = (byte)i;
#sql { CALL dbms_lob.write(:INOUT blob, :chunkLen, :i, :chunk) };
}
}

このメソッドは、BLOBに10バイトずつ書き込みます。チャンクのホスト変数はbyte[]型です。

LOBおよびBFILE型でのストアド・ファンクションの結果

BLOB、CLOBおよびBFILE型のホスト変数は、ストアド・ファンクション・コールの結果に代入できます。次に示した例は、CLOBを対象としていますが、BLOBおよびBFILEのコードにも同じ機能があります。

最初に、次のファンクション定義を想定します。

CREATE OR REPLACE FUNCTION longer_clob (c1 CLOB, c2 CLOB) RETURN CLOB IS
result CLOB;
BEGIN
IF dbms_lob.getLength(c2) > dbms_lob.getLength(c1) THEN
result := c2;
ELSE
result := c1;
END IF;
RETURN result;
END longer_clob;

次の例では、longer_clobファンクションからの戻り値の代入型としてCLOBを使用します。

void readFromLongest(CLOB c1, CLOB c2) throws SQLException
{
CLOB longest;
#sql longest = { VALUES(longer_clob(:c1, :c2)) };
readFromClob(longest);
}

readFromLongest()メソッドは、前に定義したreadFromClob()メソッドを使用して、渡されたCLOBの長い方の内容を出力します。

LOBおよびBFILEホスト変数とSELECT INTOターゲット

BLOB、CLOBおよびBFILE型のホスト変数は、SELECT INTO実行文のINTOリストに記述できます。次に示した例は、BLOBとCLOBを対象としていますが、BFILEのコードにも同じ機能があります

次の表定義を想定します。

CREATE TABLE basic_lob_table(x VARCHAR2(30), b BLOB, c CLOB);
INSERT INTO basic_lob_table
VALUES('one', '010101010101010101010101010101', 'onetwothreefour');
INSERT INTO basic_lob_table
VALUES('two', '020202020202020202020202020202', 'twothreefourfivesix');

次の例では、BLOBとCLOBをホスト変数として使用し、定義した表のデータをSELECT INTO文を使用して受け取ります。

...
BLOB blob;
CLOB clob;
#sql { SELECT one.b, two.c INTO :blob, :clob
FROM basic_lob_table one, basic_lob_table two
WHERE one.x='one' AND two.x='two' };
#sql { INSERT INTO basic_lob_table VALUES('three', :blob, :clob) };
...

この例では、BASIC_LOB_TABLEの先頭行からBLOBを取り出し、2番目の行からCLOBを取り出します。その後で、前の操作で選択したBLOBとCLOBを使用して、3番目の行を表に挿入します。

LOBとBFILEを使用したイテレータの宣言

BLOB、CLOBおよびBFILE型は、SQLJの位置および名前付きイテレータの列型として使用できます。これらのイテレータには、該当する実行可能なSQLJ操作の結果を格納できます。

次に、宣言の例を示します。

#sql iterator NamedLOBIter(CLOB c);
#sql iterator PositionedLOBIter(BLOB);
#sql iterator NamedFILEIter(BFILE bf);

LOBおよびBFILE型ホスト変数と名前付きイテレータの結果

次の例では、前の例で定義したreadFromLongest()メソッドとBASIC_LOB_TABLE表を使用し、名前付きイテレータでCLOBを使用します。BLOBおよびBFILEのコードも、同様の記述になります。

#sql iterator NamedLOBIter(CLOB c);

...
NamedLOBIter iter;
#sql iter = { SELECT c FROM basic_lob_table };
if (iter.next())
CLOB c1 = iter.c();
if (iter.next())
CLOB c2 = iter.c();
iter.close();
readFromLongest(c1, c2);
...

この例では、イテレータを使用して、BASIC_LOB_TABLEの最初の2行からCLOBを2つ選択します。次にreadFromLongest()メソッドを使用して、2つのうちの大きい方を出力します。

LOBおよびBFILE型ホスト変数と、位置イテレータのFETCH INTOターゲット

BLOB、CLOBおよびBFILE型のホスト変数は、位置イテレータで使用できます。イテレータの該当列の属性が同じ型の場合は、対応付けられているFETCH INTO文のINTOリストに、これらのホスト変数を記述できます。

次の例では、前の例で定義したwriteToBlob()メソッドとBASIC_LOB_TABLE表を使用します。CLOBおよびBFILEのコードも、同様の記述になります。

#sql iterator PositionedLOBIter(BLOB);

...
PositionedLOBIter iter;
BLOB blob = null;
#sql iter = { SELECT b FROM basic_lob_table };
for (long rowNum = 1; ; rowNum++)
{
#sql { FETCH :iter INTO :blob };
if (iter.endFetch()) break;
writeToBlob(blob, 512*rowNum);
}
iter.close();
...

この例では、BASIC_LOB_TABLE内の各BLOBに対して、writeToBlob()をコールします。各行から、512バイトずつデータが書き込まれます。

Oracle ROWIDのサポート

Oracle固有のROWID型は、データベース表の各行の一意のアドレスを格納するための型です。oracle.sql.ROWIDクラスはROWID情報をラッピングするもので、ROWID型の変数をバインドおよび定義するために使用します。

oracle.sql.ROWID型の変数は、Oracle Database 11g に接続するSQLJアプリケーションで次のように使用できます。

- SQLJ実行文およびINTOリスト中のIN、OUTまたはINOUTホスト変数として

- ストアド・ファンクション・コールの戻り値として

- イテレータ宣言での列型として

ROWIDを使用したイテレータ宣言

oracle.sql.ROWID型は、次の宣言のように、SQLJの位置および名前付きイテレータの列型として使用できます。

#sql iterator NamedRowidIter (String ename, ROWID rowid);

#sql iterator PositionedRowidIter (String, ROWID);

ROWIDホスト変数と名前付きイテレータのSELECT結果

ROWIDオブジェクトは、SQLJ実行文でIN、OUTおよびINOUTパラメータとして使用できます。また、イテレータのROWID型の列を設定できます。次のコード例では、前の例で示した宣言を使用します。

#sql iterator NamedRowidIter (String ename, ROWID rowid);

...
NamedRowidIter iter;
ROWID rowid;
#sql iter = { SELECT ename, rowid FROM emp };
while (iter.next())
{
if (iter.ename().equals("CHUCK TURNER"))
{
rowid = iter.rowid();
#sql { UPDATE emp SET sal = sal + 500 WHERE rowid = :rowid };
}
}
iter.close();
...

この例では、ROWIDに基づき、従業員Chuck Turnerの給与が$500増えます。

ストアド・ファンクションの結果としてのROWID

次のファンクションについて考えてみます。

CREATE OR REPLACE FUNCTION get_rowid (name VARCHAR2) RETURN ROWID IS
rid ROWID;
BEGIN
SELECT rowid INTO rid FROM emp WHERE ename = name;
RETURN rid;
END get_rowid;

このストアド・ファンクションの場合は、このファンクションの戻り値の代入型として、ROWIDオブジェクトが次のように使用されます。

ROWID rowid;
#sql rowid = { values(get_rowid('AMY FEINER')) };
#sql { UPDATE emp SET sal = sal + 500 WHERE rowid = :rowid };

この例では、ROWIDに従って、従業員Amy Feinerの給与が$500増えます。

SELECT INTOのターゲットとしてのROWID

ROWID型のホスト変数は、SELECT INTO文のINTOリストに記述できます。

ROWID rowid;
#sql { SELECT rowid INTO :rowid FROM emp WHERE ename='CHUCK TURNER' };
#sql { UPDATE emp SET sal = sal + 500 WHERE rowid = :rowid };

この例では、ROWIDに基づき、従業員Chuck Turnerの給与が$500増えます。

ROWIDホスト変数と位置イテレータのFETCH INTOターゲット

ROWID型のホスト変数は、FETCH INTO文のINTOリストに記述できます(イテレータ内の該当列の属性が同じ型の場合)。

#sql iterator PositionedRowidIter (String, ROWID);

...
PositionedRowidIter iter;
ROWID rowid = null;
String ename = null;
#sql iter = { SELECT ename, rowid FROM emp };
while (true)
{
#sql { FETCH :iter INTO :ename, :rowid };
if (iter.endFetch()) break;
if (ename.equals("CHUCK TURNER"))
{
#sql { UPDATE emp SET sal = sal + 500 WHERE rowid = :rowid };
}
}
iter.close();
...

この例は、前述の名前付きイテレータの例に似ていますが、位置イテレータの必須FETCH INTO構文を使用します。

位置指定更新および位置指定削除

Oracle Database 11g リリース1(11.1)以上では、SQLJで位置指定更新および位置指定削除の操作がサポートされています。位置指定更新または位置指定削除の操作は、イテレータを使用して実行できます。位置指定更新または位置指定削除に使用されるイテレータは、sqlj.runtime.ForUpdateインタフェースを実装している必要があります。名前付きイテレータ、位置イテレータまたはスクロール可能なイテレータを使用できます。

次のコードは、位置指定更新を示しています。

...
#sql iterator iter implements sqlj.runtime.ForUpdate(String str)
...
#sql iter = {SELECT ename FROM emp WHERE dpetno=10};
...
while(iter.next())
{
#sql {UPDATE emp SET sal=sal+5000 WHERE CURRENT OF :iter};
}
...

前述のコードでは、イテレータiterが作成され、emp表を更新する際に使用されます。

同様に位置指定削除を実行できます。次に例を示します。

...
#sql {DELETE FROM emp WHERE CURRENT OF :iter}
...

前述の例で、iterは、位置指定削除を実行する際に使用されるイテレータです。

WHERE CURRENT OF句で使用可能なイテレータには、次の制限事項があります。

- イテレータへの移入に使用される問合せは、複数の表に対して実行しないでください。

- イテレータでREF CURSORを戻すPL/SQLプロシージャは使用できません。

- 結果セットから移入されているイテレータは使用できません。つまり、次の文を使用して移入されたイテレータです。ここでrsは結果セットです。

#sql iter = {cast :rs}

for_updateオプション

変換時にfor_updateオプションを設定すると、SELECT文にFOR UPDATEが追加されます。次に、SELECT文はForUpdateイテレータに結果を次のように戻します。

% sqlj –for_update abc.sqlj

/* abc.sqlj */
#sql iterator  SalByName (double sal, String ename)  implements sqlj.runtime.ForUpdate;

public class abc {
…..
void func1()
{
SalByName salbn;
#sql salbn = {select sal, ename from emp };
}
…..
}

ここで、SELECT文にFOR UPDATEが追加され、次のようにForUpdateイテレータsalbnが戻されます。

………
String theSqlTS = “SELECT rowid sjT_rowid,ename, sal FROM emp WHERE ename =  :1 FOR UPDATE";
………

表5-3に、for_updateオプションに使用可能な値と前述の例の対応するSQL文を示しています。

表5-3 for_updateオプションの値と対応するSQL文

for_updateオプション

SQLJ文

SQL文

なし

sqlj -for_update abc.sqlj

SELECT rowid sjT_rowid,ename, sal FROM emp WHERE ename = :1 FOR UPDATE

nowait

sqlj -P-for_update=nowait QueryDemo.sqlj

SELECT rowid sjT_rowid,ename, sal FROM emp WHERE ename = :1 FOR UPDATE nowait

number

sqlj -P-for_update=10 QueryDemo.sqlj

SELECT rowid sjT_rowid,ename, sal FROM emp WHERE ename = :1 FOR UPDATE wait 10

注意:
アプリケーションの選択問合せにFOR UPDATEが含まれる場合、新しい変換オプションを使用すると、変換時のオンライン・チェック中に警告がスローされます。変換中にオフライン解析を選択すると、変換時にエラーは検出されません。

OracleのREF CURSOR型のサポート

Oracle PL/SQLとOracle SQLJ実装では、データベースのカーソルを表すカーソル変数を使用できます。

REF CURSOR型の概要

カーソル変数は、機能的にはJDBCの結果セットに相当し、問合せ結果をカプセル化します。カーソル変数はREF CURSORとも呼ばれますが、REF CURSOR自体は型指定子であって、型名ではありません。指定子でなく、名前付きREF CURSOR型を指定する必要があります。次に、REF CURSORの型指定の例を示します。

TYPE EmpCurType IS REF CURSOR;

OracleのREF CURSOR型のパラメータは、ストアド・プロシージャとストアド・ファンクションで戻されます。REF CURSORパラメータを戻すには、PL/SQLを使用する必要があります。SQLのみを使用した場合は戻りません。PL/SQLのストアド・プロシージャやストアド・ファンクションでは、任意の名前付きREF CURSOR型の変数を宣言したり、SELECT文を実行したり、REF CURSOR変数に戻り値としての結果を代入したりできます。

関連項目:
『Oracle Database PL/SQL言語リファレンス』

SQLJのREF CURSOR型

Oracle SQLJ実装では、REF CURSOR型を任意のイテレータ・クラス型またはjava.sql.ResultSet型のイテレータ列またはホスト変数にマッピングできます(ただし、ホスト変数はOUTのみにできます)。次に、REF CURSOR型の用途をまとめます。

- ストアド・ファンクションの戻り値に使用する結果式として

- ストアド・プロシージャまたはストアド・ファンクションの出力パラメータの出力ホスト式として

- INTOリスト中の出力ホスト式として

- イテレータ列として

SQLのCURSOR演算子は、外部のSELECT文の内側にネストされているSELECTに対して使用できます。これによって、REF CURSORオブジェクトをイテレータ列またはイテレータのResultSet列に書き込むか、REF CURSORオブジェクトをイテレータ・ホスト変数またはINTOリストのResultSetホスト変数に書き込むことが可能になります。

関連項目:
暗黙的なREF CURSOR変数の使用例(たとえば、CURSOR演算子の例など)は、「ホスト変数としてのイテレータおよび結果セットの使用」を参照してください。

注意:

- REF CURSOR型には、型コードOracleTypes.CURSORを使用する必要があります。

- REF CURSOR型は、oracle.sqlクラスではサポートされていません。java.sql.ResultSetクラスまたはイテレータ・クラスを使用する必要があります。リソースを解放するために、結果セットまたはイテレータは、処理完了時点で終了してください。

REF CURSORの例

無名ブロックからREF CURSOR型を取り出すサンプル・メソッドを次に示します。

private static EmpIter refCursInAnonBlock(String name, int no)
throws java.sql.SQLException {
EmpIter emps = null;

System.out.println("Using anonymous block for ref cursor..");
#sql { begin
INSERT INTO emp (ename, empno) VALUES (:name, :no);
OPEN :out emps FOR SELECT ename, empno FROM emp ORDER BY empno;
end
};
return emps;
}

その他のOracle Database 11g データ型のサポート

oracle.sqlのあらゆるクラスは、イテレータ列にも、入力、出力または入出力のホスト変数にも、標準Java型と同じように使用できます。たとえば、前述したクラスでは、oracle.sql.NUMBER、oracle.sql.CHAR、oracle.sql.RAWなどのクラスがサポートされています。

oracle.sql.*クラスはJava型の形式に変換する必要がないため、同等のJava型より効率および精度面で優れています。ただし、標準Javaプログラムで使用する場合、またはエンド・ユーザーで表示する場合は、データを標準Java型に変換する必要があります。

BigDecimalのサポート強化

SQLJでは、java.math.BigDecimalを次の用途に使用できます。

- SQLJ実行文中のホスト変数として

- ストアド・ファンクション・コールの戻り値として

- イテレータの列型として

標準SQLJで数値データおよび10進データの値をBigDecimalとして取得するには、JDBCのデフォルト・マッピングを使用する必要があります。

関連項目:
表5-1「ホスト式でサポートされている型の対応」

標準SQLJに対し、Oracle SQLJ実装では、Oracle9i 以上のデータベース、Oracle JDBCドライバ、Oracle固有コード生成またはOracleカスタマイザ、およびOracle SQLJランタイムを使用すると、数値から変換可能なデータ型をデフォルト以外の型にマッピングできます。変換可能な型としては、CHAR、VARCHAR2、LONGおよびNUMBERがあります。たとえば、CHAR列のデータは、BigDecimal変数への取込みができます。ただし、エラーを防ぐために、文字データの内容を数字のみにする必要があります。

注意:
BigDecimalクラスは標準java.mathパッケージにあります。

6 オブジェクト、コレクションおよびOPAQUE型

この章では、Oracle SQLJ実装でユーザー定義SQL型がどのようにサポートされるかを説明します。ユーザー定義SQL型に対応するJavaクラスを生成できるOracle JPublisherユーティリティについても説明します。この章の最後には、Oracle OPAQUE型に関する項もあります。

この章では、次の項目について説明します。

- Oracleのオブジェクトとコレクションについて

- カスタムJavaクラス

- ユーザー定義データ型

- JPublisherとカスタムJavaクラスの作成

- SQLJ実行文の強い型指定のオブジェクトと参照

- SQLJ実行文の強い型指定のコレクション

- シリアライズされたJavaオブジェクト

- 弱い型指定のオブジェクト、参照およびコレクション

- Oracle OPAQUE型

Oracleのオブジェクトとコレクションについて

ここでは、Oracle Database 11g のオブジェクトとコレクションの基本的な概念について説明します。

関連項目:
『Oracle Database SQL言語リファレンス』および『Oracle Databaseアドバンスト・アプリケーション開発者ガイド』.

ここでは、次の項目について説明します。

- オブジェクトとコレクションの概要

- Oracleオブジェクトの基本概念

- Oracleコレクションの基本概念

- オブジェクトとコレクションのデータ型

オブジェクトとコレクションの概要

Oracle SQLJ実装では、ユーザー定義のSQLオブジェクト型(複合データ構造体)、関連するSQLオブジェクト参照型およびユーザー定義のSQLコレクション型がサポートされています。Oracleのオブジェクトとコレクションは、複合データ構造体であり、複数のデータ要素で構成されます。

Oracle SQLJ実装では、強い型指定または弱い型指定の、Java表現のオブジェクト型、参照型およびコレクション型を、イテレータまたはホスト式で使用できます。強い型指定の表現では、特定のオブジェクト型、参照型またはコレクション型にマッピングするカスタムJavaクラスを使用しますが、このクラスはJava Database Connectivity (JDBC) 2.0標準のjava.sql.SQLDataインタフェース(オブジェクト型の場合のみ)またはOracleのoracle.sql.ORADataインタフェースを実装する必要があります。どちらのインタフェースもOracle Database 11g JPublisherユーティリティでサポートされており、このユーティリティを使用するとカスタムJavaクラスを自動生成できます。

「強い型指定」という用語は、特定のJava型がSQL名前指定型またはユーザー定義型に対応付けられている場合に使用されます。たとえば、PERSON型がある場合、対応するPerson Javaクラスが対応付けられます。

弱い型指定の表現では、oracle.sql.STRUCT(オブジェクトの場合)、oracle.sql.REF(オブジェクト参照の場合)またはoracle.sql.ARRAY(コレクションの場合)を使用します。弱い型指定の表現では、標準java.sql.Struct、java.sql.Refまたはjava.sql.Arrayオブジェクトもかわりに使用できます。

「弱い型指定」という用語は、Java型が汎用的な方法で使用され、複数のSQL名前指定型にマップできる場合に使用されます。Javaクラス(インタフェース)には、SQL型に特有の情報はありません。これは、oracle.sql.STRUCT、oracle.sql.REFおよびoracle.sql.ARRAY型とjava.sql.Struct、java.sql.Refおよびjava.sql.Array型の場合です。

コード中にOracle拡張型を使用する場合は、次の要件が伴うので注意してください。

- Oracle JDBCドライバを使用する必要があります。

- デフォルトのOracle固有コード生成を使用するか、またはISOコード生成の場合は必要に応じてプロファイルをカスタマイズします。Oracle固有生成コードの場合、プロファイルが生成されないため、カスタマイズは適用されません。Oracle JDBC Application Program Interface(API)は、生成されたJavaコードによって直接コールされます。

注意:
デフォルトのカスタマイザoracle.sqlj.runtime.util.OraCustomizerを使用することをお薦めします。

- アプリケーションの実行時にOracle SQLJランタイムを使用します。Oracle SQLJランタイムとOracle JDBCドライバは、Oracle拡張型をコード中に使用しない場合であっても、Oracleカスタマイザを使用する場合は常に必要です。

Oracle固有のセマンティクス・チェックを行うには、適切なチェッカを使用する必要があります。デフォルトのチェッカoracle.sqlj.checker.OracleCheckerは、フロントエンドとして機能し、環境に応じたチェッカを起動します。JDBCドライバを使用すると、Oracle固有のチェッカが起動されます。

注意:
Oracleオブジェクトとコレクション用のOracle固有の型は、oracle.sqlパッケージにあります。

関連項目:
「接続オプション」および「セマンティクス・チェックとオフライン解析のオプション」

カスタムJavaクラスの使用方法

- この章では、主に、ユーザー定義型に対するカスタムJavaクラスの使用方法について説明します。ただし、ORADataを実装したクラスは、他のOracle SQL型に対しても使用できます。ORADataを実装したクラスを使用すると、SQLとJava間のデータ転送時に任意の処理または変換を実行できます。

関連項目:
「ORAData実装のその他の使用例」

- SQLDataインタフェースは、カスタム・オブジェクト・クラス専用です。これに対し、ORADataインタフェースは、どのカスタムJavaクラスにも使用できます。

用語上の注意

- ユーザー定義のSQLオブジェクト型とSQLコレクション型は、ユーザー定義型(UDT)と呼ばれます。

- オブジェクト、参照およびコレクションのカスタムJavaクラスは、それぞれカスタム・オブジェクト・クラス、カスタム参照クラスおよびカスタム・コレクション・クラスと呼ばれます。

関連項目:
Oracleオブジェクトの特長と機能の概要は、『Oracle Databaseオブジェクト・リレーショナル開発者ガイド』を参照してください。

Oracleオブジェクトの基本概念

Oracle SQLオブジェクトは複合データ構造体であり、関連するデータ項目(各従業員に関する事実など)を1つのデータ単位にまとめたものです。オブジェクト型は、機能的にはJavaのクラスに相当します。Java型をインスタンス化してオブジェクトをいくつでも使用できるように、特定のオブジェクト型のオブジェクトをいくつでも設定して使用できます。

たとえば、CHAR型の属性name、CHAR型のaddress、CHAR型のphonenumberおよびNUMBER型のemployeenumberを持つオブジェクト型EMPLOYEEを定義できます。

Oracleのオブジェクトのメソッド(ストアド・プロシージャ)は、オブジェクト型への対応付けができます。これらのメソッドは、staticメソッドまたはインスタンス・メソッドとして、PL/SQLまたはJavaで実装できます。メソッドのシグネチャとして、任意の数の入力、出力または入出力パラメータを使用できます。すべては初期定義によって決まります。

Oracleコレクションの基本概念

Oracle SQLコレクションは、次の2つのカテゴリに分類されます。

- 可変長配列(VARRAY型)

- ネストした表(NESTED TABLE型)

どちらのカテゴリも1次元ですが、その要素として複合オブジェクト型を使用できます。VARRAY型は1次元配列に対して使用しますが、NESTED TABLE型は表に含まれる単一列の表に対して使用します。VARRAY型の変数をVARRAYと呼びます。NESTED TABLE型の変数をネストした表と呼びます。

VARRAYは、配列と同様、データ要素の順序付けられた集合であり、各要素が1つの索引を持ち、すべての要素のデータ型が同じです。VARRAYのサイズは、要素の最大数を示します。OracleのVARRAYは、名前が示すように可変サイズですが、VARRAY型の宣言時に、そのVARRAY型の最大サイズを指定する必要があります。

ネストした表は、順序付けされていない要素の集合です。表内のネストした表要素は、それ自体SQLで問合せを実行します。表と同じように、ネストした表の行数は、作成時に指定する必要はありません。行数は動的に算出されます。

注意:
VARRAYの各要素またはネストした表内の各行は、ユーザー定義のオブジェクト型にすることが可能であり、ユーザー定義オブジェクト型の属性に対して、VARRAY型およびNESTED TABLE型を使用できます。Oracle Database 11gでは、コレクション型のネストをサポートしています。VARRAYの要素またはネストした表内の行を、別のVARRAY型またはNESTED TABLE型にすることも、VARRAY属性またはネストした表の属性を持つユーザー定義のオブジェクト型にすることもできます。

オブジェクトとコレクションのデータ型

Oracle Database 11g では、ユーザー定義のオブジェクトおよびコレクション定義は、SQLのデータ型定義として機能します。これらのデータ型は、他のデータ型と同じように、表の列定義、SQLオブジェクトの属性定義およびストアド・プロシージャまたはストアド・ファンクションのパラメータの定義に使用できます。また、オブジェクト型を定義すると、そのオブジェクト参照型を他のSQL参照型のように使用できます。

たとえば、前の項のEMPLOYEE Oracleオブジェクトを考えます。このオブジェクトを定義すると、Oracleのデータ型になります。NUMBER型の表列と同じように、EMPLOYEE型の表列を持つことができます。EMPLOYEE列の各行に、EMPLOYEEオブジェクト全体を格納できます。EMPLOYEEオブジェクトへの参照で構成されるREF EMPLOYEE型の列を持つこともできます。

同様に、NUMBERのVARRAY(10)としてVARRAY型MYVARRを定義したり、CHAR(20)のNESTED TABLE型NTBLを定義できます。コレクション型MYVARRとNTBLはOracleのデータ型になるので、これらの型の列を表に定義できます。MYVARR列の各行は、最大10数字を収容する配列です。NTBL列の各行は20文字で構成されます。

カスタムJavaクラス

カスタムJavaクラスはファーストクラスの型で、ユーザー定義SQL型に対する読取りおよび書込みを透過的に行う場合に使用できます。カスタムJavaクラスの用途は、SQLとJava間のデータの変換手段を提供し、データへのアクセスを可能にすることです。この機能は、特に、オブジェクトとコレクションのサポートにおいて、またはデータのカスタム変換を行う場合に重要です。

SQLJアプリケーションで使用するすべてのユーザー定義型に対して、カスタムJavaクラスを用意することをお薦めします。Oracle JDBCドライバではデータ変換にこのクラスのインスタンスが使用され、弱い型指定のoracle.sql.STRUCT、oracle.sql.REFおよびoracle.sql.ARRAYクラスを使用するも便利で、エラーも発生しにくくなります。

SQLJイテレータまたはホスト式で使用するには、カスタムJavaクラスにoracle.sql.ORADataおよびoracle.sql.ORADataFactoryインタフェース、または標準java.sql.SQLDataインタフェースを実装する必要があります。ここでは、これらのインタフェースとカスタムJavaクラス機能の概要を、次の項目について説明します。

- カスタムJavaクラスのインタフェース指定

- オブジェクト・メソッドでのカスタムJavaクラスのサポート

- カスタムJavaクラスの要件

- カスタムJavaクラスのコンパイル

- カスタム・データの読込みと書込み

- ORAData実装のその他の使用例

カスタムJavaクラスのインタフェース指定

ここでは、ORADataおよびORADataFactoryインタフェースと標準SQLDataインタフェースの指定について説明します。

Oracle Database 11g には、ユーザー定義型(oracle.sql.ORADataおよびoracle.sql.ORADataFactory)に対するOracle固有のカスタムJavaクラス機能をサポートするための一連のAPIが含まれています。

以前この機能のために使用されていたoracle.sql.CustomDatumおよびoracle.sql.CustomDatumFactoryインタフェースは非推奨になりました。

ORADataおよびORADataFactoryの指定

Oracleには、oracle.sql.ORADataインタフェースと関連するoracle.sql.ORADataFactoryインタフェースが用意されています。これらのインタフェースを使用して、Oracleのオブジェクト型、参照型およびコレクション型をカスタムJavaクラスにマッピングできます。

データの送信や取出しにはoracle.sql.Datumオブジェクトの形式を使用し、元のデータは適切なoracle.sql.Datumのサブクラス(oracle.sql.STRUCTなど)の形式にします。このデータはSQL形式のままです。oracle.sql.Datumオブジェクトはラッパーとしてのみ機能します。

関連項目:
『Oracle Database JDBC開発者ガイドおよびリファレンス』

Java形式からSQL形式へのデータ変換に使用するtoDatum()メソッドは、ORADataインタフェースで指定します。このメソッドでは、接続オブジェクトを入力として見なし、データをoracle.sql.*表現に変換します。JDBCドライバは、実行時に接続オブジェクトを使用して、型チェックと型変換を行います。ORADataとtoDatum()は、次のように指定します。

interface oracle.sql.ORAData
{
oracle.sql.Datum toDatum(java.sql.Connection c) throws SQLException;
}

カスタムJavaクラスのインスタンスを作成し、SQL形式からJava形式に変換するcreate()メソッドは、ORADataFactoryインタフェースで指定します。このメソッドは、入力としてDatumオブジェクトを取り、このオブジェクトにはデータおよび型コード(基になるデータがSQL型であることを示すOracleTypes.RAWなど)が含まれます。このメソッドから戻されるカスタムJavaクラスのオブジェクトには、ORADataインタフェースが実装されています。このオブジェクトは、入力されたDatumオブジェクトからデータを取り出します。ORADataFactoryとcreate()は、次のように指定します。

interface oracle.sql.ORADataFactory
{
oracle.sql.ORAData create(oracle.sql.Datum d, int sqlType)
throws SQLException;
}

ORADataインタフェースとORADataFactoryインタフェース間の関係を確立するには、ORADataインタフェースを実装したカスタムJavaクラスに、static getORADataFactory()メソッドを実装する必要があります。このメソッドで戻されるオブジェクトは、ORADataFactoryインタフェースが実装されているので、カスタムJavaクラスのインスタンスの作成に使用できます。戻されたオブジェクト自体が、カスタムJavaクラスのインスタンスであることも可能であり、この場合、Oracle JDBCドライバは、必要に応じてそのcreate()メソッドを使用して、さらにカスタムJavaクラスのインスタンスを生成します。

注意:
JPublisherの出力は、ORADataインタフェースおよびそのtoDatum()メソッドと、ORADataFactoryインタフェースおよびそのcreate()メソッドとを、1つのカスタムJavaクラスに実装できます。ただし、toDatum()とcreate()を別々のインタフェースに指定した場合は、それぞれを別個のクラスに実装することも可能になります。ORADataおよびそのtoDatum()メソッドと、getORADataFactory()メソッドを1つのカスタムJavaクラスに実装する一方で、ORADataFactoryおよびそのcreate()メソッドを別個のファクトリ・クラスに実装することも可能です。ここでは、両方のインタフェースを1つのクラスに実装する場合について説明します。

関連項目:
「ORADataを実装したクラスに対するOracleの要件」

JPublisherを使用するして-usertypes=oracleを指定すると、JPublisherでカスタムJavaクラスが生成され、このクラスにはORADataインタフェース、ORADataFactoryインタフェースおよびgetORADataFactory()メソッドが実装されます。下位互換性を保つために、JPublisherの-compatibleオプションとともに-usertypes=oracleを指定して、CustomDatumおよびCustomDatumFactoryインタフェースを使用することもできます。

関連項目:
『Oracle Database JPublisherユーザーズ・ガイド』

ORADataとCustomDatumインタフェースの比較

Oracle9iデータベースでは、oracle.jdbc.driverクラスにかわってoracle.jdbcインタフェースが導入されていました。そのため、カスタマイズされたオブジェクトへのアクセスに以前使用されていたoracle.sql.CustomDatumおよびoracle.sql.CustomDatumFactoryインタフェースは非推奨になり、かわりにoracle.sql.ORADataおよびoracle.sql.ORADataFactoryインタフェースを使用します。CustomDatumインタフェースのように、これらを標準SQLDataインタフェースのOracle固有の代替インタフェースとして使用できます。CustomDatumインタフェースは、下位互換性を保つために現在もサポートされています。

CustomDatumおよびCustomDatumFactoryは、次のように定義します。

public interface CustomDatum
{
oracle.sql.Datum toDatum(
oracle.jdbc.driver.OracleConnection conn
) throws SQLException;

public interface CustomDatumFactory
{
oracle.sql.CustomDatum create(
oracle.sql.Datum d, int sqlType
) throws SQLException;
}

接続connおよび型コードsqlTypeは、ORADataおよびORADataFactoryで説明されているように使用されます。ただし、CustomDatumでは、標準Connection型ではなく、必ずOracle固有のOracleConnection型を使用してください。

SQLDataの指定

標準JDBC 2.0には、構造化オブジェクト型をJavaクラスにマッピングし、変換するためのjava.sql.SQLDataインタフェースが提供されています。このインタフェースは、構造化オブジェクト型のみをマッピングの対象としているため、コレクションや配列などのSQL型はマッピングできません。

SQLDataインタフェースは、JDBC 2.0標準であり、readSQL()メソッドを指定してデータをJavaオブジェクトに読み取る一方で、writeSQL()メソッドを指定してJavaオブジェクトからデータベースに書き込みます。JPublisherを使用して-usertypes=jdbcを指定するとJPublisherでカスタムJavaクラスが生成され、このクラスにはSQLDataインタフェースが実装されます。

標準SQLData機能の追加詳細は、Sun社のJDBC 2.0以上のAPI仕様を参照してください。

関連項目:
「SQLDataを実装したクラスに対する要件」

オブジェクト・メソッドでのカスタムJavaクラスのサポート

Oracleオブジェクト・メソッドは、カスタムJavaクラスのラッパーから起動できます。基になるストアド・プロシージャの記述言語がPL/SQL、Javaのどちらであるか、またSQLに公開されているかどうかは、ユーザーには表示されません。

Javaのラッパー・メソッドでサーバー側メソッドを起動するには、サーバーと通信するための接続が必要です。接続オブジェクトは、明示的パラメータとして提供することも、別の方法で関連付けることも可能です。たとえば、カスタムJavaクラスの属性として提供します。ラッパー・メソッドで使用する接続オブジェクトを非静的属性とした場合、このラッパー・メソッドをカスタムJavaクラスのインスタンス・メソッドとすると、この接続にアクセスできます。JPublisherで生成したカスタムJavaクラスでは、この手法が採用されています。

Oracleオブジェクト・メソッドの出力および入出力パラメータに関しては、次のことに留意してください。ストアド・プロシージャ(SQLオブジェクト・メソッド)によって、ある引数の内部状態が変更された場合、ストアド・プロシージャに渡された実引数も変更されます。Javaで記述した場合、こうした現象は起こりません。JDBC出力パラメータがストアド・プロシージャ・コールから戻る場合、新規に作成されたオブジェクトに格納する必要があります。元のオブジェクト識別性は失われます。

出力または入出力パラメータをコール元に戻す場合は、パラメータを配列要素として渡す方法もあります。入出力パラメータの場合は、ラッパー・メソッドが入力として配列要素をとります。処理後、ラッパーによって出力が配列要素に代入されます。JPublisherで生成したカスタムJavaクラスでは、この手法が使用されます。つまり、出力または入出力パラメータをそれぞれ単一要素配列で渡します。

JPublisherを使用すると、デフォルトではラッパー・メソッドが実装されます。生成されたクラスには、SQLDataインタフェースまたはORADataインタフェースが実装されており、このことが当てはまります。このデフォルトの機能を無効化するには、JPublisherの-methodsフラグをfalseに設定します。

関連項目:
『Oracle Database JPublisherユーザーズ・ガイド』

注意:
カスタムJavaクラスを実装する場合、ラッパー・メソッドを実装する方法としていくつかの選択肢があります。サーバーでのデータ処理には、SQLオブジェクト・メソッドによって直接実行する場合と、クライアントからサーバーへオブジェクト値を転送して、サーバー上でメソッドを実行する場合があります。JPublisherでのラッパー・メソッドの実装および実装による効果については、「JPublisherで生成されるラッパー・メソッド」を参照してください。

カスタムJavaクラスの要件

カスタムJavaクラスに求められる要件としては、有効なホスト変数型としてOracle SQLJトランスレータで認識できることおよびトランスレータで型チェックできることが挙げられます。

注意:
ユーザー定義型用のカスタムJavaクラスは、このマニュアルで「ラッパー・クラス」と呼ばれている場合が多くあります。

ORADataを実装したクラスに対するOracleの要件

ORADataを実装するためのOracleでの要件は、どのカスタムJavaクラスの場合にも基本的には同じです。ただし、クラスによるマッピング先が、オブジェクト、オブジェクト参照、コレクションまたはその他のSQL型のどれに該当するかによって、この要件は若干異なってきます。

この要件を次に示します。

- oracle.sql.ORADataインタフェースを実装したクラスであること。

- oracle.sql.ORADataFactoryオブジェクトを戻り値とするgetORADataFactory()メソッドを実装したクラスであること。メソッドのシグネチャは、次のように指定します。

public static oracle.sql.ORADataFactory getORADataFactory();

非推奨のCustomDatumインタフェースを使用する場合、クラスでgetFactory()メソッドを実装すること。このメソッドはoracle.sql.CustomDatumFactoryオブジェクトを戻します。メソッドのシグネチャは、次のように指定します。

public static oracle.sql.CustomDatumFactory getFactory();

- クラスがString定数_SQL_TYPECODEを持ち、この定数が、toDatum()から戻されるDatumサブクラス・インスタンスのoracle.jdbc.OracleTypes型コードに初期化されること。型コードを次に示します。

- カスタム・オブジェクト・クラスの場合

public static final int _SQL_TYPECODE = OracleTypes.STRUCT;

- カスタム参照クラスの場合

public static final int _SQL_TYPECODE = OracleTypes.REF;

- カスタム・コレクション・クラスの場合

public static final int _SQL_TYPECODE = OracleTypes.ARRAY;

これ以外のクラスの場合は、それぞれ適切な型コードで初期化します。たとえば、カスタムJavaクラスで、RAWフィールドに対してJavaオブジェクトをシリアライズおよびシリアライズ解除するには、_SQL_TYPECODEをOracleTypes.RAWに初期化します。

注意:
OracleTypesクラスは、各Oracleデータ型の型コード(整数の定数)のみを定義します。標準SQL型のOracleTypesエントリは、標準java.sql.Types型定義クラスのエントリと同じです。

関連項目:
「シリアライズされたJavaオブジェクト」

- _SQL_TYPECODEがSTRUCT、REFまたはARRAYのいずれかに該当する(つまり、オブジェクト、オブジェクト参照またはコレクションを表す)カスタムJavaクラスの場合、該当のユーザー定義型の名前を示す定数を保持していること。次に例を示します。

- カスタム・オブジェクト・クラスおよびカスタム・コレクション・クラスのString定数_SQL_NAMEは、ユーザー定義型に対して宣言したSQL名に初期化する必要があります。次に例を示します。

public static final String _SQL_NAME = UDT name;

たとえば、ユーザー定義のPERSONオブジェクトのカスタム・オブジェクト・クラスの定数は次のようになります。

public static final String _SQL_NAME = "PERSON";

次のように、必要に応じて、スキーマで同様に指定できます。

public static final String _SQL_NAME = "SCOTT.PERSON";

PERSONオブジェクトのコレクションをPERSON_ARRAYと宣言した場合のカスタム・コレクション・クラスの定数は、次のようになります。

public static final String _SQL_NAME = "PERSON_ARRAY";

- カスタム参照クラスのString定数_SQL_BASETYPEは、参照先のユーザー定義型に対して宣言したSQL名に初期化する必要があります。

public static final String _SQL_BASETYPE = UDT name;

PERSON参照のカスタム参照クラスの定数は、次のようになります。

public static final String _SQL_BASETYPE = "PERSON";

前述以外のORADataで使用する場合、UDT名の指定はありません。

使用時には次の事項に注意してください。

- コレクション型の名前は、ベース型ではなく、コレクション型を表す名前にします。たとえば、PERSONオブジェクトに対し、VARRAYまたはNESTED TABLE型のPERSON_ARRAYを宣言した場合は、_SQL_NAMEエントリに指定するコレクション型の名前は、PERSONではなく、PERSON_ARRAYになります。

- SQL型を_SQL_NAMEフィールドに指定するときに、SQL型が大/小文字を区別して(引用符で囲んで)宣言されている場合、CaseSensitiveやSCOTT.CaseSensitiveなど、宣言されているとおりにSQL名を指定する必要があります。これは、引用符内で同様に名前の大/小文字を区別するJPublisher入力ファイルでの使用方法と異なります。SQL型を大/小文字を区別して宣言していない場合(引用符なし)、ADDRESSやSCOTT.ADDRESSのように、すべて大文字でSQL名を指定する必要があります。
JPublisherでは、大/小文字の区別とJPublisherの-omit_schema_names設定がある場合はそれに従って、自動的にこのフィールドの値を生成します。

SQLDataを実装したクラスに対する要件

ISO SQLJ規格では、SQLDataインタフェースを実装するクラスへの型マップ定義の要件を概説しています。一方、SQLDataラッパー・クラスは、public static finalフィールドでSQL関連オブジェクト型を識別できます。

次の点は重要なので、十分に注意してください。

- マッピングの指定に型マップを使用する場合でも、標準でないpublic static finalフィールドを使用する場合でも、一貫して指定する必要があります。public static finalフィールドを不要にする目的ですべての関連マッピングを指定する型マップを使用するか、または型マップをまったく使用せずにすべてのマッピングをpublic static finalフィールドで指定します。

- SQLDataは、ORADataとは異なり、構造化オブジェクト型のマッピング専用です。オブジェクト参照やコレクションや配列などのSQL型のマッピングには、SQLDataを使用できません。ORADataを使用しない場合、オブジェクト参照とコレクションをマッピングする方法は、それぞれ弱い型指定のjava.sql.Refとjava.sql.Array、またはoracle.sql.REFとoracle.sql.ARRAYを使用する方法のみです。

- SQL型からJava型へのマッピングを指定するとき、SQL型が大/小文字を区別する方法で宣言されている場合、CaseSensitiveまたはSCOTT.CaseSensitiveなど宣言されているとおりにSQL名を指定する必要があります。これは、引用符内で同様に名前の大/小文字を区別するJPublisher入力ファイルでの使用方法と異なります。SQL型を大/小文字を区別して宣言していない場合、ADDRESSやSCOTT.ADDRESSのように、すべて大文字でSQL名を指定する必要があります。

型マップ・リソースで指定したマッピング

まず、ISO SQLJ規格に従ったマッピング表現を想定します。Address、pack.Personおよびpack.Manager.InnerPM(InnerPMはManagerの内部クラスです)がjava.sql.SQLDataを実装している3つのラッパー・クラスであるとします。

次の点を考慮する必要があります。

- これらのクラスは、宣言済の接続コンテキスト型の明示的接続コンテキスト・インスタンスを使用する文でのみ採用する必要があります。たとえば、この型をSDContextと呼ぶとします。

Address               a =...;
pack.Person           p =...;
pack.Manager.InnerPM pm =...;
SDContext ctx = new SDContext(url,user,pwd,false);
#sql [ctx] { ... :a ... :p ... :pm ... };

- 接続コンテキスト型は、java.util.PropertyResourceBundleを実装している関連クラスを指定するwith属性のtypeMapで宣言されている必要があります。前述の例では、SDContextが次のように宣言されています。

#sql public static context SDContext with (typeMap="SDMap");

- 型マップのリソースは、SQLオブジェクト型からjava.sql.SQLDataインタフェースを実装するJavaクラスにマッピングしている必要があります。このマッピングは、次の形式のエントリで指定します。

class.java_class_name=STRUCT sql_type_name

STRUCTキーワードは省略可能です。例では、SDMap.propertiesリソース・ファイルに次のエントリがあります。

class.Address=STRUCT SCOTT.ADDRESS
class.pack.Person=PERSON
class.pack.Manager$InnerPM=STRUCT PRODUCT_MANAGER

パッケージとクラス名の分割にはピリオド(.)を使用しますが、内部クラス名を分割するにはドル記号($)を使用する必要があります。

重要:
デフォルトのOracle固有コード生成を使用している場合、コンテキスト型がSDContextの文に使用されるイテレータにも同じ型マップSDMapが宣言されていることが必要です。次に例を示します。

#sql public static iterator SDIter with (typeMap="SDMap");
...
SDContext sdctx = ...
SDIter sditer;
#sql [sdctx] sditer = { SELECT ...};

これにより、イテレータ・クラスに正しいコードが生成されたことを確認します。

マッピングを型マップ・リソースに指定するこのメカニズムは、非標準の方法よりも複雑になっています。さらに、型マップ・リソースをデフォルトの接続コンテキストと関連付けることはできません。すべてのマッピング情報が1つの場所、型マップ・リソースに置かれるというメリットがあります。つまり、コンパイル済アプリケーションでの型マッピングは、後で簡単に調整できます。たとえば、新規SQL型およびJavaラッパーを拡張SQL-Java型階層に含めることができます。

次の点に注意してください。

- この機能を使用するには、SQLJ runtime12またはruntime12eeライブラリを採用する必要があります。型マップはjava.util.Mapオブジェクトで表されます。これらは、SQLJランタイムAPIで公開されていますが、汎用ランタイム・ライブラリではサポートできません。

- SQLDataラッパー・クラスがSQLJ文のOUTまたはINOUTパラメータに現れた場合、Oracle SQLJランタイムおよびOracle固有コード生成またはプロファイルのカスタマイズを使用する必要があります。これは、Oracle JDBCがそのようなパラメータのSQL型をregisterOutParameter()で必要とするためです。さらに、OUTパラメータ型を登録するため、SQL型は変換中に有力な型マップにより凍結されます。

- SQLJ型マップは基礎となる接続で使用しているJDBC型マップとは独立しています。このため、SQLDataラッパーを使用しているSQLJコードおよびJDBCコードを混在させている場合は、注意が必要です。しかし、指定されたSQLJ接続コンテキスト上の有効な型マップは、簡単に抽出できます。

ctx.getTypeMap();

ラッパー・クラスの静的フィールドで指定されたマッピング

SQLDataを実装しているクラスは、次の非標準要件を満たすことができます。

- JavaクラスはString定数_SQL_NAMEを宣言し、そこでJavaクラスによってラップされるSQL型の名前を定義します。例として、Addressクラスには次のようなフィールド宣言があります。

public static final String _SQL_NAME="SCOTT.ADDRESS";

次の宣言はpack.Person内にあります。

public static final String _SQL_NAME="PERSON";

また、pack.Manager.InnerPMクラスには次の要素があります。

public static final String _SQL_NAME="PRODUCT_MANAGER";

JPublisherでは、常に_SQL_NAMEフィールドとともにSQLDataラッパー・クラスが生成されます。ただし、このフィールドは型マップを参照するSQLJ文では無視されます。

注意:

- _SQL_NAMEフィールドを実装するクラスが明示的接続コンテキスト型および関連型マップとともにSQLJ文内で使用されている場合、その型マップが使用され、_SQL_NAMEフィールドは無視されます。これにより、既存のSQLJプログラムのISO SQLJ規格への移行は簡素化されます。

- _SQL_NAMEフィールドで指定した静的SQL-Java型の対応は、基礎となる接続で使用しているJDBC型マップからは独立しています。このため、SQLDataラッパーを使用しているSQLJコードおよびJDBCコードを混在させている場合は、注意が必要です。

カスタムJavaクラスのコンパイル

SQLJのコマンドラインには、カスタムJavaクラス(ORADataまたはSQLDataを実装)の.javaファイルを、アプリケーションの.sqljファイルと一緒に指定できます。ただし、この指定は、SQLJの-checksourceフラグをtrue (デフォルト)に設定し、CLASSPATHにカスタムJavaソースの保存ディレクトリを指定した場合には必要ありません。

注意:
ここでは、カスタム・オブジェクトとカスタム・コレクション用に、.sqljファイルではなく.javaファイルを作成していることを想定しています。.sqljファイルは、SQLJコマンドラインで指定される必要があります。

たとえば、ObjectDemo.sqljでOracleのオブジェクト型ADDRESSおよびPERSONを使用し、これらのオブジェクトのカスタムJavaクラスが生成されている場合は、次のようにSQLJを実行できます。

- -checksource=trueを指定し、CLASSPATHにカスタムJavaソースの保存ディレクトリを指定した場合は、次のようにします。

% sqlj ObjectDemo.sqlj

- -checksource=falseを指定した場合は、次のようにします(この行は、全体を1行で入力します)。

% sqlj ObjectDemo.sqlj Address.java AddressRef.java Person.java PersonRef.java

また、Javaコンパイラを使用してカスタム.javaソース・ファイルを直接コンパイルすることもできます。この場合は、.sqljファイルの変換前に、コンパイルする必要があります。

関連項目:

- 「ソース・ファイル名のチェック(-checkfilename)」

- 第8章「トランスレータのコマンドラインとオプション」

注意:
ORAData実装はOracle固有の機能を必要とするため、トランスレータの移植設定を-warn=noportable (デフォルト)に設定する必要があり、この設定にしない場合は移植性に関する多数の警告がSQLJから通知されます。-warnフラグの詳細は、「トランスレータからの警告(-warn)」を参照してください。

カスタム・データの読込みと書込み

カスタムJavaクラス・インスタンスを使用すると、Oracle SQLJおよびJDBC実装では、ユーザー定義型の読込みと書込みが可能になります(ただし、これらは組込み型です)。この仕組みをユーザーが意識することはありません。

ORAData実装およびSQLData実装でのデータの読込み/書込みの仕組みは、『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

ORAData実装のその他の使用例

ここまでは、カスタムJavaクラスについて、次のような使用例を取り上げてきました。

- SQLオブジェクトのラッパー: このカスタム・オブジェクト・クラスは、oracle.sql.STRUCTインスタンスに対して使用します。

- SQL参照のラッパー: このカスタム参照クラスは、oracle.sql.REFインスタンスに対して使用します。

- SQLコレクションのラッパー: このカスタム・コレクション・クラスは、oracle.sql.ARRAYインスタンスに対して使用します。

これ以外のoracle.sql.*型をラッピングする場合でも、カスタムJavaクラスを用意すると独自の変換または処理に役立つことがあります。このためには、次の例に示すように、ORADataを実装したクラスを使用してください(SQLData使用しません)。

- データの暗号化と復号化、またはデータの妥当性チェックを行う場合

- 読込み後または書込み前の値をロギングする場合

- CHAR列(URL情報を格納した文字フィールドなど)をより小さいコンポーネントに解析する場合

- 文字列を数値定数にマッピングする場合

- データをより適切なJava形式にマッピングする場合(DATEフィールドをjava.util.Date形式にマッピングする場合など)

- データ表現をカスタマイズする場合(選択した表のフィート単位データをメートル単位で表現する場合など)

- Javaオブジェクトをシリアライズおよびシリアライズ解除する場合(RAWフィールドなどに対して)

注意:
このような機能は、SQLDataインタフェースを使用しても実現されません。SQLData実装でラッピング対象となるのは構造化オブジェクト型のみに限られているためです。

関連項目:
「シリアライズされたJavaオブジェクト」

ORADataの一般的な使用方法: BetterDate.java

ここでは、ORADataインタフェースを実装したクラスを使用して、Javaの日付をカスタマイズする方法を示します。これは、java.sql.Dateのかわりに使用できます。

注意:
これは、完全なアプリケーションではありません。main()メソッドはありません。

import java.util.Date;
import oracle.sql.ORAData;
import oracle.sql.DATE;
import oracle.sql.ORADataFactory;
import oracle.jdbc.OracleTypes;

// a Date class customized for user's preferences:
//      - months are numbers 1..12, not 0..11
//      - years are referred to through four-digit numbers, not two.

public class BetterDate extends java.util.Date
implements ORAData, ORADataFactory {
public static final int _SQL_TYPECODE = OracleTypes.DATE;

String[]monthNames={"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
"JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
String[]toDigit={"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};

static final BetterDate _BetterDateFactory = new BetterDate();

public static ORADataFactory getORADataFactory() { return _BetterDateFactory;}

// the current time...
public BetterDate() {
super();
}

public oracle.sql.Datum toDatum(java.sql.Connection conn) {
return new DATE(toSQLDate());
}

public oracle.sql.ORAData create(oracle.sql.Datum dat, int intx) {
if (dat==null) return null;
DATE DAT = ((DATE)dat);
java.sql.Date jsd = DAT.dateValue();
return new BetterDate(jsd);
}

public java.sql.Date toSQLDate() {
java.sql.Date retval;
retval = new java.sql.Date(this.getYear()-1900, this.getMonth()-1,
this.getDate());
return retval;
}
public BetterDate(java.sql.Date d) {
this(d.getYear()+1900, d.getMonth()+1, d.getDate());
}
private static int [] deconstructString(String s) {
int [] retval = new int[3];
int y,m,d; char temp; int offset;
StringBuffer sb = new StringBuffer(s);
temp=sb.charAt(1);
// figure the day of month
if (temp < '0' || temp > '9') {
m = sb.charAt(0)-'0';
offset=2;
} else {
m = (sb.charAt(0)-'0')*10 + (temp-'0');
offset=3;
}

// figure the month
temp = sb.charAt(offset+1);
if (temp < '0' || temp > '9') {
d = sb.charAt(offset)-'0';
offset+=2;
} else {
d = (sb.charAt(offset)-'0')*10 + (temp-'0');
offset+=3;
}

// figure the year, which is either in the format "yy" or "yyyy"
// (the former assumes the current century)
if (sb.length() <= (offset+2)) {
y = (((new BetterDate()).getYear())/100)*100 +
(sb.charAt(offset)- '0') * 10 +
(sb.charAt(offset+1)- '0');
} else {
y = (sb.charAt(offset)- '0') * 1000 +
(sb.charAt(offset+1)- '0') * 100 +
(sb.charAt(offset+2)- '0') * 10 +
(sb.charAt(offset+3)- '0');
}
retval[0]=y;
retval[1]=m;
retval[2]=d;
//    System.out.println("Constructing date from string as: "+d+"/"+m+"/"+y);
return retval;
}
private BetterDate(int [] stuff) {
this(stuff[0], stuff[1], stuff[2]);
}
// takes a string in the format: "mm-dd-yyyy" or "mm/dd/yyyy" or
// "mm-dd-yy" or "mm/dd/yy" (which assumes the current century)
public BetterDate(String s) {
this(BetterDate.deconstructString(s));
}

// years are as '1990', months from 1..12 (unlike java.util.Date!), date
// as '1' to '31'
public BetterDate(int year, int months, int date) {
super(year-1900,months-1,date);
}
// returns "Date: dd-mon-yyyy"
public String toString() {
int yr = getYear();
return getDate()+"-"+monthNames[getMonth()-1]+"-"+
toDigit[(yr/1000)%10] +
toDigit[(yr/100)%10] +
toDigit[(yr/10)%10] +
toDigit[yr%10];
//    return "Date: " + getDate() + "-"+getMonth()+"-"+(getYear()%100);
}
public BetterDate addDays(int i) {
if (i==0) return this;
return new BetterDate(getYear(), getMonth(), getDate()+i);
}
public BetterDate addMonths(int i) {
if (i==0) return this;
int yr=getYear();
int mon=getMonth()+i;
int dat=getDate();
while(mon<1) {
--yr;mon+=12;
}
return new BetterDate(yr, mon,dat);
}
// returns year as in 1996, 2007
public int getYear() {
return super.getYear()+1900;
}
// returns month as 1..12
public int getMonth() {
return super.getMonth()+1;
}
public boolean equals(BetterDate sd) {
return (sd.getDate() == this.getDate() &&
sd.getMonth() == this.getMonth() &&
sd.getYear() == this.getYear());
}
// subtract the two dates; return the answer in whole years
// uses the average length of a year, which is 365 days plus
// a leap year every 4, except 100, except 400 years =
// = 365 97/400 = 365.2425 days = 31,556,952 seconds
public double minusInYears(BetterDate sd) {
// the year (as defined in the preceding text) in milliseconds
long yearInMillis = 31556952L;
long diff = myUTC()-sd.myUTC();
return (((double)diff/(double)yearInMillis)/1000.0);
}
public long myUTC() {
return Date.UTC(getYear()-1900, getMonth()-1, getDate(),0,0,0);
}

// returns <0 if this is earlier than sd
// returns = if this == sd
// else returns >0
public int compare(BetterDate sd) {
if (getYear()!=sd.getYear()) {return getYear()-sd.getYear();}
if (getMonth()!=sd.getMonth()) {return getMonth()-sd.getMonth();}
return getDate()-sd.getDate();
}
}

ユーザー定義データ型

ここでは、Oracle Database 11g のユーザー定義オブジェクト型とユーザー定義コレクション型の作成例および使用例を示します。

オブジェクト型の作成

オブジェクト型を作成するSQLコマンドは、次の形式で指定します。

CREATE TYPE typename AS OBJECT
(
attrname1    datatype1,
attrname2    datatype2,
...         ...
attrnameN    datatypeN
);

typename で、オブジェクト型の名前を指定します。attrname1 からattrnameN で、属性名を指定します。datatype1 からdatatypeN で、属性のデータ型を指定します。

次に、Oracle Database 11g におけるユーザー定義オブジェクト型の作成例を示します。

この例では、SQLを使用して次の項目を作成します。

- 2つのオブジェクト型、PERSONとADDRESS。

- PERSONオブジェクト用の型付けされた表。

- EMPLOYEES表。ADDRESS列が1列とPERSON参照列が2列あります。

これらの項目を作成するスクリプトを次に示します。

/*** Using user-defined types (UDTs) in SQLJ ***/
/
/*** Create ADDRESS UDT ***/
CREATE TYPE ADDRESS AS OBJECT
(
street        VARCHAR(60),
city          VARCHAR(30),
state         CHAR(2),
zip_code      CHAR(5)
)
/
/*** Create PERSON UDT containing an embedded ADDRESS UDT ***/
CREATE TYPE PERSON AS OBJECT
(
name    VARCHAR(30),
ssn     NUMBER,
addr    ADDRESS
)
/
/*** Create a typed table for PERSON objects ***/
CREATE TABLE persons OF PERSON
/
/*** Create a relational table with two columns that are REFs
to PERSON objects, as well as a column which is an Address ADT. ***/
CREATE TABLE  employees
(
empnumber            INTEGER PRIMARY KEY,
person_data     REF  PERSON,
manager         REF  PERSON,
office_addr          ADDRESS,
salary               NUMBER
)
/*** Insert some data--2 objects into the persons typed table ***/
INSERT INTO persons VALUES (
PERSON('Wolfgang Amadeus Mozart', 123456,
ADDRESS('Am Berg 100', 'Salzburg', 'AT','10424')))
/
INSERT INTO persons VALUES (
PERSON('Ludwig van Beethoven', 234567,
ADDRESS('Rheinallee', 'Bonn', 'DE', '69234')))
/
/** Put a row in the employees table **/
INSERT INTO employees (empnumber, office_addr, salary) VALUES (
1001,
ADDRESS('500 Oracle Parkway', 'Redwood Shores', 'CA', '94065'),
50000)
/
/** Set the manager and PERSON REFs for the employee **/
UPDATE employees
SET manager =
(SELECT REF(p) FROM persons p WHERE p.name = 'Wolfgang Amadeus Mozart')
/
UPDATE employees
SET person_data =
(SELECT REF(p) FROM persons p WHERE p.name = 'Ludwig van Beethoven')

注意:
Oracle SQL実装では、特にユーザー定義型の表にアクセスする場合に、表の別名(この例のpなど)の使用を習慣付けることをお薦めします。オブジェクトの属性にアクセスする場合は、この構文を使用する必要があります。別名を使用する必要のない場合でも、別名の使用によって明確化できます。表の別名の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

コレクション型の作成

コレクションは、次の2つの種類があります。

- 可変長配列(VARRAY)

- ネストした表(NESTED TABLE)

VARRAY型を作成するSQLコマンドは、次の形式で指定します。

CREATE TYPE typename IS VARRAY(n) OF datatype;

typename でVARRAY型の名前を、n で配列内の最大要素数を、またdatatype で配列要素のデータ型を指定します。次に例を示します。

CREATE TYPE myvarr IS VARRAY(10) OF INTEGER;

NESTED TABLE型を作成するSQLコマンドは、次の形式で指定します。

CREATE TYPE typename AS TABLE OF datatype;

typenameでネストした表型の目的の名前を指定し、datatypeで表要素のデータ型を指定します。データ型は標準データ型だけでなく、ユーザー定義型も指定できます。ネストした表は1列のみに限られていますが、1つの列型を、複数の属性を持つ複合オブジェクトにすることも可能です。ネストした表には、データベース表と同様に、行数制限がありません。次に例を示します。

CREATE TYPE person_array AS TABLE OF person;

このCREATE TYPEコマンドを指定すると、PERSONオブジェクトから構成された各行にNESTED TABLE型が作成されます。

次に、Oracle Database 11g におけるユーザー定義のコレクション型およびオブジェクト型の作成例を示します。

SQLを使用して次の項目が作成および設定されます。

- 2つのオブジェクト型PARTICIPANT_TおよびMODULE_T

- コレクション型MODULETBL_T(MODULE_Tオブジェクトのネストした表)

- PARTICIPANT_T参照の列およびネストした表のMODULETBL_T列を含むPROJECTS表

- コレクション型PHONE_ARRAY(VARCHAR2(30)のVARRAY)

- PERSONとADDRESSオブジェクト(「オブジェクト型の作成」に同じ定義が示されています)

- EMPLOYEES表(PHONE_ARRAY列を含む)

これらの項目を作成するスクリプトを次に示します。

Rem This is a SQL*Plus script used to create schema to demonstrate collection
Rem manipulation in SQLJ

CREATE TYPE PARTICIPANT_T AS OBJECT (
empno   NUMBER(4),
ename   VARCHAR2(20),
job     VARCHAR2(12),
mgr     NUMBER(4),
hiredate DATE,
sal      NUMBER(7,2),
deptno   NUMBER(2))
/
SHOW ERRORS
CREATE TYPE MODULE_T  AS OBJECT (
module_id  NUMBER(4),
module_name VARCHAR2(20),
module_owner REF PARTICIPANT_T,
module_start_date DATE,
module_duration NUMBER )
/
SHOW ERRORS
CREATE TYPE MODULETBL_T AS TABLE OF MODULE_T;
/
SHOW ERRORS
CREATE TABLE projects (
id NUMBER(4),
name VARCHAR(30),
owner REF PARTICIPANT_T,
start_date DATE,
duration NUMBER(3),
modules  MODULETBL_T  ) NESTED TABLE modules STORE AS modules_tab;

SHOW ERRORS
CREATE TYPE PHONE_ARRAY IS VARRAY (10) OF varchar2(30)
/

/*** Create ADDRESS UDT ***/
CREATE TYPE ADDRESS AS OBJECT
(
street        VARCHAR(60),
city          VARCHAR(30),
state         CHAR(2),
zip_code      CHAR(5)
)
/
/*** Create PERSON UDT containing an embedded ADDRESS UDT ***/
CREATE TYPE PERSON AS OBJECT
(
name    VARCHAR(30),
ssn     NUMBER,
addr    ADDRESS
)
/
CREATE TABLE  employees
( empnumber            INTEGER PRIMARY KEY,
person_data     REF  person,
manager         REF  person,
office_addr          address,
salary               NUMBER,
phone_nums           phone_array
)
/

JPublisherとカスタムJavaクラスの作成

Oracleでは、Oracleのオブジェクト型、参照型およびコレクション型を強い型指定のパラダイムのJavaクラスに柔軟にマッピングできます。開発者は、これらのカスタムJavaクラスを次の方法で作成できます。

- OracleのJPublisherユーティリティでカスタムJavaクラスを自動生成し、このクラスを変更せずにそのまま使用する方法

- JPublisherでカスタムJavaクラスと対応するサブクラス(後でユーザーが機能を変更できる)を自動生成する方法

- JPublisherを使用せずに、手動でカスタムJavaクラスをコーディングする方法(「カスタムJavaクラスの要件」の要件を満たすクラスの場合のみ)

カスタムJavaクラスは手動でもコーディングできますが、JPublisherで生成されたクラスを直接使用すること、またはJPublisherで生成されたサブクラスを変更することをお薦めします。

JPublisherでは、Oracle oracle.sql.ORADataまたは標準java.sql.SQLDataインタフェースを実装したカスタム・オブジェクト・クラスを生成できます。このうちのORAData実装をJPublisherで生成した場合は、カスタム参照クラスも一緒に生成されます。現行より古いJDBCバージョンとの互換性のために、JPublisherで、非推奨のoracle.sql.CustomDatumインタフェースを実装するクラスを生成することもできます。

SQLDataインタフェースは、カスタム参照クラスやカスタム・コレクション・クラスには実装できません。これから開発するコードを移植可能にする方法は、弱い型指定の標準java.sql.Refオブジェクトとjava.sql.Arrayオブジェクトを、それぞれ参照とコレクションにマッピングする方法のみです。

ここでは、次の項目について説明します。

- JPublisherで生成される内容

- カスタムJavaクラスの生成

- JPublisherのINPUTファイルおよびプロパティ・ファイル

- カスタムJavaクラスの作成およびメンバー名の指定

- JPublisherで生成されるラッパー・メソッド

- JPublisherのカスタムJavaクラスの例

- JPublisher生成クラスの拡張

関連項目:

- 『Oracle Database JPublisherユーザーズ・ガイド』

- 『Oracle Database JDBC開発者ガイドおよびリファレンス』

JPublisherで生成される内容

JPublisherを使用してカスタムJavaクラスを生成する場合は、ORAData(カスタム・オブジェクト・クラス、カスタム参照クラスまたはカスタム・コレクション・クラス用)またはSQLData(カスタム・オブジェクト・クラス専用)実装を使用できます。ORAData実装には、ORADataFactoryインタフェース(カスタムJavaクラスのインスタンス生成に必要なインタフェース)も実装できます。

JPublisherの-usertypesオプションの設定内容に応じて、実装の対象が決まります。-usertypes=oracle設定ではORAData実装が指定され、-usertypes=jdbc設定ではSQLData実装が指定されます。

ORAData実装

ユーザー定義オブジェクト型を処理対象としてJPublisherを実行し、カスタム・オブジェクト・クラスに対してORAData実装を使用すると、次のようなクラスが自動的に生成されます。

- カスタム・オブジェクト・クラス(通常は.sqljソース・ファイル内)。Oracleのオブジェクト型に対応する型定義です。
このクラスには、各属性のアクセッサ・メソッドがあります。たとえば、getFoo()およびsetFoo()は、属性fooのアクセッサ・メソッドです。JPublisherのデフォルトでは、サーバー側Oracleオブジェクトのメソッドを起動するラッパー・メソッドもクラスに生成されます。ただし、-methods=falseを設定すると、このラッパー・メソッドを生成しないように指定できます。この場合、JPublisherは、ラッパー・メソッドを生成せずに、カスタム・オブジェクト用に.sqljファイルではなく.javaファイルを作成します。

- Oracleオブジェクト型へのオブジェクト参照にアクセスするためのカスタム参照クラス。
このカスタム参照クラスのgetValue()メソッドは、カスタム・オブジェクト・クラスのインスタンスを戻り値としており、もう1つのsetValue()メソッドは、カスタム・オブジェクト・クラスのインスタンスを入力として取り、データベース内のオブジェクトの値を更新します。

SQLオブジェクト型で参照を使用しているかどうかにかかわらず、強い型指定の参照クラスが常に生成されます。

- 最上位オブジェクトのオブジェクト属性またはコレクション属性にアクセスするためのカスタム・クラス。
Javaでは、最上位クラスのインスタンスを作成するとき、このクラスを使用して属性を作成します。

ユーザー定義コレクション型を処理対象としてJPublisherを実行し、ORADataを実装するように指定すると、次のようなクラスが自動的に生成されます。

- カスタム・コレクション・クラス。指定したOracleコレクション型に対応する型定義として機能します。
このカスタム・コレクション・クラスのオーバーロード・メソッドgetArray()およびsetArray()は、コレクション単位で取得や更新を行うメソッドであり、getElement()メソッドおよびsetElement()メソッドは、コレクションの要素単位で取得や更新を行うメソッドです。このクラスには、これ以外のユーティリティ・メソッドもあります。

- 要素のカスタム・オブジェクト・クラス(コレクションの要素がオブジェクトの場合)。
Javaでは、コレクションのインスタンスを作成するときに、このクラスを使用してオブジェクト要素を作成します。

JPublisherで生成したこの2種類のカスタムJavaクラスには、ORADataインタフェース、ORADataFactoryインタフェースおよびgetORADataFactory()メソッドが実装されます。

注意:

- ORAData実装を指定した場合、生成されたクラスはOracle固有の機能を使用するため、移植できなくなります。

- JPublisherではCustomDatumインタフェースは非推奨になりましたが、このインタフェースの実装は-compatibleオプションによってサポートされています。

ORAData実装のための強い型指定のオブジェクト参照

OracleのORADataを実装する場合、JPublisherでは、弱い型指定のoracle.sql.REFクラスを使用するのではなく、常に強い型指定のオブジェクト参照クラスを生成します。これによって、オブジェクト参照が強い型指定されている場合、型の安全性が向上し、SQLの動作がミラー化されます。強い型指定のクラス(PERSONオブジェクトを参照するPersonRefなどの名前とともに使用)は、基本的にはREFクラス用のラッパーです。

これらの強い型指定のREFラッパーには、参照されるSQLオブジェクトのインスタンスを対応するJavaクラスのインスタンスの形式で生成するgetValue()メソッドがあります。(継承する場合は、対応するJavaクラスのサブクラスのインスタンスとして生成することになります。)たとえば、PERSON SQLオブジェクト型と対応するPerson Javaクラスがある場合、PersonRef Javaクラスも存在します。PersonRefクラスのgetValue()メソッドは、データベース内のPERSONオブジェクトのデータを含むPersonインスタンスを戻します。

SQLオブジェクト型にオブジェクト参照の属性がある場合、そのオブジェクト型に対応するJavaクラスには、該当の参照型に対応するJavaクラスのインスタンスの属性があります。たとえば、MANAGER REF属性のPERSONオブジェクトがある場合、対応するPerson JavaクラスはManagerRef属性を持ちます。

SQLData実装

ユーザー定義型のオブジェクト型を処理対象としてJPublisherを実行し、カスタム・オブジェクト・クラスに対してSQLData実装を選択する場合、Oracleオブジェクト型に対応する型定義として機能するカスタム・オブジェクト・クラスが生成されます。このカスタム・コレクション・クラスに属するものを次に示します。

- 各属性のアクセッサ・メソッド

- 標準SQLDataインタフェースのreadSQL()メソッドとwriteSQL()メソッドの実装

- サーバー側で実行されるOracleオブジェクト・メソッドを起動するラッパー・メソッド(JPublisher実行時の設定が-methods=false以外の場合)

ただし、SQLDataインタフェースはオブジェクトのみを対象とし、参照やコレクションには使用できないため、Oracleオブジェクト型を参照するためのカスタム参照クラスについては、JPublisherでは生成の対象とはしていません。弱い型指定の標準java.sql.Refインスタンスまたはoracle.sql.REFインスタンスを使用する場合、移植性を気にする必要はありません。REFインスタンスは、カスタム参照クラスのインスタンスと同様に、Oracle拡張メソッドgetValue()およびsetValue()を使用して、参照するオブジェクトのインスタンスに対して読込みと書込みを行います。標準Refインスタンスには、こうした読込みと書込みの機能はありません。

同様に、カスタム・コレクション・クラスに対してはSQLData実装を使用できないため、弱い型指定の標準java.sql.Arrayインスタンスを使用するか、または移植性が必要でなければoracle.sql.ARRAYインスタンスを使用してください。ArrayインスタンスとARRAYインスタンスは、カスタム・コレクション・クラスのインスタンスと同様に、getArray()機能を備えているため、コレクションの全体または一部の読取りはできますが、要素レベルでのアクセスおよび書込みはできません(このアクセスや書込みには、カスタム・コレクション・クラスのgetElement()メソッドとsetElement()メソッドを使用する必要があります)。

注意:
JDBCの仕様では、SQLDataインタフェースが移植可能であると定義されています。ただし、JPublisherで生成されるSQLData実装を移植可能とするには、Oracle固有の機能とOracle型のマッピングを使用しないようにします(これらを使用した場合は、Oracle固有のoracle.sql.*クラスが使用されるためです)。

カスタムJavaクラスの生成

ここでは、JPublisherのコマンドラインの主要機能について説明します。主要機能として、Javaにマッピングするユーザー定義型を指定する機能、およびオブジェクト・クラス名、コレクション・クラス名、属性型のマッピングおよびラッパー・メソッドを指定する機能があります。次に、要点をまとめます。

- JPublisherの-usertypesオプションを介して、使用する実装を指定します。

- Javaにマッピングするユーザー定義型の指定。使用するJPublisherのカスタム・オブジェクト・クラスとカスタム・コレクション・クラスの名前を指定することも、デフォルトの名前を使用することも可能です。必要に応じてJPublisherの-sql、-userおよび-caseオプションを使用します。

- オプションとして、-numbertypes、-builtintypesおよび-lobtypesなどのJPublisherの-xxx typesオプションを介して属性型マッピングを指定します。

- ラッパー・メソッド(Oracleオブジェクト・メソッドなど)の作成要否も指定できます。デフォルトでは作成されますが、JPublisherの-methodsフラグでの指定も可能です。

注意:
これ以降は、カスタム参照クラスやカスタム・コレクション・クラスを簡潔に説明するために、ORAData実装についてのみ記述します。

生成されたクラスへの実装の選択

JPublisherを実行する前に、OracleのORADataインタフェースと標準SQLDataインタフェースのどちらを生成されたクラスに実装するかを検討します。SQLDataを使用すると、コードの移植性が高くなりますが、ORADataを使用すると、型マップが不要になるなどいくつかのメリットがあります。

次の点に注意してください。

- カスタム・コレクション・クラスには、ORAData実装を使用する必要があります。SQLDataインタフェースではコレクションをサポートしていません。

- 強い型指定の参照クラスでは、常にORADataカスタム・オブジェクト・クラスの実装が生成され、SQLDataカスタム・オブジェクト・クラスの実装は生成されません。SQLDataインタフェースは、強い型指定のオブジェクト参照をサポートしていません。かわりに、弱い型指定のjava.sql.Ref型またはoracle.sql.REF型を使用してください。

JPublisher -usertypesオプションを使用して、クラスに実装するインタフェースを指定します。-usertypes=oracle設定(デフォルト)ではORADataインタフェースが指定され、-usertypes=jdbc設定ではSQLDataインタフェースが指定されます。

注意:
CustomDatumインタフェースは、ORADataに引き継がれ、Oracle9i データベースでは非推奨になりましたが、このインタフェースの実装が必要な場合は、JPublisherのcustomdatumの-compatible設定を使用して実装が可能です。これに-usertypes=oracle設定を組み合せることによって、生成されたクラスにCustomDatumインタフェースが実装されます。デフォルトは-compatible=oradataです。
-compatible=8iまたは-compatible=both8iを設定しても、JPublisherでCustomDatumが使用され、同様にOracle8i のJPublisherと互換性のあるコード生成が実行されます。詳細は、『Oracle Database JPublisherユーザーズ・ガイド』を参照してください。

次に示すJPublisherのコマンドラインは、それぞれORAData、CustomDatumおよびSQLDataを実装する例です(%はシステム・プロンプトです)。

% jpub -usertypes=oracle ... <other option settings>

% jpub -usertypes=oracle -compatible=customdatum ... <other option settings>

% jpub -usertypes=jdbc ... <other option settings>

-usertypes=jdbcの場合、-compatible=customdatumまたは-compatible=oradata設定はJPublisherでは無視されます。

Javaにマッピングするユーザー定義型の指定

JPublisherでカスタムJavaクラスを作成する場合は、Javaにマッピングするユーザー定義SQL型を-sqlオプションで指定します。カスタム・オブジェクト・クラスとカスタム・コレクション・クラスの名前を指定することも、デフォルト名を使用することも可能です。

最上位カスタム・クラス(-sqlオプションで名前を指定したユーザー定義型に対応するクラス)のデフォルト名には、JPublisherコマンドラインで入力したユーザー定義型の名前が使用されます。データベース内のSQL名はデフォルトでは大/小文字が区別されないため、SQL名を大文字で開始することによって、Java規則に従ってクラス名を大文字で開始できます。たとえば、employeeオブジェクトのカスタム・クラスを作成するには、次のようにJPublisherを実行します。

% jpub -sql=Employee ...

employeeオブジェクトの属性であるhome_addressオブジェクトなど、他のクラスのデフォルト名は、JPublisherの-caseオプションで指定します。-caseオプションを指定しないと、mixedに設定されます。つまり、カスタム・クラスのデフォルト名は、ユーザー定義型名の頭文字と以降の各ワードの頭文字が大文字になります。JPublisherでは、アンダースコア(_)、ドル記号($)、およびJavaの識別子で無効な文字は、ワード間のセパレータとしてみなされます。これらの文字は処理時に破棄されます。

たとえば、Oracleのオブジェクト型home_addressの場合は、クラスHomeAddressがHomeAddress.sqljまたは.javaのソース・ファイルに生成されます。

注意:

- JPublisherコマンドラインでは、大/小文字を区別していないSQL名のみサポートされます。大/小文字を区別する方法でユーザー定義型をSQLに定義した場合、コマンドラインや引用符ではなくJPublisherのINPUTファイルに名前を指定する必要があります。

- 旧バージョンのJPublisherとの下位互換用として、-sqlのかわりに-typesオプションを従来どおり使用できます。

JPublisherのコマンドラインでは、-sqlオプションに次の構文を使用します。

-sql=udt1<:mapclass1><,udt2<:mapclass2>>,...,<udtN<:mapclassN>> ...

単一のオプション設定で複数のアクションを指定できることに注意してください。

データベース・スキーマを指定するには、-userオプションを使用します。次に例を示します。

% jpub -sql=Myobj,mycoll:MyCollClass -user=scott
Enter scott password: password

注意:
カンマの前後に空白を挿入しないでください。

このように入力すると、OracleのオブジェクトはMYOBJという名前になり、Myobjクラスを定義したMyobj.sqljソース・ファイルが生成されます。また、MYCOLL Oracleコレクションに対して、MyCollClassクラスを定義したソース・ファイルMyCollClass.javaが生成されます。

-sqlにはスキーマ名(次の例のscottスキーマなど)も指定できます。

% jpub -sql=scott.Myobj,scott.mycoll:MyCollClass -user=scott
Enter scott password: password

カスタム参照クラスの名前は指定できません。JPublisherでは、カスタム・オブジェクト・クラス名の後ろにRefが追加されて、自動的に生成されます。これは、ORAData実装の場合のみです。たとえば、Myobjカスタム・オブジェクト・クラスを定義するMyobj.sqlj Javaソース・ファイルをJPublisherで作成すると、MyobjRefカスタム参照クラスを定義するMyobjRef.java Javaソース・ファイルも生成されます。

注意:
スキーマ(例のようにscottなど)を指定しても、カスタムJavaクラスの名前には取り込まれません。

「ユーザー定義データ型」で定義したオブジェクト型とコレクション型のカスタムJavaクラスを作成するには、次のようにJPublisherを実行します。

% jpub -user=scott -sql=Address,Person,Phone_array,Participant_t,Module_t,Moduletbl_t
Enter scott password: password

または、カスタム・オブジェクト・クラスとカスタム・コレクション・クラスの名前を明示的に指定し、次のように実行します。

% jpub -user=scott -sql=Address,Person,phone_array:PhoneArray,
participant_t:ParticipantT,module_t:ModuleT,moduletbl_t:ModuletblT
Enter scott password: password

前述の2つの例はそれぞれ折り返されて表示されていますが、1行で入力されたコマンドラインです。

2番目の例では、Javaソース・ファイルAddress.sqlj、AddressRef.java、Person.sqlj、PersonRef.java、PhoneArray.java、ParticipantT.sqlj、ParticipantTRef.java、ModuleT.sqlj、ModuleTRef.javaおよびModuletblT.javaが生成されます。ソース・ファイルの例は、「JPublisherのカスタムJavaクラスの例」を参照してください。

カスタムJavaクラスの設定方法を特定するために、JPublisherは指定されたスキーマに接続し、指定されたオブジェクト型の属性または指定されたコレクション型の要素を調べます。

注意:
単一の-sql設定に複数のマッピングを指定するかわりに、同一のコマンドラインに複数の-sqlオプションを使用できます。複数の-sqlオプションの効果は累積されます。

JPublisherで生成するメソッドおよび属性のデフォルト名の大/小文字の使用方法を変更するには、-caseオプションを使用します(オブジェクトまたはコレクションが属性の場合、つまり下位カスタムJavaクラスの場合も、このオプションを使用します)。次の4通りの設定があります。

- -case=mixed(デフォルト)
大文字になる文字は、クラス名を構成する各ワードの頭文字、属性名を構成する各ワードの頭文字およびメソッド名の2番目以降のワードの頭文字です。これ以外の文字はすべて小文字になります。JPublisherでは、アンダースコア(_)、ドル記号($)、およびJavaの識別子で無効な文字は、ワード間のセパレータとしてみなされます。これらの文字は処理時に破棄されます。

- -case=same
大/小文字区別は、データベース内での表現と同じになります。アンダースコアとドル記号は保持され、無効な文字は破棄されます。

- -case=upper
小文字が大文字に変換されます。アンダースコアとドル記号は保持され、無効な文字は破棄されます。

- -case=lower
大文字が小文字に変換されます。アンダースコアとドル記号は保持され、無効な文字は破棄されます。

注意:
JPublisherの実行時にJavaにマッピングするユーザー定義型を指定しないと、スキーマ内のすべてのユーザー定義型が処理されます。最上位カスタム・クラスとその他のクラス(オブジェクトの属性またはコレクションの要素)のクラス名は、-caseオプションに基づき生成されます。

型のマッピング指定

JPublisherには、ユーザー定義型およびその属性型や要素型をSQLとJavaとの間でマッピングする方法が数通りあります。

JPublisherではSQL型が次のようなグループに分類されています。各グループに対応するJPublisherオプションは、各項に示したとおりです。

- 数値型: SQL型NUMBERとして格納されるすべての型
JPublisherの-numbertypesオプションは、数値型のマッピング指定に使用します。

- ラージ・オブジェクト(LOB)型: SQL型のBLOBおよびCLOB
JPublisherの-lobtypesオプションは、LOB型のマッピング指定に使用します。

- 組込み型: データベース内にSQL型として格納されている型のうち、前に示した分類のどれにも該当しない型(たとえば、CHAR、VARCHAR2、LONG、RAWなど)
JPublisherの-builtintypesオプションは、組込み型のマッピング指定に使用します。

JPublisherでは次の型マッピング・モードを定義します。

- JDBCマッピング(設定はjdbc): SQL型とネイティブなJava型とのマッピングに標準デフォルト・マッピング型を使用します。この設定は、-numbertypes、-lobtypesおよび-builtintypesオプションに有効です。

- Oracleマッピング(設定はoracle): SQL型へのマッピングの際に、対応するoracle.sql型を使用します。この設定は、-numbertypes、-lobtypesおよび-builtintypesオプションに有効です。

- Object JDBCマッピング(設定はobjectjdbc): JDBCマッピングをさらに拡張したマッピングです。オブジェクトJDBCマッピングでは、適切であれば、Javaプリミティブ型(int、float、doubleなど)のかわりに、標準java.langパッケージの数値オブジェクト型(java.lang.Integer、Float、Doubleなど)が使用されます。java.lang型ではNULL値が許容されますが、基本型では許容されません。この設定は、-numbertypesオプションにのみ有効です。

- BigDecimalマッピング(設定はbigdecimal): 数値属性へのマッピングの際にjava.math.BigDecimalを使用します。これは、桁数の多い数値を使用してもoracle.sql.NUMBER型は使用しない場合に適したマッピング方法です。この設定は、-numbertypesオプションにのみ有効です。

注意:
BigDecimalマッピングを使用すると、パフォーマンスが著しく劣化する場合があります。

SQLオブジェクト型や要素型の属性型に対してマッピング指定を省略すると、JPublisherでは次のデフォルトが使用されます。

- 数値型のデフォルトは、Object JDBCマッピングです。

- LOB型のデフォルトは、Oracleマッピングです。

- 組込みタイプ型のデフォルトは、JDBCマッピングです。

これ以外に代替のマッピングを使用する場合は、-numbertypes、-lobtypesおよび-builtintypesオプションを使用します。どのオプションを使用するかは、処理対象とする属性型およびマッピングに応じて決めてください。

属性型自体がSQLオブジェクト型である場合には、-usertypes設定値に基づいてマッピングされます。

注意:
カスタム・オブジェクト・クラスに対してSQLDataが実装されるように指定し、コードが移植可能であるようにする場合は、属性型に対して移植可能なマッピングを使用する必要があります。数値型または組込み型をマッピング対象とする場合はデフォルトで移植可能になりますが、LOB型の場合は-lobtypes=jdbcを指定する必要があります。

表6-1に、SQL型、マッピング設定およびデフォルト設定に関してJPublisherでの分類をカテゴリ別にまとめます。

表6-1 JPublisherでのSQL型の分類、サポートされている設定およびデフォルト

SQL型の分類

JPublisherマッピング・オプション

マッピング設定

デフォルト

UDT型

-usertypes

oracle、jdbc

oracle

数値型

-numbertypes

oracle、jdbc、objectjdbc、bigdecimal

objectjdbc

LOB型

-lobtypes

oracle、jdbc

oracle

組込み型

-builtintypes

oracle、jdbc

jdbc

注意:
以前のリリースで使用された-mappingオプションは、JPublisherでは非推奨ですが、サポートはされています。JPublisherの-mappingオプション設定値を新しいマッピング・オプション設定値に変換する方法の詳細は、『Oracle Database JPublisherユーザーズ・ガイド』を参照してください。

ラッパー・メソッドの生成

OracleオブジェクトをJavaにマッピングするためのカスタム・オブジェクト・クラスを作成する際、-methodsオプションは、OracleオブジェクトのメソッドにJavaラッパーを含めるかどうかをJPublisherに指示します。デフォルトの-methods=true設定では、ラッパーが生成され、JPublisherではカスタム・オブジェクト・クラス用に.javaファイルではなく.sqljファイルが生成されます(ただし、基になるSQLオブジェクトに実際にメソッドない場合を除きます)。

JPublisherでラッパー・メソッドを生成すると、元のオブジェクト・メソッドがstaticでも、必ずインスタンス・メソッドになります。次に、-methodsオプションの設定例を示します。

% jpub -sql=Myobj,mycoll:MyCollClass -user=scott -methods=true
Enter scott password: password

この例では、デフォルトのネーミング・メソッドが使用されます。Javaのメソッド名は、最初の文字が小文字になる他は、カスタムJavaクラス名と同じ方法でネーミングされます。たとえば、オブジェクトのメソッド名CALC_SALは、デフォルトでJavaのラッパー・メソッド名calcSal()になります。かわりにJavaのメソッド名を指定することも可能ですが、この場合は、JPublisherのINPUTファイルを使用する必要があります。

注意:
-methodsオプションには他の用途もあり、例としては、パッケージのラッパー・クラスやパッケージのメソッドのラッパー・メソッドの生成に使用できます。この内容はこのマニュアルの対象外です。詳細は、『Oracle Database JPublisherユーザーズ・ガイド』を参照してください。

オーバーロード・メソッドについて

JPublisherの実行対象のOracleオブジェクトにオーバーロード・メソッドがあり、複数のシグネチャが同一のJavaシグネチャに対応する場合は、シグネチャごとに一意なメソッド名が生成されます。つまり、ファンクション名の後ろに_n が付けられます(n は番号です)。生成されたカスタムJavaクラスの2つのメソッドは、それぞれ一意な名前とシグネチャになります。一例として、MY_TYPEオブジェクト型の生成時に定義されるSQLファンクションについて考えます。

CREATE OR REPLACE TYPE my_type AS OBJECT
(
...

MEMBER FUNCTION myfunc(x INTEGER)
RETURN my_return IS
BEGIN
...
END;

MEMBER FUNCTION myfunc(y SMALLINT)
RETURN my_return IS
BEGIN
...
END;
...
);

このままでは、myfuncの定義は両方とも、Java形式の名前とシグネチャになります。

myfunc(Integer)

その理由は、SQL形式のINTEGERおよびSMALLINTが、Java Integer型にマッピングされているためです。

かわりに、JPublisherでは、myfunc_1ともう1つのmyfunc_2をコールします。_n はそれぞれ一意です。簡単な例では、_1、_2のようになりますが、各ファンクションに一意の値ではなく、任意の値でもかまいません。

注意:
オーバーロードしたラッパー・メソッドに対するJPublisherでの処理は、オブジェクトやパッケージ内で作成されたSQLファンクションに対しても実行されます。最上位レベルではオーバーロードが許容されません。

カスタムJavaクラスの生成および代替クラスのマッピング

JPublisherでは、カスタムJavaクラスを生成できる他、オブジェクト型またはコレクション型のマッピング先として、生成したクラスでなく代替クラスが指定できます。

通常は、JPublisherで生成したクラスをスーパークラスにし、これを拡張して機能を追加し、オブジェクト型をサブクラスにマッピングします。たとえば、Oracleオブジェクト型ADDRESSのカスタムJavaクラスを作成し、JPublisherで生成されなかった機能を追加するとします。この場合は、JPublisherでJAddressカスタムJavaクラスを生成してから、これを拡張してMyAddressクラスを作成します。専用機能をMyAddressに追加してから、JPublisherでADDRESSオブジェクトを、JAddressクラスではなく、MyAddressにマッピングします。JPublisherでは、JAddressではなく、MyAddressの参照クラスも生成できます。

JPublisherでは、代替クラスへのマッピングを容易に行えます。-sqlオプションを次の構文で指定します。

-sql=object_type:generated_class:map_class

前の例の場合は、次のように設定します。

-sql=ADDRESS:JAddress:MyAddress

この設定では、クラスJAddressがソース・ファイルJAddress.sqlj(またはJAddress.java)に作成され、次の処理が行われます。

- ADDRESSオブジェクト型のマッピング先が、JAddressクラスではなく、MyAddressクラスになります。したがって、データベースから取得したオブジェクトにADDRESS属性があると、Javaでこの属性がMyAddressのインスタンスとして生成されます。ADDRESSオブジェクトを直接取得する場合は、MyAddressインスタンスに取り込まれます。

- JAddressRefクラスではなく、MyAddressRefクラスがMyAddressRef.javaに生成されます。

- ファイルがすでに存在していないかぎり、MyAddress.sqlj(またはMyAddress.java)ソース・ファイルにMyAddressクラスの初期バージョンが生成されます。存在している場合、ファイルは変更されません。

MyAddressはJAddressにサブクラス化されます。MyAddressに対して拡張機能を実装するためには、JPublisherで生成されたMyAddressソース・ファイルを使用し、必要に応じてそのファイルを編集できます。

JPublisher生成クラスを拡張する方法(前例の続き)は、「JPublisher生成クラスの拡張」を参照してください。

JPublisherのINPUTファイルおよびプロパティ・ファイル

JPublisherでは、専用のINPUTファイルおよび標準のプロパティ・ファイルを使用して、型のマッピングなどのオプション設定を指定できます。

JPublisherのINPUTファイルの使用方法

JPublisherのコマンドライン・オプション-inputを使用して、型マッピングを追加するためのINPUTファイルをJPublisherに指定できます。INPUTファイル内のSQLは、コマンドラインの-sqlに相当し、ASまたはGENERATE...AS構文は、コマンドラインのコロン区切り構文に相当します。次の構文を使用しますが、1つのSQLコマンドに指定できるマッピングは1つだけです。

SQL udt1 <GENERATE GeneratedClass1> <AS MapClass1>
SQL udt2 <GENERATE GeneratedClass2> <AS MapClass2>
...

GeneratedClass1 とGeneratedClass2 が生成され、udt1 がMapClass1 に、udt2 がMapClass2 にマッピングされます。

注意:
ユーザー定義型が大/小文字を区別する方法でSQLに定義されている場合、引用符内に名前を指定する必要があります。次に例を示します。

SQL "CaseSenstiveType" AS CaseSensitiveType

大/小文字を区別しないスキーマ名を指定する場合も、次のようになります。

SQL SCOTT."CaseSensitiveType" AS CaseSensitiveType

または、大/小文字を区別するスキーマ名を指定する場合、次のようになります。

SQL "Scott"."CaseSensitiveType" AS CaseSensitiveType

AS句はオプションです。

スキーマ名または型名自体の一部として、ピリオド(.)を使用しないでください。

INPUTファイルの例

次の例では、JPublisherは、コマンドラインの-userオプションに基づき、INPUTファイルmyinput.inで型マッピングを調べます。

コマンドラインで次のように指定します。

% jpub -input=myinput.in -user=scott
Enter scott password: password

INPUTファイルmyinput.inの内容は次のようになります。

SQL Myobj
SQL mycoll AS MyCollClass
SQL employee GENERATE Employee AS MyEmployee

次の処理が行われます。

- ユーザー定義型MYOBJの名前は、カスタム・オブジェクト・クラスの名前として入力したMyobjになります。JPublisherでは、ソース・ファイルMyobj.sqlj(またはMyobjにメソッドがない場合はMyobj.java)およびMyobjRef.javaが作成されます。

- ユーザー定義型MYCOLLが、MyCollClassにマッピングされます。JPublisherでは、MyCollClass.javaソース・ファイルが生成されます。

- ユーザー定義型EMPLOYEEがMyEmployeeクラスにマッピングされます。JPublisherでは、ファイルがすでに存在していないかぎり、初期バージョンのMyEmployee.sqlj(または.java)に加え、ソース・ファイルEmployee.sqlj(またはEmployee.java)およびMyEmployeeRef.javaが作成されます。データベースから取得したオブジェクトにEMPLOYEE属性があると、Javaでこの属性がMyEmployeeのインスタンスとして生成されます。EMPLOYEEオブジェクトを直接取得する場合は、MyEmployeeのインスタンスに取り込まれます。MyEmployeeコードに関する責任は開発者にありますが、EMPLOYEEオブジェクトに対して特別な機能をJavaで実装するためには、JPublisherで生成したMyEmployeeソース・ファイルを利用して、そのファイルを編集できます。MyEmployeeはEmployeeクラスにサブクラス化されます。

JPublisherのプロパティ・ファイルの使用方法

JPublisherのコマンドライン・オプション-propsで、型マッピングなどのオプション設定に使用するプロパティ・ファイルを指定できます。

プロパティ・ファイルでのjpub. (ピリオドを含む)は、コマンドラインの- (シングル・ダッシュ)に相当します。その他の構文は同じです。1行に1つのオプションを指定してください。

型マッピングの場合、jpub.sqlは-sqlに相当します。単一のjpub.sql設定で複数のマッピングを指定できます。また、複数のjpub.sqlオプションを使用できます。複数の-sqlオプションが1つのコマンドラインにある場合、オプションの効果は累積されます。

注意:
jpub.または--jpub.(2つのダッシュの後にjpub.が続く)で開始しないプロパティ・ファイルの行は無視されます。これによって、型を作成するSQLスクリプトとJPublisher用のプロパティ・ファイルに同じファイルを使用できます。JPublisherの各文を「--」(SQLのコメントを示す)で開始すると、SQL*Plusでは無視されます。また、SQL文はJPublisherによって無視されます。

プロパティ・ファイルの例

次の例では、JPublisherはコマンドラインの-userオプションに基づき、プロパティ・ファイルjpub.propertiesで型マッピングと属性マッピング・オプションを調べます。

コマンドラインで次のように指定します。

% jpub -props=jpub.properties -user=scott
Enter scott password: password

プロパティ・ファイルjpub.propertiesの内容は次のとおりです。

jpub.sql=Myobj,mycoll:MyCollClass,employee:Employee:MyEmployee
jpub.usertypes=oracle

このように指定すると、oracleマッピングの設定が明示的に指定され、前の入力ファイルの例と同じ結果になります。

注意:
SQLJと異なり、JPublisherにはデフォルトのプロパティ・ファイルがありません。プロパティ・ファイルを使用するには、-propsオプションを使用します。

カスタムJavaクラスの作成およびメンバー名の指定

カスタムJavaクラスの作成時に、カスタム・クラスの属性またはメソッドの名前を指定できます。ただし、この属性やメソッド名は、JPublisherコマンドラインでの指定はできません。次のようにTRANSLATE構文を使用して、JPublisherのINPUTファイルで指定する必要があります。

SQL udt <GENERATE GeneratedClass> <AS MapClass> <TRANSLATE membername1 AS Javaname1> <, membername2 AS Javaname2> ...

TRANSLATEペア(membernameN AS JavanameN )はカンマで区切ります。

たとえば、EMPLOYEE Oracleオブジェクト型のADDRESS属性の名前をHomeAddressにし、GIVE_RAISEメソッドの名前をgiveRaise()にするとします。また、Employeeクラスを作成し、EMPLOYEEオブジェクトのマッピング先をこれから作成するMyEmployeeクラスにするとします。(この例はINPUTファイル構文の全体を示すものであり、メンバー名の指定には関係ありません。)

SQL employee GENERATE Employee AS MyEmployee
TRANSLATE address AS HomeAddress, GIVE_RAISE AS giveRaise

注意:

- メンバー名を指定すると、それ以外の指定しなかったメンバーすべてにデフォルトの名前が与えられます。

- 属性を大文字(homeAddressではなくHomeAddress)で指定する理由は、アクセッサ・メソッドと同じネーミング規則が適用されるためです。たとえば、getHomeAddress()はネーミング規則に従っていますが、gethomeAddress()は従っていません。

JPublisherで生成されるラッパー・メソッド

ここでは、JPublisherでのラッパー・メソッドの生成方法と、ランタイムのラッパー・メソッド・コールの処理方法を説明します。

ラッパー・メソッドの生成

次に、JPublisherでのラッパー・メソッドの生成方法について説明します。

- JPublisherで生成したラッパー・メソッドは、SQLJで実装されます。したがって、-methods=trueに設定すると、オブジェクト型でメソッドを定義している場合は、カスタム・オブジェクト・クラスが、.javaファイルではなく、.sqljファイルに定義されます。.sqljファイルを変換するには、SQLJを実行します。

注意:
オブジェクト型でメソッドを定義していない場合でも、-methods=alwaysの設定で.sqljファイルが生成されることを確認できます。詳細は、『Oracle Database JPublisherユーザーズ・ガイド』を参照してください。

- JPublisherで生成したラッパー・メソッドは、すべてインスタンス・メソッドとして実装されます。サーバー側メソッドの起動にデータベース接続を必要とするからです。JPublisher生成のカスタムJavaクラスの各インスタンスに接続が対応付けられます。

ラッパー・メソッド・コールのランタイム実行

JPublisherで生成したJavaラッパー・メソッドをランタイムに実行する方法を説明します。ここで取り上げるJavaラッパー・メソッドとは、カスタムJavaオブジェクトのメソッドのことを指していますが、SQLメソッドのラッピングとは、SQLオブジェクトのメソッドをラッパー・メソッドでラッピングすることを指します。

- カスタムJavaオブジェクトがSQLオブジェクトに変換され、データベースに渡されると、ラッピングされたSQLメソッドが起動されます。このSQLメソッドの起動後、SQLオブジェクトの新しい値が戻り値として新規のカスタムJavaオブジェクトの形でJavaに戻されます。この戻り値は、ラッピングされたSQLメソッドからのファンクション戻り値(SQLメソッドがストアド・プロシージャの場合)、または追加の出力パラメータの配列要素(SQLメソッドがストアド・ファンクションで、ファンクション戻り値がすでに存在している場合)のどちらかになります。

- 出力または入出力パラメータが単一要素配列の要素として渡されます。入出力パラメータの場合は、ラッパー・メソッドが入力として配列要素をとります。処理後、ラッパーによって出力が配列要素に代入されます。

JPublisherのカスタムJavaクラスの例

ここでは、次のユーザー定義型に対して、JPublisherで生成されるORAData実装の例を示します。

- カスタム・オブジェクト・クラス(Oracleのオブジェクト型 ADDRESSに対応するAddress)とそのカスタム参照クラス(AddressRef)

- カスタム・コレクション・クラス(Oracleのコレクション型MODULETBL_Tに対応するMODULETBL_T)

-methodsオプションがデフォルトのtrueに設定されており、ADDRESS型にメソッドがあるとします。この結果、.sqljファイルがAddressクラスに対して生成されます。

関連項目:
JPublisherで生成されるSQLDataおよびORAData実装の各例については、『Oracle Database JPublisherユーザーズ・ガイド』を参照してください。

カスタム・オブジェクト・クラス: Address.sqlj

次に、JPublisherで生成されるカスタム・オブジェクト・クラスのソース・コードの例を示します。実装の詳細は省略されています。

この例では、「オブジェクト型の作成」と異なり、OracleオブジェクトADDRESSの属性はstreetとzip_codeのみです。

package bar;

import java.sql.SQLException;
import java.sql.Connection;
import oracle.jdbc.OracleTypes;
import oracle.sql.ORAData;
import oracle.sql.ORADataFactory;
import oracle.sql.Datum;
import oracle.sql.STRUCT;
import oracle.jpub.MutableStruct;

public class Address implements ORAData, ORADataFactory
{
public static final String _SQL_NAME = "SCOTT.ADDRESS";
public static final int _SQL_TYPECODE = OracleTypes.STRUCT;

public static ORADataFactory getORADataFactory()
{ ... }

/* constructors */
public Address()
{ ... }

public Address(String street, java.math.BigDecimal zip_code)
throws SQLException
{ ... }

/* ORAData interface */
public Datum toDatum(Connection c) throws SQLException
{ ... }

/* ORADataFactory interface */
public ORAData create(Datum d, int sqlType) throws SQLException
{ ... }

/* accessor methods */
public String getStreet() throws SQLException
{ ... }

public void setStreet(String street) throws SQLException
{ ... }

public java.math.BigDecimal getZipCode() throws SQLException
{ ... }

public void setZipCode(java.math.BigDecimal zip_code) throws SQLException
{ ... }

}

カスタム参照クラス: AddressRef.java

次に、ADDRESSオブジェクトへの参照としてJPublisherで生成されるカスタム参照クラスのソース・コードの例を示します。実装の詳細は省略されています。

package bar;

import java.sql.SQLException;
import java.sql.Connection;
import oracle.jdbc.OracleTypes;
import oracle.sql.ORAData;
import oracle.sql.ORADataFactory;
import oracle.sql.Datum;
import oracle.sql.REF;
import oracle.sql.STRUCT;

public class AddressRef implements ORAData, ORADataFactory
{
public static final String _SQL_BASETYPE = "SCOTT.ADDRESS";
public static final int _SQL_TYPECODE = OracleTypes.REF;

public static ORADataFactory getORADataFactory()
{ ... }

/* constructors */
public AddressRef()
{ ... }

public static AddressRef(ORAData o) throws SQLException
{ ... }

/* ORAData interface */
public Datum toDatum(Connection c) throws SQLException
{ ... }

/* ORADataFactory interface */
public ORAData create(Datum d, int sqlType) throws SQLException
{ ... }

public static AddressRef cast(ORAData o) throws SQLException
{ ... }

public Address getValue() throws SQLException
{ ... }

public void setValue(Address c) throws SQLException
{ ... }
}

カスタム・コレクション・クラス: ModuletblT.java

次に、JPublisherで生成されるカスタム・コレクション・クラスのソース・コードの例を示します。実装の詳細は省略されています。

import java.sql.SQLException;
import java.sql.Connection;
import oracle.jdbc.OracleTypes;
import oracle.sql.ORAData;
import oracle.sql.ORADataFactory;
import oracle.sql.Datum;
import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;
import oracle.jpub.runtime.MutableArray;

public class ModuletblT implements ORAData, ORADataFactory
{
public static final String _SQL_NAME = "SCOTT.MODULETBL_T";
public static final int _SQL_TYPECODE = OracleTypes.ARRAY;

public static ORADataFactory getORADataFactory()
{ ... }

/* constructors */
public ModuletblT()
{ ... }

public ModuletblT(ModuleT[] a)
{ ... }

/* ORAData interface */
public Datum toDatum(Connection c) throws SQLException
{ ... }

/* ORADataFactory interface */
public ORAData create(Datum d, int sqlType) throws SQLException
{ ... }

public String getBaseTypeName() throws SQLException
{ ... }

public int getBaseType() throws SQLException
{ ... }

public ArrayDescriptor getDescriptor() throws SQLException
{ ... }

/* array accessor methods */
public ModuleT[] getArray() throws SQLException
{ ... }

public void setArray(ModuleT[] a) throws SQLException
{ ... }

public ModuleT[] getArray(long index, int count) throws SQLException
{ ... }

public void setArray(ModuleT[] a, long index) throws SQLException
{ ... }

public ModuleT getObjectElement(long index) throws SQLException
{ ... }

public void setElement(ModuleT a, long index) throws SQLException
{ ... }
}

JPublisher生成クラスの拡張

JPublisherで生成したカスタムJavaクラスは、メソッドと一時フィールドを追加して、機能を拡張できます。このためには、JPublisher生成クラスを拡張します。

たとえば、JPublisherで、ADDRESS SQLのオブジェクト型からJAddressクラスを生成するとします。また、ADDRESSオブジェクトを表すMyAddressクラスを使用し、特別な機能を実装します。このMyAddressクラスは、JAddressの拡張クラスとする必要があります。

JPublisher生成クラスの機能を拡張する場合は、単にメソッドを追加する方法もあります。ただし、クラスをJPublisherで再生成する予定がある場合は、JPublisher生成クラスへのメソッドの追加は避けてください。この方法で変更したクラスをJPublisherで再生成する場合は、コピーを保存しておき、変更内容を手動でマージする必要があります。

生成クラスを拡張するためのJPublisherの機能

次のJPublisherの構文でJAddressを生成し、MyAddressにマッピングできます。

-sql=ADDRESS:JAddress:MyAddress

または、INPUTファイルで次のように指定します。

SQL ADDRESS GENERATE JAddress AS MyAddress

このように指定した結果、JPublisherで生成される参照クラスは、MyAddressRef.javaのMyAddressRefであって、JAddressRefが生成されることはありません。

また、JPublisher生成コードが変更され、次の機能が実装されます。

- SQL型ADDRESSの属性は、JAddressクラスではなく、MyAddressクラスで表されます。

- ADDRESS型のメソッド引数およびファンクション結果は、JAddressクラスではなく、MyAddressクラスで表されます。

- SQL型ADDRESSのJavaオブジェクトは、JAddressファクトリではなく、MyAddressファクトリで構築されます。

追加コードを作成する場合も、おそらくMyAddressを使用することになります。

実行時にOracle JDBCドライバによって、データベース内のADDRESSデータのオカレンスが、JAddressのインスタンスではなく、MyAddressのインスタンスにマッピングされます。

拡張クラスの要件

JPublisherではデフォルトの場合、作成されるファイルがすでに存在していないかぎり、MyAddress.sqljファイル(元のクラスがメソッドを使用し、これらのメソッドを公開している場合)またはMyAddress.javaファイルに、初期バージョンのMyAddressユーザー・サブクラスが作成されます(ファイルがすでに存在している場合、ファイルは変更されません)。このファイルは、必要な機能を追加するために編集できます。

MyAddressには、引数を持たないコンストラクタを用意する必要があります。適切に初期化したオブジェクトを容易に構築するには、スーパークラスのコンストラクタを明示的にまたは暗黙的に起動します。

JPublisher生成クラスを拡張した場合、_SQL_NAMEフィールド(必須)の定義と_SQL_TYPECODEフィールドの定義がサブクラスに継承されます。

また、次のどちらかが当てはまります。

- JPublisherで生成したクラスには、ORADataおよびORADataFactoryインタフェースが実装されているため、必要とされるtoDatum()およびJPublisherで生成されたクラスのcreate()機能がサブクラスに継承されます。ただし、サブクラスには、自分でマッピングしたクラスのインスタンス(MyAddressオブジェクトなど)を戻り値とするgetORADataFactory()メソッドを実装します。

- JPublisherで生成したクラスにSQLDataインタフェースが実装されている場合、この実装と生成クラスのreadSQL()およびwriteSQL()機能とがサブクラスに継承されます。

JPublisher生成のカスタム・オブジェクト・クラス: JAddress.sqlj

JPublisherで生成されたJAddressクラスのコード(ORADataおよびORADataFactoryを実装する)は、AddressがJAddressに置換されることを除き、前述のAddressクラスのコードとほぼ同じです。

JPublisher生成のその他の参照クラス: MyAddressRef.java

これまでの項の例の続きとして、JPublisher生成の参照クラスMyAddressRefのコードを検討します(MyAddressクラスがADDRESSオブジェクトのマッピング先となるため、ここで取り上げるクラスはJAddressRefではありません)。また、このクラスにはORADataとORADataFactoryも実装されます。この実装は、クラス名が異なることと、アクセッサ・メソッドがAddressインスタンスではなくMyAddressインスタンスを使用することを除いて、AddressRef.javaの実装とほぼ同じです。

拡張カスタム・オブジェクト・クラス: MyAddress.sqlj

これまでの例の続きとして、JPublisherで生成されるJAddressクラスのサブクラスであるMyAddressのサンプル・コードを示します。JAddressから継承された内容は、コード中のコメントに記述してあります。実装の詳細は省略されています。

import java.sql.SQLException;
import oracle.sql.ORAData;
import oracle.sql.ORADataFactory;
import oracle.sql.Datum;
import oracle.sql.STRUCT;
import oracle.jpub.runtime.MutableStruct;

public class MyAddress extends JAddress
{
/* _SQL_NAME inherited from MyAddress */
/* _SQL_TYPECODE inherited from MyAddress */

static _myAddressFactory = new MyAddress();

public static ORADataFactory getORADataFactory()
{
return _myAddressFactory;
}

/* constructor */
public MyAddress()
{ super(); }

/* ORAData interface */
/* toDatum() inherited from JAddress */

/* ORADataFactory interface */
public ORAData create(oracle.sql.Datum d, int sqlType) throws SQLException
{ ... }

/* accessor methods inherited from JAddress */

/* Additional methods go here.  These additional methods (not shown)
are the reason that JAddress was extended.
*/
}

SQLJ実行文の強い型指定のオブジェクトと参照

Oracle SQLJ実装では、強い型指定のオブジェクトまたは参照をホスト式およびイテレータで使用して、オブジェクト・データの読込みおよび書込みを柔軟に行えます。

イテレータの場合は、カスタム・オブジェクト・クラスをイテレータの列型として使用できます。または、属性のSQLデータ型にマップしている列型を使用して、イテレータ列をオブジェクトの各属性に対応付けることができます(エクステント表と同様)。

ホスト式の場合は、カスタム・オブジェクト・クラス型またはカスタム参照クラス型のホスト変数を使用できます。または、属性のSQLデータ型にマップしている変数型を使用して、ホスト変数をオブジェクトの属性に対応付けることができます。

次に、Oracleオブジェクトの操作例を示します。SQLJ実行文のホスト変数とイテレータ列に対して、カスタム・オブジェクト・クラス、カスタム・オブジェクト・クラスの属性およびカスタム参照クラスを使用します。

次の2つの例は、オブジェクト・レベルでの操作です。

- オブジェクトとオブジェクト参照のイテレータ列への取出し

- オブジェクトの更新

「各オブジェクト属性から作成したオブジェクトの挿入」の例は、スカラー属性レベルでの操作です。

「オブジェクト参照の更新」の例は、参照による操作です。

Oracleのオブジェクト型ADDRESSおよびPERSONは、「オブジェクト型の作成」を参照してください。

オブジェクトとオブジェクト参照のイテレータ列への取出し

この例では、カスタムJavaクラスとカスタム参照クラスをイテレータの列型として使用します。ADDRESS Oracleオブジェクト型が次のように定義されているものとします。

CREATE TYPE ADDRESS AS OBJECT
(  street VARCHAR(40),
zip NUMBER );

また、EMPADDRS表が次のように定義されているものとします。この表には、ADDRESS列とADDRESS参照列があります。

CREATE TABLE empaddrs
(  name VARCHAR(60),
home ADDRESS,
loc REF ADDRESS );

ADDRESS Oracleオブジェクト型に対応するカスタムJavaクラスAddressとカスタム参照クラスAddressRefをJPublisherで生成するか、または手動で作成すると、次のようにAddressとAddressRefとを名前付きイテレータで使用できます。

#sql iterator EmpIter (String name, Address home, AddressRef loc);

...
EmpIter ecur;
#sql ecur = { SELECT name, home, loc FROM empaddrs };
while (ecur.next()) {
Address homeAddr = ecur.home();
// Print out the home address.
System.out.println ("Name: " + ecur.name() + "\n" +
"Home address: " + homeAddr.getStreet() + "   " +
homeAddr.getZip());
// Now update the loc address zip code through the address reference.
AddressRef homeRef = ecur.loc();
Address location = homeRef.getValue();
location.setZip(new BigDecimal(98765));
homeRef.setValue(location);
}
...

ecur.home()メソッド・コールは、イテレータのhome列からAddressオブジェクトを抽出し、homeAddrローカル変数に代入します(効率化)。このオブジェクトの属性にアクセスするには、次に示したJavaの標準ドット区切り構文を使用します。

homeAddr.getStreet()

ロケーション・アドレス(この例ではzipコード)を操作するには、getValue()およびsetValue()メソッドを使用します。これらのメソッドは、JPublisher生成のカスタム参照クラスの標準機能です。

注意:
次の例では、「オブジェクト型の作成」のSQLスクリプトで定義した型と表を使用します。

オブジェクトの更新

この例では、Address Java型の入力ホスト変数を宣言し、設定することで、employees表の列にあるADDRESSオブジェクトを更新します。更新前と更新後の両方で、アドレスが選択されてAddress型の出力ホスト変数に入力され、検証用に出力されます。

...
// Updating an object

static void updateObject()
{

Address addr;
Address new_addr;
int empnum = 1001;

try {
#sql {
SELECT office_addr
INTO :addr
FROM employees
WHERE empnumber = :empnum };
System.out.println("Current office address of employee 1001:");

printAddressDetails(addr);

/* Now update the street of address */

String street ="100 Oracle Parkway";
addr.setStreet(street);

/* Put updated object back into the database */

try {
#sql {
UPDATE employees
SET office_addr = :addr
WHERE empnumber = :empnum };
System.out.println
("Updated employee 1001 to new address at Oracle Parkway.");

/* Select new address to verify update */

try {
#sql {
SELECT office_addr
INTO :new_addr
FROM employees
WHERE empnumber = :empnum };

System.out.println("New office address of employee 1001:");
printAddressDetails(new_addr);

} catch (SQLException exn) {
System.out.println("Verification SELECT failed with "+exn); }

} catch (SQLException exn) {
System.out.println("UPDATE failed with "+exn); }

} catch (SQLException exn) {
System.out.println("SELECT failed with "+exn); }
}
...

AddressオブジェクトのsetStreet()アクセッサ・メソッドが使用されています。JPublisherで生成したカスタムJavaクラスには、属性ごとにアクセッサ・メソッドが用意されています。

この例では、printAddressDetails()ユーティリティを使用しています。このメソッドのソース・コードを次に示します。

static void printAddressDetails(Address a) throws SQLException
{

if (a == null)  {
System.out.println("No Address available.");
return;
}

String street = ((a.getStreet()==null) ? "NULL street" : a.getStreet()) ;
String city = (a.getCity()==null) ? "NULL city" : a.getCity();
String state = (a.getState()==null) ? "NULL state" : a.getState();
String zip_code = (a.getZipCode()==null) ? "NULL zip" : a.getZipCode();

System.out.println("Street: '" + street + "'");
System.out.println("City:   '" + city   + "'");
System.out.println("State:  '" + state  + "'");
System.out.println("Zip:    '" + zip_code + "'" );
}

各オブジェクト属性から作成したオブジェクトの挿入

この例では、PERSONオブジェクトとネストされているADDRESSオブジェクトの属性に対応する入力ホスト変数を宣言し、設定します。これらの値を使用して、新しいPERSONオブジェクトをデータベース内のpersons表に挿入します。

...
// Inserting an object

static void insertObject()
{
String new_name   = "NEW PERSON";
int    new_ssn    = 987654;
String new_street = "NEW STREET";
String new_city   = "NEW CITY";
String new_state  = "NS";
String new_zip    = "NZIP";
/*
* Insert a new PERSON object into the persons table
*/
try {
#sql {
INSERT INTO persons
VALUES (PERSON(:new_name, :new_ssn,
ADDRESS(:new_street, :new_city, :new_state, :new_zip))) };

System.out.println("Inserted PERSON object NEW PERSON.");

} catch (SQLException exn) { System.out.println("INSERT failed with "+exn); }
}
...

オブジェクト参照の更新

この例では、persons表からPERSON参照を選択し、この値を使用してemployees表内のPERSON参照を更新します。属性値の基準チェックには、単純な入力ホスト変数を使用します。新しく更新された参照を使用して、その参照先のPERSONオブジェクトを選択することで、情報を出力して、ユーザーが変更内容を検証できるようになります。

...
// Updating a REF to an object

static void updateRef()
{
int empnum = 1001;
String new_manager = "NEW PERSON";

System.out.println("Updating manager REF.");
try {
#sql {
UPDATE employees
SET manager =
(SELECT REF(p) FROM persons p WHERE p.name = :new_manager)
WHERE empnumber = :empnum };

System.out.println("Updated manager of employee 1001. Selecting back");

} catch (SQLException exn) {
System.out.println("UPDATE REF failed with "+exn); }

/* Select manager back to verify the update */
Person manager;

try {
#sql {
SELECT deref(manager)
INTO :manager
FROM employees e
WHERE empnumber = :empnum };

System.out.println("Current manager of "+empnum+":");
printPersonDetails(manager);

} catch (SQLException exn) {
System.out.println("SELECT REF failed with "+exn); }

}
...

注意:
この例では、前述の表の別名構文(p)を使用しています。また、参照先オブジェクトから参照を選択するには、REF構文が必要になり、参照からオブジェクトを選択するには、DEREF構文が必要になります。表の別名、REFおよびDEREFの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

SQLJ実行文の強い型指定のコレクション

Oracle SQLJ実装では、強い型指定のオブジェクトおよび参照と同じように、強い型指定のコレクションをイテレータまたはホスト式で使用して、データの読込みおよび書込みを行えます。

SQLJ開発者にとっては、2種類のコレクション(VARRAYとネストした表)の扱いは基本的に同じですが、実装とパフォーマンスの面で相違点が多少あります。

Oracle SQLJ実装では、構文の複数の選択肢がサポートされていて、ネストした表(内側の表)にアクセスして、操作できるようになっています(外側の表から切り離して、または外側の表と一緒に操作することも可能です)。ここでは、ネストの内側の表のみの操作を詳細レベルの操作と呼び、ネストの内側の表と外側の表の同時操作をマスター・レベルの操作と呼びます。

ここでは、いくつかの構文について簡単に説明してから、ネストした表の操作例を示します。ネストした表の操作は、VARRAYの操作より複雑です。

MODULETBL_T Oracleコレクション型と関連する表、およびオブジェクト型の定義については、「コレクション型の作成」を参照してください。

注意:
Oracle SQLJ実装では、VARRAY型およびNESTED TABLE型を型単位でのみ取得できます。これは、Oracle SQL実装とは違い、ネストした表の問合せを選択的に実行できます。

ここでは、次の項目について説明します。

- ネストした表へのアクセス: TABLE構文とCURSOR構文

- ネストした表を含む行の挿入

- ホスト式へのネストした表の取出し

- TABLE構文によるネストした表の操作

- ネスト・イテレータによるネストした表からのデータの選択

- ホスト式へのVARRAYの取出し

- VARRAY行への挿入

ネストした表へのアクセス: TABLE構文とCURSOR構文

Oracle SQLJ実装では、ネストしたイテレータを使用して、ネストした表のデータにアクセスできます。外部のSELECT文でCURSORキーワードを使用し、内部のSELECT文をカプセル化します。「ネスト・イテレータによるネストした表からのデータの選択」を参照してください。

Oracleでは、TABLEキーワードを使用すると、ネストした表を行単位で操作できます。Oracleではこのキーワードを使用すると、副問合せで戻される列値が、スカラー値ではなくネストした表であることが認識されます。単一列値を戻す副問合せまたはネストした表に解決される式の前に、TABLEキーワードを指定する必要があります。

次に、TABLE構文の使用例を示します。

UPDATE TABLE(SELECT a.modules FROM projects a WHERE a.id=555) b
SET module_owner=
(SELECT ref(p) FROM employees p WHERE p.ename= 'Smith')
WHERE b.module_name = 'Zebra';

この例のTABLEを見ると、ネストの外側の表の列から選択された、ネストの内側の単一の表を参照していることがわかります。

注意:
この例では、前述のように、表の別名構文(projectsにはa、ネストした表にはb、またemployeesにはp)が使用されています。

ネストした表を含む行の挿入

この例では、マスター・レベル(ネストの外側の表)と詳細レベル(ネストの内側の表)を同時に明示的に操作する処理を示します。ここでは、projects表に行を挿入します。この表の各行にはMODULETBL_T型のネストした表が含まれ、ネストした表にはMODULE_Tオブジェクトの行が含まれています。

最初に、スカラー値を設定し(id、name、start_date、duration)、ネストした表の値を設定します。ネストした表の要素は複数の属性を持つオブジェクトであるため、別のレベルの抽象化も行いますネストした表の値を設定するとき、ネストした表の各MODULE_Tオブジェクトに対して、各属性値を設定する必要があります。最後に、owner値(初期値null)を別の文で設定します。

// Insert Nested table details along with master details

public static void insertProject2(int id)  throws Exception
{
System.out.println("Inserting Project with Nested Table details..");
try {
#sql { INSERT INTO Projects(id,name,owner,start_date,duration, modules)
VALUES ( 600, 'Ruby', null, '10-MAY-98',  300,
moduletbl_t(module_t(6001, 'Setup ', null, '01-JAN-98', 100),
module_t(6002, 'BenchMark', null, '05-FEB-98',20) ,
module_t(6003, 'Purchase', null, '15-MAR-98', 50),
module_t(6004, 'Install', null, '15-MAR-98',44),
module_t(6005, 'Launch', null,'12-MAY-98',34))) };
} catch ( Exception e) {
System.out.println("Error:insertProject2");
e.printStackTrace();
}

// Assign project owner to this project

try {
#sql { UPDATE Projects pr
SET owner=(SELECT ref(pa) FROM participants pa WHERE pa.empno = 7698)
WHERE pr.id=600 };
} catch ( Exception e) {
System.out.println("Error:insertProject2:update");
e.printStackTrace();
}
}

ホスト式へのネストした表の取出し

この例では、ネストした表を詳細レベルで直接操作します。前述のとおり、ModuletblTは、ネストした表MODULETBL_Tに対するJPublisher生成のカスタム・コレクション・クラス(ORAData実装)であり、ModuleTはMODULE_Tオブジェクトに対するJPublisher生成のカスタム・オブジェクト・クラスです。ネストした表MODULETBL_TにはMODULE_Tオブジェクトが格納されます。

MODULE_Tオブジェクトのネストした表をprojects表のmodules列から選択し、ModuletblTホスト変数に格納します。

次に、ネストした表を含むModuletblT変数をあるメソッドに渡し、そのメソッドはgetArray()メソッドを使用して要素にアクセスします。getArray()メソッドはデータをModuleT[]配列に書き込みます。JPublisherで生成したカスタム・コレクション・クラスには、必ずgetArray()メソッドがあります。その後、このModuleT[]配列の各要素をModuleTオブジェクトにコピーし、各属性をアクセッサ・メソッド(getModuleName()など)で取得し、出力します。JPublisherで生成したカスタム・オブジェクト・クラスには、必ずこのようなアクセッサ・メソッドがあります。

static ModuletblT mymodules=null;
...

public static void getModules2(int projId)
throws Exception
{
System.out.println("Display modules for project " + projId );

try {
#sql {SELECT modules INTO :mymodules
FROM projects  WHERE id=:projId };
showArray(mymodules);
} catch(Exception e) {
System.out.println("Error:getModules2");
e.printStackTrace();
}
}

public static void showArray(ModuletblT a)
{
try {
if ( a == null )
System.out.println( "The array is null" );
else {
System.out.println( "printing ModuleTable array object of size "
+a.length());
ModuleT[] modules = a.getArray();

for (int i=0;i<modules.length; i++) {
ModuleT module = modules[i];
System.out.println("module "+module.getModuleId()+
", "+module.getModuleName()+
", "+module.getModuleStartDate()+
", "+module.getModuleDuration());
}
}
}
catch( Exception e ) {
System.out.println("Show Array");
e.printStackTrace();
}
}

TABLE構文によるネストした表の操作

この例では、TABLE構文を使用して、ネストした表を詳細レベルで操作します。マスター・レベルの基準に基づき、ネストした表の要素に直接アクセスして更新します。

assignModule()メソッドを使用すると、PROJECTS表のMODULES列からMODULE_Tオブジェクトのネストした表が選択された後、このネストして表の特定の行のMODULE_NAMEが更新されます。同様に、deleteUnownedModules()メソッドを使用すると、MODULE_Tオブジェクトのネストした表が選択され、その後でこのネストした表で所有者のいないモジュール(MODULE_OWNERがNULLのモジュール)が削除されます。

これらのメソッドでは、前述のように表の別名構文を使用します。この例では、ネストした表にm、participants表にpを使用しています。

/* assignModule
Illustrates accessing the nested table using the TABLE construct
and updating the nested table row
*/
public static void assignModule(int projId, String moduleName,
String modOwner) throws Exception
{
System.out.println("Update:Assign '"+moduleName+"' to '"+ modOwner+"'");

try {
#sql {UPDATE TABLE(SELECT modules FROM projects WHERE id=:projId) m
SET m.module_owner=
(SELECT ref(p) FROM participants p WHERE p.ename= :modOwner)
WHERE m.module_name = :moduleName };
} catch(Exception e) {
System.out.println("Error:insertModules");
e.printStackTrace();
}
}

/* deleteUnownedModules
// Demonstrates deletion of the Nested table element
*/

public static void deleteUnownedModules(int projId)
throws Exception
{
System.out.println("Deleting Unowned Modules for Project " + projId);
try {
#sql { DELETE TABLE(SELECT modules FROM projects WHERE id=:projId) m
WHERE m.module_owner IS NULL };
} catch(Exception e) {
System.out.println("Error:deleteUnownedModules");
e.printStackTrace();
}
}

ネスト・イテレータによるネストした表からのデータの選択

SQLJでは、ネストした表にアクセスする1つ方法として、ネストしたイテレータの使用があります。このためには、次の例で使用されているCURSOR構文が必要です。コードで名前付きイテレータ・クラスModuleIterを定義し、このクラスをmodules列の型として、別の名前付きイテレータ・クラスProjIterで使用します。移入されたProjIterインスタンスの中の各modules項目は、ネスト・イテレータとして表されたネストした表です。

CURSOR構文は、ネストされているSELECT文の要素であり、ネストされているイテレータを移入します。選択されたデータは、イテレータのアクセッサ・メソッドによってユーザーに出力されます。

この例では、前述のように、表の別名構文を使用します。ここでは、projects表にはaを使用し、ネストした表にはbを使用しています。

...

//  The Nested Table is accessed using the ModuleIter
//  The ModuleIter is defined as Named Iterator

#sql public static iterator ModuleIter(int moduleId ,
String moduleName ,
String moduleOwner);

// Get the Project Details using the ProjIter defined as
// Named Iterator. Notice the use of ModuleIter:

#sql public static iterator ProjIter(int id,
String name,
String owner,
Date start_date,
ModuleIter modules);

...

public static void listAllProjects() throws SQLException
{
System.out.println("Listing projects...");

// Instantiate and initialize the iterators

ProjIter projs = null;
ModuleIter  mods = null;
#sql projs = {SELECT a.id,
a.name,
initcap(a.owner.ename) as "owner",
a.start_date,
CURSOR (
SELECT b.module_id AS "moduleId",
b.module_name AS "moduleName",
initcap(b.module_owner.ename) AS "moduleOwner"
FROM TABLE(a.modules) b) AS "modules"
FROM projects a };

// Display Project Details

while (projs.next()) {
System.out.println( "\n'" + projs.name() + "' Project Id:"
+ projs.id() + " is owned by " +"'"+ projs.owner() +"'"
+ " start on "
+ projs.start_date());

// Notice the modules from the ProjIter are assigned to the module
// iterator variable

mods = projs.modules();
System.out.println ("Modules in this Project are : ");

// Display Module details

while(mods.next()) {
System.out.println ("  "+ mods.moduleId() + " '"+
mods.moduleName() + "' owner is '" +
mods.moduleOwner()+"'" );
}                    // end of modules
mods.close();
}                      // end of projects
projs.close();
}

ホスト式へのVARRAYの取出し

ここでは、VARRAYをホスト式に取り出す例を示します。次のSQL定義を想定します。

CREATE TYPE PHONE_ARRAY IS VARRAY (10) OF varchar2(30)
/
/*** Create ADDRESS UDT ***/
CREATE TYPE ADDRESS AS OBJECT
(
street        VARCHAR(60),
city          VARCHAR(30),
state         CHAR(2),
zip_code      CHAR(5)
)
/
/*** Create PERSON UDT containing an embedded ADDRESS UDT ***/
CREATE TYPE PERSON AS OBJECT
(
name    VARCHAR(30),
ssn     NUMBER,
addr    ADDRESS
)
/

CREATE TABLE  employees
( empnumber            INTEGER PRIMARY KEY,
person_data     REF  person,
manager         REF  person,
office_addr          address,
salary               NUMBER,
phone_nums           phone_array
)
/

PHONE_ARRAY SQL型からマッピングするPhoneArrayカスタム・コレクション・クラスを、JPublisherで生成するとします。

次のメソッドでこの表から行を選択し、データをPhoneArray型のホスト変数に格納します。

private static void selectVarray() throws SQLException
{
PhoneArray ph;
#sql {select phone_nums into :ph from employees where empnumber=2001};
System.out.println(
"there are "+ph.length()+" phone numbers in the PhoneArray.  They are:");

String [] pharr = ph.getArray();
for (int i=0;i<pharr.length;++i)
System.out.println(pharr[i]);
}

VARRAY行への挿入

ここでは、ホスト式からVARRAYにデータを挿入する例を示します。前例と同じSQL定義とカスタム・コレクション・クラス(PhoneArray)を使用します。

次のメソッドはPhoneArrayインスタンスを定義し、ホスト変数として使用して、データをデータベース内のVARRAYに挿入します。

// creates a varray object of PhoneArray and inserts it into a new row
private static void insertVarray() throws SQLException
{
PhoneArray phForInsert = consUpPhoneArray();
// clean up from previous demo runs
#sql {delete from employees where empnumber=2001};
// insert the PhoneArray object
#sql {insert into employees (empnumber, phone_nums)
values(2001, :phForInsert)};
}

private static PhoneArray consUpPhoneArray()
{
String [] strarr = new String[3];
strarr[0] = "(510) 555.1111";
strarr[1] = "(617) 555.2222";
strarr[2] = "(650) 555.3333";
return new PhoneArray(strarr);
}

シリアライズされたJavaオブジェクト

Javaオブジェクトのインスタンスをデータベースとの間で読み書きする場合、Javaクラスに対応するSQLオブジェクト型を定義して、前述のカスタムJavaクラスのマッピング機構を使用すると、利便性が高まることがあります。これによって、Javaオブジェクトへの完全なSQL問合せが可能になります。

ただし、RAWまたはBLOB型のデータベース列を使用して、Javaオブジェクトをそのまま格納した後で取り出す場合もあります。このためには、2つの方法があります。

- 標準でない型マップの拡張機能を使用するか、型コード・フィールドをシリアライズ可能なクラスに追加することによって、シリアライズ可能なJavaクラスをRAWまたはBLOB列にマップできます。これにより、RAWまたはBLOBとしてシリアライズ可能なクラスのインスタンスを格納できます。

- ORAData機能を使用して、RAWまたはBLOB列に格納できるインスタンスを持つ、シリアライズ可能なラッパー・クラスを定義できます。

これらの方法で実行するシリアライズは、Oracle SQLJランタイム・ライブラリのみ対象です。

ここでは、次の項目について説明します。

- RAWおよびBLOB列に対するJavaクラスのシリアライズ

- SerializableDatum: ORADataの実装

- SQLJアプリケーションのSerializableDatum

- SerializableDatum(クラス全体)

RAWおよびBLOB列に対するJavaクラスのシリアライズ

RAW列またはBLOB列内に直接Javaクラスのインスタンスを格納する場合は、SQLとJavaのマッピングを指定する非標準要件を満たす必要があります。SQLJ文内では、組込み型のように透過的に、シリアライズ可能なJavaオブジェクトを読み書きできます。

SQLとJavaのマッピングを指定する場合、2つのオプションがあります。

- 型マップを接続コンテキスト宣言で宣言して、この型マップでマッピングを指定します。

- public static finalフィールド_SQL_TYPECODEを使用して、マッピングを指定します。

シリアライズ可能なクラスに対する型マップの定義

SAddress、pack.SPersonおよびpack.Manager.InnerSPM(InnerSPMはManagerの内部クラスです)がシリアライズ可能なJavaクラスであるとします。つまり、これらのクラスはjava.io.Serializableインタフェースを実装します。

このクラスは、宣言済の接続コンテキスト型の明示的接続コンテキスト・インスタンスを使用する文でのみ採用する必要があります。次のSerContextがその例です。

SAddress               a =...;
pack.SPerson           p =...;
pack.Manager.InnerSPM pm =...;
SerContext ctx = new SerContext(url,user,pwd,false);
#sql [ctx] { ... :a ... :OUT p ... :INOUT pm ... };

この場合の要件を次に示します。

- 接続コンテキスト型は、java.util.PropertyResourceBundleを実装している関連クラスを指定するwith句のtypeMap属性で宣言されている必要があります。例では、SerContextが次のように宣言されています。

#sql public static context SerContext with (typeMap="SerMap");

- 型マップ・リソースはRAW列またはBLOB列から、シリアライズ可能なJavaクラスまで、非標準マッピングを提供する必要があります。このマッピングは、次の形式のエントリで指定しますが、JavaクラスがRAWとBLOBのどちらの列にマップされているかによって形式が異なります。

oracle-class.java_class_name=JAVA_OBJECT RAW
oracle-class.java_class_name=JAVA_OBJECT BLOB

キーワードoracle-classは、これがOracle固有の拡張機能であることを示しています。例では、SerMap.propertiesリソース・ファイルには次のエントリが含まれます。

oracle-class.SAddress=JAVA_OBJECT RAW
oracle-class.pack.SPerson=JAVA_OBJECT BLOB
oracle-class.packManager$InnerSPM=JAVA_OBJECT RAW

パッケージとクラス名の分割にはピリオド(.)を使用しますが、内部クラス名を分割するにはドル記号($)を使用する必要があります。

このOracle固有の拡張機能は、標準SQLData型マップ・エントリと同じ型マップ・リソースに配置できます。

フィールド使用によるシリアライズ可能クラスのマッピングの指定

シリアライズ可能クラスに型マップを使用する別の方法として、シリアライズ可能クラスのstaticフィールドを使用して、型マッピングを指定できます。前述の例のSAddressおよびSPersonクラスなど、java.io.Serializableインタフェースを実装するクラスに次のフィールドのいずれかを追加できます。

public final static int _SQL_TYPECODE = oracle.jdbc.OracleTypes.RAW;

public final static int _SQL_TYPECODE = oracle.jdbc.OracleTypes.BLOB;

注意:
手動でのクラスへの_SQL_TYPECODEフィールド追加は、型マップ機能の使用に置き換えられました。

Javaオブジェクトのシリアライズにおける制限

シリアライズの効果について、認識しておく必要があります。2つのオブジェクトAおよびBが同じオブジェクトCを共有している場合、AおよびBは、そのシリアライズとその後のシリアライズ解除の際に、オブジェクトCのそれぞれのクローンをポイントすることになります。共有は解除されます。

さらに、与えられたJavaクラスに対して宣言できるシリアライズは、RAWまたはBLOBの1種類のみです。SQLJトランスレータは、実際の使用方法がRAWまたはBLOBのいずれかに適合することのみをチェックします。

RAW列では、サイズが制限されています。シリアライズしたJavaオブジェクトが、列のサイズを超えると、ランタイム・エラーが発生します。

BLOB列の列サイズ制限がより緩やかです。シリアライズされたJavaオブジェクトのBLOB列への書込みは、Oracle JDBC Oracle Call Interface(OCI)ドライバおよびOracle JDBC Thinドライバでサポートされます。BLOB列からのシリアライズされたオブジェクトの取得は、Oracle9i 以上のすべてのOracle JDBCドライバでサポートされています。

最後に、シリアライズされたJavaオブジェクトをこの方法で処理することは、Oracle固有の拡張機能であり、Oracle SQLJランタイムと、デフォルトのOracle固有コード生成(変換時の-codegen=oracle)またはISO標準コード生成(-codegen=iso)の場合はOracle固有のプロファイルのカスタマイズが必要です。

注意:
この特定のシリアライズ・メカニズムの実装では、JDBC型マップは使用しません。BLOBまたはRAWに対するマップは、変換時にカスタマイズされたOracleのプロファイルにハードコードされるか、Javaコードに直接生成されます。

SerializableDatum: ORADataの実装

oracle.sql.STRUCT、oracle.sql.REFまたはoracle.sql.ARRAY以外のoracle.sql.*型にマッピングするカスタムJavaクラスの定義例は、「ORAData実装のその他の使用例」を参照してください。

RAWフィールドに対してJavaオブジェクトのシリアライズおよびシリアライズ解除を行う場合の例では、カスタムJavaクラスをoracle.sql.RAW型にマッピングしています。これは、BLOBフィールドにも同様に当てはまり、カスタムJavaクラスをoracle.sql.BLOB型にマッピングします。

ここでは、このようなアプリケーションの例として、ORADataインタフェースを実装し、汎用形式のカスタムJavaクラスに準拠するSerializableDatumクラスの作成について説明します。この例では、SerializableDatumの開発手順を詳細に示してから、サンプル・コード全体を示します。

注意:
このアプリケーションでは、java.io、java.sql、oracle.sqlおよびoracle.jdbcパッケージのクラスを使用しています。インポート文はここには含まれていません。

1. まず、このクラスのスケルトンから始めます。

public class SerializableDatum implements ORAData
{
// Client methods for constructing and accessing the Java object

public Datum toDatum(java.sql.Connection c) throws SQLException
{
// Implementation of toDatum()
}

public static ORADataFactory getORADataFactory()
{
return FACTORY;
}

private static final ORADataFactory FACTORY =
// Implementation of an ORADataFactory for SerializableDatum

// Construction of SerializableDatum from oracle.sql.RAW

public static final int _SQL_TYPECODE = OracleTypes.RAW;
}

SerializableDatum自体では、ORADataFactoryインタフェースが実装されることはありませんが、このクラスのgetORADataFactory()メソッドを使用すると、このインタフェースを実装したstaticメンバーが戻されます。

_SQL_TYPECODEを、OracleTypes.RAWに設定します(データベースに対する読取りおよび書込みに使用されるデータ型であるため)。SQLJトランスレータは、この型コード情報に基づき、オンラインで型チェックを行い、ユーザー定義のJava型とSQL型間の互換性を検証します。

2. 次の処理を行うクライアント・メソッドを定義します。

- SerializableDatumオブジェクトの作成

- SerializableDatumオブジェクトの設定

- SerializableDatumオブジェクトからのデータの取得

// Client methods for constructing and accessing a SerializableDatum

private Object m_data;
public SerializableDatum()
{
m_data = null;
}
public void setData(Object data)
{
m_data = data;
}
public Object getData()
{
return m_data;
}

3. toDatum()メソッドを実装して、SerializableDatumオブジェクトからoracle.sql.RAWオブジェクトへデータをシリアライズします。toDatum()の実装では、m_dataフィールドのオブジェクトをoracle.sql.RAWインスタンスとしてシリアライズした表現で戻す必要があります。

// Implementation of toDatum()

try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(m_data);
oos.close();
return new RAW(os.toByteArray());
} catch (Exception e) {
throw new SQLException("SerializableDatum.toDatum: "+e.toString()); }

4. oracle.sql.RAWオブジェクトからSerializableDatumオブジェクトへのデータ変換を実装します。この段階で、データをシリアライズ解除します。

// Constructing SerializableDatum from oracle.sql.RAW

private SerializableDatum(RAW raw) throws SQLException
{
try {
InputStream rawStream = new ByteArrayInputStream(raw.getBytes());
ObjectInputStream is = new ObjectInputStream(rawStream);
m_data = is.readObject();
is.close();
} catch (Exception e) {
throw new SQLException("SerializableDatum.create: "+e.toString()); }
}

5. ORADataFactoryを実装します。この例では、無名クラスとして実装します。

// Implementation of an ORADataFactory for SerializableDatum

new ORADataFactory()
{
public ORAData create(Datum d, int sqlCode) throws SQLException
{
if (sqlCode != _SQL_TYPECODE)
{
throw new SQLException
("SerializableDatum: invalid SQL type "+sqlCode);
}
return (d==null) ? null : new SerializableDatum((RAW)d);
}
};

SQLJアプリケーションのSerializableDatum

ここでは、前項で作成したSerializableDatumクラスのインスタンスをホスト変数およびイテレータ列として、SQLJアプリケーションで使用する方法を示します。

次の表定義を想定します。

CREATE TABLE PERSONDATA (NAME VARCHAR2(20) NOT NULL, INFO RAW(2000));

ホスト変数としてのSerializableDatum

次に、SerializableDatumインスタンスをホスト変数として使用します。

...
SerializableDatum pinfo = new SerializableDatum();
pinfo.setData (
new Object[] {"Some objects", new Integer(51), new Double(1234.27) } );
String pname = "MILLER";
#sql { INSERT INTO persondata VALUES(:pname, :pinfo) };
...

イテレータ列としてのSerializableDatum

次に、SerializableDatumを名前付きイテレータの列として使用する例を示します。

#sql iterator PersonIter (SerializableDatum info, String name);

...
PersonIter pcur;
#sql pcur = { SELECT * FROM persondata WHERE info IS NOT NULL };
while (pcur.next())
{
System.out.println("Name:" + pcur.name() + " Info:" + pcur.info());
}
pcur.close();
...

SerializableDatum(クラス全体)

次に、前項で詳細手順を示したSerializableDatumクラスのすべてのコードを示します。

import java.io.*;
import java.sql.*;
import oracle.sql.*;
import oracle.jdbc.*;

public class SerializableDatum implements ORAData
{
// Client methods for constructing and accessing a SerializableDatum

private Object m_data;
public SerializableDatum()
{
m_data = null;
}
public void setData(Object data)
{
m_data = data;
}
public Object getData()
{
return m_data;
}

// Implementation of toDatum()

public Datum toDatum(Connection c) throws SQLException
{

try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(m_data);
oos.close();
return new RAW(os.toByteArray());
} catch (Exception e) {
throw new SQLException("SerializableDatum.toDatum: "+e.toString()); }
}

public static ORADataFactory getORADataFactory()
{
return FACTORY;
}

// Implementation of an ORADataFactory for SerializableDatum

private static final ORADataFactory FACTORY =

new ORADataFactory()
{
public ORAData create(Datum d, int sqlCode) throws SQLException
{
if (sqlCode != _SQL_TYPECODE)
{
throw new SQLException(
"SerializableDatum: invalid SQL type "+sqlCode);
}
return (d==null) ? null : new SerializableDatum((RAW)d);
}
};

// Constructing SerializableDatum from oracle.sql.RAW

private SerializableDatum(RAW raw) throws SQLException
{
try {
InputStream rawStream = new ByteArrayInputStream(raw.getBytes());
ObjectInputStream is = new ObjectInputStream(rawStream);
m_data = is.readObject();
is.close();
} catch (Exception e) {
throw new SQLException("SerializableDatum.create: "+e.toString()); }
}

public static final int _SQL_TYPECODE = OracleTypes.RAW;
}

弱い型指定のオブジェクト、参照およびコレクション

SQLJでは、弱い型指定のオブジェクト、参照およびコレクションを使用できます。これらのクラスの使用は一般的には推奨されておらず、使用方法も制限されますが、便利な場合もあります。たとえば、汎用コードを記述して、どのようなSTRUCTまたはREFでも使用できます。

ここでは、次の項目について説明します。

- 弱い型指定のオブジェクト、参照およびコレクションのサポート

- 弱い型指定のオブジェクト、参照およびコレクションの使用制限

弱い型指定のオブジェクト、参照およびコレクションのサポート

Oracleのオブジェクト、参照またはコレクションをSQLJアプリケーションで使用する場合は、強い型指定のカスタム・オブジェクト・クラス、参照クラスまたはコレクション・クラス(ORADataインタフェースを実装したクラス)または強い型指定のカスタム・オブジェクト・クラス(SQLDataインタフェースを実装したクラス)を使用するかわりに、弱い型指定の汎用java.sqlインスタンスまたはoracle.sqlインスタンスを使用できます。ただし、SQLData実装をカスタム・オブジェクト・クラスとして使用した場合、弱い型指定のカスタム参照インスタンスしか使用できません。

Oracle SQLJ実装では、イテレータ列またはホスト式に対して、次に示した弱い型指定を使用できます。

- java.sql.Structまたはoracle.sql.STRUCT(オブジェクトの場合)

- java.sql.Refまたはoracle.sql.REF(オブジェクト参照の場合)

- java.sql.Arrayまたはoracle.sql.ARRAY(コレクションの場合)

ホスト式の場合は、次の方法で使用できます。

- 入力ホスト式として

- INTOリストで出力ホスト式として

こうした弱い型指定は、通常は使用しないようにしてください。SQLJの強い型指定のパラダイムのあらゆるメリットが損なわれるためです。

STRUCTオブジェクト内の各属性またはARRAYオブジェクト内の各要素がoracle.sql.Datumオブジェクトに格納されます。基礎となるデータの形式は、Datumの適切なoracle.sql.*サブタイプ(oracle.sql.NUMBERやoracle.sql.CHARなど)です。STRUCTオブジェクト内の属性は匿名です。STRUCTおよびARRAYクラスは汎用クラスであるため、これらのクラスのインスタンスに対してオブジェクトまたはコレクションの読取りや書込みを行う際は、SQLJで型チェックを行うことはできません。

一般的には、オブジェクト、参照およびコレクションに対してカスタムJavaクラスの使用をお薦めします。可能な場合は、JPublisherで生成したクラスを使用してください。

弱い型指定のオブジェクト、参照およびコレクションの使用制限

弱い型指定のオブジェクト(StructまたはSTRUCTインスタンス)、参照(RefまたはREFのインスタンス)、またはコレクション(ArrayまたはARRAYのインスタンス)は、次の状況では、ホスト式では使用できません。

- INパラメータとして(NULLの場合)

- ストアド・プロシージャまたはストアド・ファンクションのコールで、OUTまたはINOUTパラメータとして

- ストアド・ファンクションの結果式で、OUTパラメータとして

これらのパラメータとして使用できない理由は、元のSQL型の名前(Personなど)を特定できないからです。Oracle JDBCドライバは、元のSQL型の名前を使用して、Javaのユーザー定義型のインスタンスを生成します。

Oracle OPAQUE型

Oracle OPAQUE型は抽象データ型です。単なる一連のバイトとして実装されたデータの場合、内部表現は公開されません。通常、OPAQUE型はOracleで提供され、カスタマによる実装はありません。

OPAQUE型は、基本的な点でオブジェクト型に類似しています。つまり、staticメソッド、インスタンスおよびインスタンス・メソッドの概念が類似しています。一般的に、状態や内部バイト表現を操作できるのは、OPAQUE型を使用して提供されるメソッドのみです。Javaでは、oracle.sql.OPAQUEとして、またはoracle.sql.ORADataインタフェースを実装しているカスタム・クラスとして、OPAQUE型を表現できます。クライアント側では、Javaコードを実装してバイトを操作できます(バイト・パターンが判明していることが前提です)。Oracle Database 11g JPublisherユーティリティを使用すると、このようにORADataを実装するカスタム・クラスを作成して、データベースへのラウンドトリップを繰り返すことなくデータを操作できます。

関連項目:
『Oracle Database JPublisherユーザーズ・ガイド』

OPAQUE型の主な例は、Oracle Database 11g で提供しているXMLTypeです。Oracleが提供する型によって、データベースのXMLデータをネイティブに処理することが容易になります。

SYS.XMLTypeによって次の機能が提供され、Javaのoracle.xdb.XMLTypeクラスを介して公開されます。

- 表またはビューの列のデータ型として使用できます。XMLTypeにはあらゆるコンテンツを格納できますが、XMLコンテンツを最適に格納するように設計されています。そのインスタンスはSQLでXMLドキュメントを表現できます。

- XMLコンテンツの操作を行う組込みメンバー・ファンクションを含むSQL APIがあります。たとえば、XMLTypeファンクションを使用すると、Oracle Database 11g インスタンスに格納されているXMLデータの作成、問合せ、抽出および索引付けができます。

- ストアド・プロシージャで、パラメータ、戻り値および変数に使用できます。

- この機能は、PL/SQL、JavaおよびC(OCI)で提供されるAPIを介して使用することもできます。

関連項目:
『Oracle XML DB開発者ガイド』

7 高度な言語機能

この章では、アプリケーションのコーディングで利用できるSQLJ言語の高度な機能について説明します。SQLJの基本機能に関する詳細は、第4章「基本的な言語機能」を参照してください。

内容は次のとおりです。

- 接続コンテキスト

- 実行コンテキスト

- SQLJでのマルチスレッド

- イテレータ・クラスの実装と拡張機能

- 詳細なトランザクション制御

- SQLJとJDBCの連係動作

- 動的SQLのサポート

- 実行計画の修正

接続コンテキスト

SQLJでは接続コンテキストの概念がサポートされているため、様々なSQLエンティティ・セットで強い型指定の接続を使用できます。接続コンテキストは、特定のSQLエンティティ・セット(表、ビュー、ストアド・プロシージャなど)に関連付けられているといえます。SQLJでは、追加の接続コンテキスト・クラスを宣言することにより、特定のSQLエンティティ・セットを使用する接続で各クラスを使用できるようになります。1つの接続コンテキスト・クラスに対してインスタンスがいくつか存在する場合、これらのインスタンスは、同じ物理エンティティを使用したり、同じスキーマに接続する必要はありませんが、少なくとも名前およびデータ型が同じエンティティのセットを使用します。

関連項目:
1種類のSQLエンティティと1つの接続コンテキスト・クラスのみを使用する場合に重点を置いた、接続の基本に関する概要は、「接続の際の考慮事項」を参照してください。

ここでは、次の項目について説明します。

- 接続コンテキストの概要

- 接続コンテキストのロジスティクス

- 接続コンテキスト・クラスの宣言と使用方法の補足

- 複数の接続コンテキストの例

- 接続コンテキスト・クラスの実装と機能

- 接続コンテキスト宣言でのIMPLEMENTS句の使用

- 接続コンテキストのセマンティクス・チェック

- 標準データ・ソースのサポート

- SQLJ固有のデータ・ソース

- JavaServer Pages用のSQLJ固有の接続JavaBeans

- グローバル・トランザクションのSQLJサポート

接続コンテキストの概要

アプリケーションで数種類のSQLエンティティ・セットを使用する場合は、通常、1つ以上の追加の接続コンテキスト・クラスを宣言して使用することになります(「SQLJ宣言の概要」を参照)。各接続コンテキスト・クラスは、相互に関連するSQLエンティティの特定のセットに使用可能であり、これは特定の接続コンテキスト・クラスを使用して定義した接続はすべて、同じ名前および同じデータ型を持つ表、ビュー、ストアド・プロシージャなどを使用することを意味します。

たとえば、SQLエンティティ・セットの例として、人事(HR)部で使用する表とストアド・プロシージャのセットがあるとします。EMPLOYEESおよびDEPARTMENTS表と、CHANGE_DEPTおよびUPDATE_HEALTH_PLANストアド・プロシージャが使用されることが考えられます。別のSQLエンティティ・セットとして、財務部で使用する表およびプロシージャのセットがあるとすると、この場合は、EMPS表(人事部で使用する従業員表とは異なる表)、およびGIVE_RAISEストアド・プロシージャとCHANGE_WITHHOLDINGストアド・プロシージャで構成されると考えられます。

SQLエンティティへの接続コンテキスト・クラスをカスタマイズすると、オンラインのセマンティクス・チェックの精度が上がります。オンライン・チェックでは、SQLJ文中にあるSQLエンティティのうち、指定した接続コンテキスト・クラスを使用する各エンティティが、基本スキーマにある変換用SQLエンティティと同じかどうかが検証されます。基本スキーマは、SQLJの接続先データベース・アカウントの1つで、特定の接続コンテキスト・クラスを使用したSQLJ文に対するオンライン・チェックに使用されます。トランスレータへの基本スキーマを指定するには、SQLJコマンドラインから-user、-passwordおよび-urlオプションを使用します。基本スキーマは、実行時にアプリケーションで使用されるアカウントと同じにしてもしなくてもかまいません。

関連項目:
「接続オプション」

関連性が薄いと思われる幅広いSQLエンティティの1つのグループを複数のSQLJ文で使用し、これらのSQL文に対して1つの接続コンテキスト・クラスのみを使用する場合は、汎用性の高い基本スキーマを作成する必要があります。この基本スキーマには、これら文すべてで使用される表、ビューおよびストアド・プロシージャが、すべて含まれる必要があります。これに対し、特定の接続コンテキスト・クラスを使用するすべてのSQLJ文で、相互に関連すると思われる限られたSQLエンティティのセットを使用する場合は、より限定的な特定の基本スキーマを作成できます。これによって、より詳細で有効なセマンティクス・チェックが可能になります。

注意:

- 接続コンテキスト・クラスの宣言では、宣言される接続コンテキスト・クラスで使用するSQLエンティティのセットは定義されないため、異なる関連しないエンティティのセットを使用する接続に対しても、同じ接続コンテキスト・クラスが使用可能になる点に注意してください。接続コンテキスト・クラスをどのように使用するかは自由に決められます。特定の接続コンテキスト・クラスで使用可能なSQLエンティティを制限するのは、基本スキーマで使用可能なエンティティのセット(変換時にオンライン・セマンティクス・チェックを使用する場合)、および実行時の接続先のスキーマで使用可能なエンティティのセット(その接続コンテキスト・クラスのインスタンスを使用)です。

- アプリケーションで使用するSQL修飾名(SCOTT.EMPなど)に、エンティティの常駐場所を指定した場合、基本スキーマ(オンライン・チェックを使用する場合)およびランタイム・スキーマからリソースへのアクセスには、完全修飾名を指定する必要があります。

- ベンダー各社のデータベースへの接続にも、接続コンテキスト・クラスを使用可能です。ただし、同じ名前や互換性のあるデータ型を使用して、接続先スキーマのエンティティにアクセスできる場合に限られます。

接続コンテキストのロジスティクス

接続コンテキスト・クラスを宣言すると、SQLJトランスレータによって生成されたコードにクラスが定義されます。宣言した接続コンテキスト・クラスの他に、デフォルトの接続コンテキスト・クラスが定義されます。

sqlj.runtime.ref.DefaultContext

接続コンテキスト・インスタンスを作成する場合は、特定のスキーマおよびSQL操作が実行される特定のセッションとトランザクションを指定します。その場合、接続コンテキスト・クラスのコンストラクタへの入力パラメータとして、ユーザー名、パスワードおよびデータベースURLを指定します。接続コンテキスト・インスタンスでは、そのセッションで実行されたSQL操作が管理されます。

SQLJ文ごとに、使用する接続コンテキスト・インスタンスを指定します。次の例では、2つの異種スキーマに接続するための接続コンテキスト・クラスMyContextの基本的な宣言と使用方法を示します。通常の使用では、この両スキーマのSQLエンティティは、それぞれ名前とデータ型が同じであることが前提になります。

#sql context MyContext;

...
MyContext mctx1 = new MyContext
("jdbc:oracle:thin:@localhost:1521/myservice", "scott", "tiger", false);
MyContext mctx2 =  new MyContext
("jdbc:oracle:thin@localhost:1521/myservice", "brian", "mypasswd", false);

接続コンテキスト・クラスのコンストラクタは、ブール型の自動コミット・パラメータを指定する点に注意してください。また、同じスキーマに、異なる接続コンテキスト・インスタンスで接続できる点にも注意してください。前の例では、必要であれば、mctx1とmctx2の両方でscott/tigerを指定できます。ただし、実行時には、一方の接続コンテキスト・インスタンスは、他方のインスタンスが行ったデータベースの変更を、それがコミットされるまで認識することができません。ただし、両方の接続コンテキスト・インスタンスが同一の基本Java Database Connectivity (JDBC)接続インスタンスから作成されている場合は、例外です。どの接続コンテキスト・クラスでも、そのコンストラクタの1つは入力としてJDBC接続インスタンスを使用します。

接続コンテキスト・クラスの宣言と使用方法の補足

ここでは、接続コンテキスト・クラスを宣言し、クラスのインスタンスを使用してデータベース接続を定義する方法について、例を示して説明します。

接続コンテキスト・クラスのコンストラクタは、次の入力パラメータ・セットのいずれかをとる場合、データベース・スキーマへの接続を開きます(DefaultContextクラスの場合)。

- URL(String)、ユーザー名(String)、パスワード(String)、自動コミット(boolean)

- URL(String)、java.util.Propertiesオブジェクト、自動コミット(boolean)

- URL(ユーザー名やパスワードなど、接続の詳細を指定するString)、自動コミットの設定(boolean)

- JDBC接続オブジェクト(Connection)

- SQLJ接続コンテキスト・オブジェクト

注意:

- JDBC接続オブジェクトを引数とするコンストラクタを使用する場合は、接続コンテキスト・インスタンスをNULL JDBCで初期化しないでください。

- 自動コミットの設定では、SQL操作が自動的にコミットされるかどうかが定義されます。詳細は、「基本的なトランザクション制御」を参照してください。

- 接続コンテキスト・クラスがデータ・ソースwith句で宣言されている場合は、別の種類のコンストラクタが実装されます。詳細は、「標準データ・ソースのサポート」を参照してください。

接続コンテキスト・クラスの宣言

次に示す宣言では、接続コンテキスト・クラスが生成されます。

#sql context OrderEntryCtx <implements_clause> <with_clause>;

これを実行すると、SQLJトランスレータで、sqlj.runtime.ConnectionContextインタフェースを実装し、ベース・クラス(おそらく抽象クラスで、ConnectionContextインタフェースを実装する)を拡張するクラスが生成されます。このベース・クラスは、使用する特定のSQLJ実装の1つの機能となるものです。implements句とwith句の使用は任意で、前者は実装する追加のインタフェースを指定し、後者は定義および初期化する変数を指定します。

関連項目:
「IMPLEMENTS句宣言」および「WITH句宣言」

次は、SQLJトランスレータによって生成される内容です(メソッドの実装は省略してあります)。

class OrderEntryCtx implements sqlj.runtime.ConnectionContext
extends ...
{
public OrderEntryCtx(String url, Properties info, boolean autocommit)
throws SQLException {...}
public OrderEntryCtx(String url, boolean autocommit)
throws SQLException {...}
public OrderEntryCtx(String url, String user, String password,
boolean autocommit) throws SQLException {...}
public OrderEntryCtx(Connection conn) throws SQLException {...}
public OrderEntryCtx(ConnectionContext other) throws SQLException {...}

public static OrderEntryCtx getDefaultContext() {...}
public static void setDefaultContext(OrderEntryCtx ctx) {...}
}

接続コンテキスト・インスタンスの作成

前述の例を使用して、次の構文でOrderEntryCtxクラスをインスタンス化します。

OrderEntryCtx myOrderConn = new OrderEntryCtx
(url, username, password, autocommit);

次に例を示します。

OrderEntryCtx myOrderConn = new OrderEntryCtx
("jdbc:oracle:thin:@localhost:1521/myservice", "scott", "tiger", true);

このためには、DefaultContextクラスのインスタンス化と同じ方法を使用します。DefaultContextを含むすべての接続コンテキスト・クラスでは、それぞれコンストラクタのシグネチャが同じです。

注意:

- 通常は、JDBCドライバを登録した後で、接続コンテキスト・インスタンスを作成する必要があります。「実行時に使用するドライバの選択および登録」を参照してください。

- 接続コンテキスト・クラスがデータ・ソースwith句で宣言されている場合は、別の種類のコンストラクタが実装されます。詳細は、「標準データ・ソースのサポート」を参照してください。

SQLJ句での接続コンテキスト・インスタンスの指定

次は、基本的なSQLJ文の構文です。

#sql <[<conn><, ><exec>]> { SQL operation };

接続コンテキスト・インスタンスは、#sqlトークンの後ろの大カッコの内側に指定します。次のSQLJ文の例では、前述の例で使用したmyOrderConnを接続コンテキスト・インスタンスとして使用します。

#sql [myOrderConn] { UPDATE TAB2 SET COL1 = :w WHERE :v < COL2 };

DefaultContextクラスや宣言済の接続コンテキスト・クラスのインスタンスは、このようにして指定します。

接続コンテキスト・インスタンスの終了

処理が終了したら、すべての接続コンテキスト・インスタンスを閉じることをお薦めします。「接続の終了」のDefaultContextクラスの説明にもあるように、各接続コンテキスト・クラスにはclose()メソッドが含まれます。

接続コンテキスト・インスタンスのうち、元の接続を他の接続インスタンスと共有するものについては、元の接続を開いたままにしておく必要があります。

関連項目:
「共有接続の終了」

複数の接続コンテキストの例

次は、複数の接続コンテキストを使用するSQLJアプリケーションの例です。この例では、一方のSQLエンティティにはDefaultContextクラスのインスタンスを暗黙的に使用し、もう一方のSQLエンティティには、宣言済のDeptContext接続コンテキスト・クラスのインスタンスを使用しています。

この例では、静的なOracle.connect()メソッドを使用してデフォルト接続を確立し、静的なOracle.getConnection()メソッドを使用して追加の接続を作成して、別のDefaultContextインスタンスをDeptContextコンストラクタに渡します。前述のとおり、これは、SQLJ接続コンテキスト・インスタンスを作成できるいくつかの方法のうちの1つです。

import java.sql.SQLException;
import oracle.sqlj.runtime.Oracle;

// declare a new context class for obtaining departments
#sql context DeptContext;

#sql iterator Employees (String ename, int deptno);

class MultiSchemaDemo
{
public static void main(String[] args) throws SQLException
{
// set the default connection to the URL, user, and password
// specified in your connect.properties file
Oracle.connect(MultiSchemaDemo.class, "connect.properties");

// create a context for querying department info using
// a second connection
DeptContext deptCtx =
new DeptContext(Oracle.getConnection(MultiSchemaDemo.class,
"connect.properties"));

new MultiSchemaDemo().printEmployees(deptCtx);
deptCtx.close();
}

// performs a join on deptno field of two tables accessed from
// different connections.
void printEmployees(DeptContext deptCtx) throws SQLException
{
// obtain the employees from the default context
Employees emps;
#sql emps = { SELECT ename, deptno FROM emp };

// for each employee, obtain the department name
// using the dept table connection context
while (emps.next()) {
String dname;
int deptno = emps.deptno();
#sql [deptCtx] {
SELECT dname INTO :dname FROM dept WHERE deptno = :deptno
};
System.out.println("employee: " +emps.ename() +
", department: " + dname);
}
emps.close();
}
}

接続コンテキスト・クラスの実装と機能

ここでは、SQLJで接続コンテキスト・クラス(DefaultContextクラスなど)を実装する方法と、これらのクラスに含まれる主なメソッドについて説明します。前述のとおり、DefaultContextクラスおよび生成されるすべての接続コンテキスト・クラスは、ConnectionContextインタフェースを実装します。

注意:
接続コンテキスト・クラスの拡張はSQLJ仕様で許可されていないので、Oracle SQLJ実装での拡張はサポートされていません。

ConnectionContext インタフェース

各接続コンテキスト・クラスには、sqlj.runtime.ConnectionContextインタフェースが実装されています。

このインタフェースで指定される基本メソッドは、次のとおりです。

- close(boolean CLOSE_CONNECTION/KEEP_CONNECTION): その接続を保持するために使用されているすべてのリソースを解放し、オープンされている接続プロファイルをすべてクローズするメソッド。基になるJDBC接続を閉じるかどうかは、CLOSE_CONNECTIONまたはKEEP_CONNECTIONが指定されているかによります。これらは、ConnectionContextインタフェース特有のstaticブール定数です。

関連項目:
「共有接続の終了」

- getConnection(): その接続コンテキスト・インスタンスの基になるJDBC接続オブジェクトを戻すメソッド。

- getExecutionContext(): その接続コンテキスト・インスタンスのデフォルトのExecutionContextインスタンスを戻すメソッド。

関連項目:
「実行コンテキスト」

接続コンテキスト・クラスの追加メソッド

ConnectionContextインスタンスで定義されているメソッドの他に、次のメソッドが各接続コンテキスト・クラスで定義されています。

- YourCtxClass getDefaultContext(): これは静的メソッドで、特定の接続コンテキスト・クラスのデフォルトの接続コンテキスト・インスタンスを戻します。

- setDefaultContext(YourCtxClass connctxinstance ): これはstaticメソッドで、クラスのデフォルトの接続コンテキスト・インスタンスとして、任意の接続コンテキスト・インスタンスを定義します。

デフォルト接続として、DefaultContextクラスのみのインスタンスを使用することも可能ですが、setDefaultContext()メソッドでクラスのデフォルト・コンテキストとして宣言された接続コンテキスト・クラスのインスタンスを指定するのも便利です。このようにすると、特定のクラスのgetDefaultContext()メソッドを使用して、便利に取得することができます。たとえば、SQLJ実行文の接続コンテキスト・インタフェースを次のように指定できます。

#sql context MyContext;

...
MyContext myctx1 = new MyContext(url, user, password, autocommit);
...
MyContext.setDefaultContext(myctx1);
...
#sql [MyContext.getDefaultContext()] { SQL operations };
...

さらに、各接続コンテキスト・クラスでは、SQLJ文のキャッシングを制御するメソッドを定義します。次に示すstaticメソッドです。

- setDefaultStmtCacheSize(int)

- int getDefaultStmtCacheSize()

次のインスタンス・メソッドがあります。

- setStmtCacheSize(int)

- int getStmtCacheSize()

デフォルトで、文のキャッシングを使用できます。

関連項目:
「文キャッシングのための接続コンテキスト・メソッド(Oracle固有コードの場合)」

接続コンテキスト宣言でのIMPLEMENTS句の使用

接続コンテキスト宣言にインタフェースを実装する場合があります。たとえば、接続コンテキスト・クラスの機能のサブセットのみを公開するインタフェースを定義する必要があるとします。さらに具体的には、クラスで必要なのはgetConnection()の機能のみで、接続コンテキスト・クラスの他の機能は不要だとします。

例として、HasConnectionというインタフェースを作成し、getConnection()メソッドは指定しますが、接続コンテキスト・クラスに一般にみられる他のメソッドは指定しません。次に、接続コンテキスト・クラスを宣言し、getConnection()機能のみを公開することができますが、それには、接続コンテキスト・インスタンスを、宣言済の接続コンテキスト・クラスの型を持つ変数ではなく、HasConnection型の変数に割り当てます。

HasConnectionがmypackageパッケージにあると想定して、次のように宣言します。

#sql public context MyContext implements mypackage.HasConnection;

次のように、接続インスタンスをインスタンス化します。

HasConnection myConn = new MyContext (url, username, password, autocommit);

次に例を示します。

HasConnection myConn = new MyContext
("jdbc:oracle:thin:@localhost:1521/myservice", "scott", "tiger", true);

接続コンテキストのセマンティクス・チェック

SQLJの優れた機能の1つは接続の強い型指定であり、通常は、それぞれの接続コンテキスト・クラスが、特定の相互に関連するSQLエンティティ・セットの操作に使用されます。これは、1つのクラスのすべての接続インスタンスが同じ物理エンティティを使用するという意味ではありません。そうではなく、同じプロパティを持つエンティティ、つまり表およびビューに関連付けられる名前と権限、その行のデータ型、ストアド・プロシージャの名前と定義などが同じエンティティを使用するということです。この強い型指定によって、SQLJセマンティクス・チェックは、使用中のデータベース接続に関して、SQL操作が正しく使用されていることを変換時に検証できます。

変換時にオンライン・セマンティクス・チェックを使用するには、接続コンテキスト・クラスごとに、適切なSQLエンティティ・セットを含むサンプル・スキーマを提供します。これらのサンプル・スキーマは、基本スキーマと呼ばれます。SQLJ -user、-passwordおよび-urlオプションを適切に組み合わせて、基本スキーマを提供します。次に示す2つの例のうち、1つはDefaultContextクラスの場合、もう1つは宣言済の接続コンテキスト・クラスで、-userオプションを使用してユーザー、パスワードおよびURLがすべて指定されている場合です。

-user=scott/tiger@jdbc:oracle:oci:@
-user@MyContext=scott/tiger@jdbc:oracle:oci:@

トランスレータは、セマンティクス・チェック時に、特定の接続コンテキスト・クラスを指定された基本スキーマに接続し、次の処理を行います。

- 接続コンテキスト・クラスのインスタンスを指定するコード中の各SQLJ文を検証し、そのSQL操作(どの表にアクセスし、どのストアド・プロシージャを使用するのか、など)をチェックします。

- SQL操作におけるエンティティが基本スキーマにある既存のエンティティと一致することを検証します。

ユーザーは、適切なランタイム・スキーマを基本スキーマとして選択する必要があります。具体的には、基本スキーマの表、ビュー、ストアド・ファンクションおよびストアド・プロシージャの各名前とデータ型を、SQL操作で使用されているものと同一にし、各権限を正しく設定する必要があります。

変換時にいずれかの接続コンテキスト・クラスに適切な基本スキーマを使用できない場合は、その接続コンテキスト・クラスにSQLJトランスレータ・オプションを指定する必要はありません。その場合、その接続コンテキスト・クラスの接続オブジェクトを指定するSQLJ文では、可能な範囲でセマンティクス・チェックが行われます。

注意:
トランスレータ・オプション設定に指定する基本スキーマでは、実行時に使用されるスキーマは指定されません。基本スキーマからトランスレータに渡されるのは、SQLJ実行文で使用するエンティティと照合するための一組のSQLエンティティのみです。

標準データ・ソースのサポート

JDBC 2.0拡張Application Programming Interface(API)では、DriverManagerにかわって、データ・ソースおよびJava Naming and Directory Interface(JNDI)を使用したJDBC接続の取得が仕様化されました。JNDI名を検索することによって、データベース接続を確立できます。この名前は、通常、Graphical User Interface(GUI)のJavaBeansデプロイメント・ツールを通してインストールされるjavax.sql.DataSourceオブジェクトを通して、プログラム・ランタイムより前に特定のデータベースおよびスキーマに対してバインドされます。この名前は、ディレクトリ・サービスに名前を再バインドするのみでソース・コードを変更せずに、別の物理的接続にバインドされる場合もあります。

SQLJでは、柔軟で移植可能な方法で接続コンテキスト・インスタンスを作成するため、同じメカニズムを使用します。データ・ソースは、JDBC 2.0拡張APIで定義したように、接続プールまたは分散トランザクション・サービスを使用して実装されます。

関連項目:
『Oracle Database JDBC開発者ガイドおよびリファレンス』

接続コンテキストとデータ・ソースの関連付け

SQLJでは、通常、データ・ソース名がJDBC接続の象徴名となるのと同じように、接続コンテキスト・クラスを論理的スキーマに関連付けます。データ・ソース名を接続コンテキストの宣言に追加することにより、両方のコンセプトを結合します。次に例を示します。

#sql context EmpCtx with (dataSource="jdbc/EmpDB");

dataSourceプロパティで宣言した接続コンテキスト・クラスには、必ず追加のコンストラクタがあります。このEmpCtxの例では、次のコンストラクタがあります。

- EmpCtx(): jdbc/EmpDBのデータ・ソースを検索し、接続を取得するためにデータ・ソースでgetConnection()メソッドをコールします。

- EmpCtx(String user, String password): jdbc/EmpDBのデータ・ソースを検索し、接続を取得するためにデータ・ソースでgetConnection(user,password)メソッドをコールします。

- EmpCtx(ConnectionContext ctx): 接続を取得するためにctxへ委任します。

dataSourceプロパティで宣言した接続コンテキスト・クラスでは、DriverManagerベースのコンストラクタがいくつか削除されます。このEmpCtxの例では、次のコンストラクタが削除されます。

- EmpCtx(Connection conn)

- EmpCtx(String url, String user, String password, boolean autoCommit)

- EmpCtx(String url, boolean autoCommit)

- EmpCtx(String url, java.util.Properties info, boolean autoCommit)

- EmpCtx(String url, boolean autoCommit)

データ・ソース接続の自動コミット・モード

DriverManagerベースのコンストラクタとは異なり、データ・ソース・ベースのコンストラクタには、明示的な自動コミット・パラメータは含まれていません。常に、データ・ソースで定義された自動コミット・モードを使用します。

データ・ソースは、デプロイメント例によってはデフォルトの自動コミット・モードを持つように設定されています。たとえば、通常、サーバーおよび中間層のデータ・ソースでは自動コミットをオフにしています。クライアント上のデータ・ソースは自動コミットをオンにしています。ただし、特定の自動コミット設定を使用してデータ・ソースを設定することも可能です。これで、データ・ソースを特定のアプリケーションやデプロイメント例にあわせて設定できます。これを単一のデータベース/ドライバ設定のみを指定するJDBC URLと比較してください。

プログラムでは、接続コンテキスト・インスタンスの基になるJDBC接続を使用して、既存の自動コミット設定を確認および上書きできます。

注意:
確立する接続の自動コミット状態について次の点に留意してください。

- Oracleクラスを使用する場合、明示的に指定しないと、自動コミットはオフになります。

- DefaultContextまたはDriverManager形式のコンストラクタを指定した接続コンテキストを使用する場合、自動コミット設定は、常に明示的に指定する必要があります。

- データ・ソースのメカニズムを使用する場合、自動コミット設定が基になるデータ・ソースから継承されます。ほとんどの環境では、データ・ソース・オブジェクトはJDBCに基づいており、自動コミット・オプションはオンになっています。予期せぬ動作を防ぐために、常に自動コミット設定を確認してください。

データ・ソースとデフォルト・コンテキストの関連付け

SQLJプログラムがデフォルトの接続コンテキストにアクセスし、かつデフォルトのコンテキストが設定されていない場合、SQLJランタイムは接続を確立するために、デフォルトのSQLJデータ・ソースを使用します。デフォルトのSQLJデータ・ソースは、JNDI名jdbc/defaultDataSourceにバインドされます。

このメカニズムでは、デフォルトのSQLJ接続コンテキストに対するデフォルトのJDBC接続を定義し、インストールするための移植性のある方法を提供します。

データ・ソースのサポートの要件

プログラムでデータ・ソースを使用するには、Java環境でjavax.sql.*パッケージ、javax.naming.*パッケージおよびInitialContextプロバイダを指定する必要があります。後者は、SQLJランタイムがデータ・ソース・オブジェクトを検索できるJNDIコンテキストを取得する際に必要となります。

Oracleで提供するSQLJランタイムはすべて、データ・ソースをサポートしています。ただし、runtime12eeライブラリを使用する場合、CLASSPATH内にjavax.sql.*およびjavax.naming.*がなければ、ランタイムはロードされません。反対に、他のランタイム・ライブラリでは、リフレクションを使用してDataSourceオブジェクトが取得されます。

SQLJ固有のデータ・ソース

Oracle SQLJ実装によるSQLJ固有のデータ・ソースのサポートがruntime12eeライブラリで提供されます。現在、SQLJ固有のデータ・ソースは、サーバー内部ではなく、クライアント側または中間層アプリケーションで使用できます。

SQLJ固有のデータ・ソースは、SQLJ接続コンテキスト・インスタンスを戻すメソッドを使用して、JDBCデータ・ソース機能を拡張します。これによって、JDBC開発者が接続を管理するように、SQLJ開発者が接続コンテキストを管理できるようになります。一般に、SQLJ固有のデータ・ソースの各インタフェースまたは各クラスは、対応する標準JDBCデータ・ソースのインタフェースまたはOracleデータ・ソース・クラスに基づいています。

SQLJデータ・ソースのインタフェース

sqlj.runtime.ConnectionContextFactoryインタフェースは、SQLJデータ・ソース機能の基本インタフェースとして動作します。このインタフェースは、Oracleデータ・ソース専用の一連のインタフェースによって実装され、接続プーリング、接続キャッシングまたは分散トランザクションなどの機能に対するサポートを追加します。

ConnectionContextFactoryインタフェースは、次に示すメソッドを指定して、SQLJ接続コンテキスト・インスタンスを戻します。

- DefaultContext getDefaultContext()

- DefaultContext getDefaultContext(boolean autoCommit)

- DefaultContext getDefaultContext(String user, String password)

- DefaultContext getDefaultContext(String user, String password, boolean autoCommit)

- ConnectionContext getContext(Class aContextClass)

- ConnectionContext getContext(Class aContextClass, boolean autoCommit)

- ConnectionContext getContext(Class aContextClass, String user, String password)

- ConnectionContext getContext(Class aContextClass, String user, String password, boolean autoCommit)

getDefaultContextメソッドは、SQLJデフォルト・コンテキストのsqlj.runtime.ref.DefaultContextインタフェースを戻します。getContext()メソッドは、sqlj.runtime.ConnectionContextインスタンスを戻します。具体的には、メソッドのコールに指定されるユーザー宣言の接続コンテキスト・クラスのインスタンスを戻します。

getDefaultContext()およびgetContext()には、接続コンテキスト・インスタンスの基になるJDBC接続に対する接続パラメータ(自動コミット設定、ユーザー設定とパスワード設定、または3つの設定すべて)を指定できるシグネチャがあります。ユーザーとパスワードが未指定の場合は、接続を生成する基となるデータ・ソースからユーザーとパスワードが取得されます。自動コミット設定が未指定の場合は、基になるデータ・ソースの設定が明示的にtrueに指定されていないかぎり、デフォルトはfalseです。

ConnectionContextFactoryを実装する各Oracleデータ・ソース・インタフェースは、基本データ・ソース、接続プーリング・データ・ソース、分散トランザクション(XA)データ・ソースなどに適した機能のメソッドを指定するために、標準のJDBCデータ・ソース・インタフェースも実装しています。SqljDataSource、SqljConnectionPoolDataSourceおよびSqljXADataSourceインタフェースは、sqlj.runtimeパッケージに実装済であり、次のように指定されています。

- interface SqljDataSource extends javax.sql.DataSource, ConnectionContextFactory { }

- interface SqljDataSource extends javax.sql.ConnectionPoolDataSource, ConnectionContextFactory { }

- interface SqljXADataSource extends javax.sql.XADataSource, ConnectionContextFactory { }

SQLJデータ・ソースのクラス

Oracleでは、OracleDataSource、OracleConnectionPoolDataSource、OracleXADataSource、OracleConnectionCacheImpl、OracleXAConnectionCacheImplおよびOracleOCIConnectionPoolのJDBCデータ・ソースの各クラスに対応するSQLJ固有のクラスを提供しています。

関連項目:
『Oracle Database JDBC開発者ガイドおよびリファレンス』

Oracle SQLJ固有のデータ・ソース・クラスは、oracle.sqlj.runtimeおよびoracle.sqlj.runtime.clientの2つのパッケージに格納されています。

oracle.sqlj.runtimeパッケージには、次のクラスが含まれています。

- class OracleSqljDataSource extends oracle.jdbc.pool.OracleDataSource implements ConnectionContextFactory

注意:
OracleSqljDataSourceクラスはjava.io.Serializableインタフェースを実装します。したがって、このクラスはシリアライズ可能で、Oracle9i Application Server Containers for J2EE(OC4J)などのクラスタ環境で使用できます。

- class OracleSqljConnectionPoolDataSource extends oracle.jdbc.pool.OracleConnectionPoolDataSource implements ConnectionContextFactory

- abstract class OracleSqljXADataSource extends oracle.jdbc.xa.OracleXADataSource implements ConnectionContextFactory

- class OracleSqljOCIConnectionPool extends oracle.jdbc.pool.OracleOCIConnectionPool implements ConnectionContextFactory

注意:

- OracleSqljConnectionCacheImplを使用している場合は、OracleSqljDataSourceに置き換える必要があります。

- OracleSqljXAConnectionCacheImplを使用している場合は、OracleSqljXADataSourceに置き換える必要があります。

oracle.sqlj.runtime.clientパッケージには、次のクラスが含まれています。

- class OracleSqljXADataSource extends oracle.jdbc.xa.client.OracleXADataSource implements ConnectionContextFactory

対応するJDBCクラスのかわりに、拡張されたこれらのクラスを使用できます。これらのクラスには、getDefaultContext()およびgetContext()メソッドが含まれています。これらのメソッドをコールする場合は、次の手順が発生します。

1. 現行のデータ・ソースから新しい論理JDBC接続が取得されます。

2. 論理接続から接続コンテキスト・インスタンスが作成され、戻されます。

例: SQLJデータ・ソースの使用

中間層の環境で使用される場合、SQLJ固有のデータ・ソースは、JDBCデータ・ソースのようにJNDIの位置にバインドされます。次の例のように、明示的にバインドできます。

//Initialize the data source
SqljXADataSource sqljDS = new OracleSqljXADataSource();
sqljDS.setUser("scott");
sqljDS.setPassword("tiger");
sqljDS.setServerName("myserver");
sqljDS.setDatabaseName("ORCL");
sqljDS.setDataSourceName("jdbc/OracleSqljXADS");

//Bind the data source to JNDI
Context ctx = new InitialContext();
ctx.bind("jdbc/OracleSqljXADS");

中間層のOC4J環境の場合、もう1つの方法として、j2ee/home/config/data-sources.xmlファイルの設定によってデータ・ソースをインスタンス化し、JNDIにバインドする方法もあります。たとえば、ファイル内の次の<data-source>要素は、OracleSqljXADataSourceインスタンスを作成し、それをJNDIの位置jdbc/OracleSqljXADSにバインドします。

<data-source
class="oracle.sqlj.runtime.OracleSqljXADataSource"
name="jdbc/OracleSqljXADS"
location="jdbc/OracleSqljXADS"
xa-location="jdbc/OracleSqljXADS/xa"
username="scott"
password="tiger"
url="jdbc:oracle:thin:@myhost:1521/myservice"
/>

関連項目:
『Oracle Application Server Containers for J2EEサービス・ガイド』

JNDIの位置にバインドされたSQLJ固有のデータ・ソースは、接続コンテキスト・インスタンスの作成時に検索および使用されます。次のコードは、前述の<data-source>要素の情報を使用して、接続コンテキスト・インスタンス(それぞれDefaultContextインスタンスとユーザー宣言MyCtxクラスのインスタンス)を作成します。

sqlj.runtime.SqljDataSource sqljDS;
InitialContext initCtx = new InitialContext();
sqljDS = (sqlj.runtime.SqljDataSource)initCtx.lookup("jdbc/OracleSqljXADS");
// getDefaultContext
DefaultContext ctx = sqljDS.getDefaultContext();
// getContext
/* Declare MyCtx connection context class. You could optionally use a "with"
clause to specify  any desired connection parameters not available
through the underlying data source.
*/
#sql public static context MyCtx;
MyCtx ctx = (MyCtx) sqljDS.getContext(MyCtx.class);

JavaServer Pages用のSQLJ固有の接続JavaBeans

Oracleでは、Java Server Pages(JSP)ページ内部からのデータベース接続用に一連のJavaBeansが実装されました。元のBeanである、oracle.jsp.dbutilのConnBeanおよびConnCacheBeanについては、『Oracle Application Server Containers for J2EE JSPタグ・ライブラリおよびユーティリティ・リファレンス』を参照してください。

Oracle SQLJ実装には、SQLJ JSPページで使用するruntime12eeライブラリのこれらのJavaBeansについて、次の拡張機能が用意されています。

- oracle.sqlj.runtime.SqljConnBean

- oracle.sqlj.runtime.SqljConnCacheBean

ConnBeanおよびConnCacheBeanには、JDBC接続オブジェクトを戻すメソッドが含まれています。SqljConnBeanおよびSqljConnCacheBeanは、String型のContextClassと呼ばれるBeanプロパティをサポートし、SQLJ接続コンテキスト・インスタンスを戻すように機能が拡張されています。

注意:
SqljConnBeanクラスはjava.io.Serializableインタフェースを実装します。したがって、このクラスはシリアライズ可能で、OC4Jなどのクラスタ環境で使用できます。

SqljConnBeanおよびSqljConnCacheBeanには、次のメソッドが用意されています。

- void setContextClass(String contextClassName)

- String getContextClass()

- DefaultContext getDefaultContext()

- ConnectionContext getContext()

ContextClassプロパティは、DefaultContextを使用していない場合に、ユーザー宣言の接続コンテキスト・クラスの名前を指定します。setContextClass()メソッドを介して、このプロパティを設定できます。

接続コンテキスト・インスタンスを取得するには、必要に応じてgetDefaultContext()またはgetContext()を使用します。前者はsqlj.runtime.ref.DefaultContextインスタンスを戻し、後者はsqlj.runtime.ConnectionContextインスタンス、特にContextClassプロパティで指定されたクラスのインスタンス(デフォルトではDefaultContext)を戻します。

ただし、getDefaultContext()メソッドとgetContext()メソッドは、SqljConnBeanとSqljConnCacheBeanでは実装が異なることに注意してください。

SqljConnBeanの動作(単純な接続の場合)

SqljConnBeanインスタンスは、常に1つの論理JDBC接続と1つのSQLJ接続コンテキスト・インスタンスのみをラッピングできます。

最初のgetDefaultContext()またはgetContext()メソッドのコールによって、基礎となるJDBC接続に基づいて接続コンテキスト・インスタンスが作成され、戻されます。この接続コンテキスト・インスタンスもSqljConnBeanインスタンスに格納されます。

接続コンテキスト・インスタンスが作成および格納されると、後続のgetDefaultContext()またはgetContext()コールの動作は、格納された接続コンテキストの型によって異なります。また、getContext()の場合は、次のようにContextClassプロパティに指定されている接続コンテキスト型にも依存します。

- 後続のgetDefaultContext()コールに対して

- 格納された接続コンテキスト・インスタンスがDefaultContextインスタンスの場合、メソッドはそのインスタンスを戻し続けます。

- 格納された接続コンテキスト・インスタンスが、DefaultContextインスタンスではない場合、このメソッドは格納された接続コンテキスト・インスタンスを終了し、基になるJDBC接続を再利用して、新しい接続コンテキストをDefaultContextインスタンスとして戻します(前回の接続コンテキスト・タイプに関係なく)。これによって、新規接続コンテキスト・インスタンスがSqljConnBeanインスタンスに格納されます。

- 後続のgetContext()コールに対して

- 格納された接続コンテキスト・インスタンスが、ContextClassプロパティの指定と同じ型である場合、メソッドはそのインスタンスを戻し続けます。

- 格納された接続コンテキスト・インスタンスがContextClassの指定と同じ型ではない場合、このメソッドは格納された接続コンテキスト・インスタンスを終了し、基になるJDBC接続を再利用して、新しい接続コンテキスト・インスタンス(ContextClassで指定したもののインスタンス)を戻します。これによって、新規接続コンテキスト・インスタンスがSqljConnBeanインスタンスに格納されます。

注意:
SqljConnBeanで接続コンテキスト・インスタンスをクローズする場合、KEEP_CONNECTION設定を使用してクローズする、基礎となるJDBC接続はそのまま残ります。関連情報は、「共有接続の終了」を参照してください。

SqljConnCacheBeanの動作(接続キャッシング)

SqljConnBeanとは異なり、SqljConnCacheBean JavaBeanは、getDefaultContext()またはgetContext()の各呼出しに対して、新規論理JDBC接続に基づいて新規接続コンテキスト・インスタンスを作成し、戻します。接続コンテキスト型は、getDefaultContext()コールの場合はDefaultContext、getContext()コールの場合はContextClassプロパティに指定されている型になります。

SqljConnCacheBeanでは、作成した接続コンテキスト・インスタンスを格納しません。

例: SqljConnCacheBeanを使用するSQLJ JSPページ

次のプログラムSQLJSelectInto.sqljspは、SqljConnCacheBeanと、そのContextClass BeanプロパティおよびそのgetContext()メソッドの使用方法の一例です。

<%@ page language="sqlj"
import="java.sql.*, oracle.sqlj.runtime.SqljConnCacheBean" %>
<jsp:useBean id="cbean" class="oracle.sqlj.runtime.SqljConnCacheBean"
scope="session">
<jsp:setProperty name="cbean" property="User" value="scott"/>
<jsp:setProperty name="cbean" property="Password" value="tiger"/>
<jsp:setProperty name="cbean" property="URL"
value="jdbc:oracle:thin:@myhost:1521/myservice"/>
<jsp:setProperty name="cbean" property="ContextClass"
value="sqlj.runtime.ref.DefaultContext"/>
</jsp:useBean>
<HTML>
<HEAD> <TITLE> The SQLJSelectInto JSP  </TITLE> </HEAD>
<BODY BGCOLOR=white>
<% String empno = request.getParameter("empno");
if (empno != null) { %>
<H3> Employee # <%=empno %> Details: </H3>
<% String ename = null;  double sal = 0.0;  String hireDate = null;
StringBuffer sb = new StringBuffer();
sqlj.runtime.ref.DefaultContext ctx=null;
try {
// Make the Connection
ctx = (sqlj.runtime.ref.DefaultContext) cbean.getContext();
} catch (SQLException e) {
}
try {
#sql [ctx] { SELECT ename, sal, TO_CHAR(hiredate, 'DD-MON-YYYY')
INTO :ename, :sal, :hireDate
FROM scott.emp WHERE UPPER(empno) = UPPER(:empno)
};
sb.append("<BLOCKQUOTE><BIG><B><PRE>\n");
sb.append("Name       : " + ename + "\n");
sb.append("Salary     : " + sal + "\n");
sb.append("Date hired : " + hireDate);
sb.append("</PRE></B></BIG></BLOCKQUOTE>");
} catch (java.sql.SQLException e) {
sb.append("<P> SQL error: <PRE> " + e + " </PRE> </P>\n");
} finally {
if (ctx!= null) ctx.close();
}
%>
<H3><%=sb.toString()%></H3>
<%}
%>
<B>Enter an employee number:</B>
<FORM METHOD=get>
<INPUT TYPE="text" NAME="empno" SIZE=10>
<INPUT TYPE="submit" VALUE="Ask Oracle");
</FORM>
</BODY>
</HTML>

注意:
この例では、説明のためContextClassプロパティを使用しています。ただし、デフォルト値はDefaultContextであり、DefaultContextを使用する場合に、getContext()ではなくgetDefaultContext()を使用すると、ContextClassの値は使用されません。

グローバル・トランザクションのSQLJサポート

分散トランザクション(グローバル・トランザクションとも呼ばれこともある)は、複数の関連トランザクションの集合である、調整して管理する必要があります。分散トランザクションを構成するトランザクションは、同じデータベース内に存在することもありますが、通常は異なるデータベースに存在し、多くの場合は異なる場所に存在します。分散トランザクションを構成する各トランザクションをトランザクション・ブランチと呼びます。

X/Open分散トランザクション処理(DTP)アーキテクチャは、1つ以上のリソース・マネージャに属する複数の関連トランザクションが、1つの単位として動作するための標準アーキテクチャを定義します。これによって、アプリケーション・プログラム(AP)とリソース・マネージャ(RM)間の動作が調整され、グローバル・トランザクションになります。すべてのトランザクションは、コミットまたはロールバックされます。

Oracle XAライブラリは、Oracleサーバー以外のトランザクション・マネージャがグローバル・トランザクションを調整できるようにするための外部インタフェースです。XAライブラリを使用すると、分散トランザクションで、Oracle以外のリソース・マネージャがサポートされます。これは、複数のデータベースやリソース間に渡るトランザクションの場合に特に有効です。Oracle XAライブラリの実装は、X/Open分散トランザクション処理(DTP)ソフトウェア・アーキテクチャのXAインタフェース仕様に準拠しています。Oracle XAライブラリは、Oracle Database Enterprise Editionの一部としてインストールします。

注意:

- JDBCはXAをサポートする複数のクラスおよびインタフェースを提供します。OracleXADataSourceは、XADataSourceインタフェースを実装します。OracleXADatasourceは、XA接続のファクトリです。詳細は『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

- このドキュメントでは、XAアプリケーションで接続コンテキストを作成するためにSQLJでサポートされるメソッドを明確に示しています。接続コンテキストを作成するために、SQLJはOracleXADataSourceから作成されたJDBC接続を使用します。

図7-1 グローバル・トランザクション

次に、分散トランザクション処理(DTP)モデルの例を示します。

トランザクション・マネージャは、Oracle Databaseの外部に存在する外部中間層コンポーネントです。これによって、トランザクションの境界を指定するAPIが提供され、コミットおよびリカバリが管理されます。TMは2フェーズのコミット・エンジンを実装して、分散RMにまたがるall-or-noneセマンティクスを提供します。

リソース・マネージャは、障害発生後に通常の状態に戻すことができる共有かつリカバリ可能なリソースを制御します。たとえば、Oracleはリソース・マネージャです。

javax.sql.XADataSourceインタフェースは、XAデータ・ソースの標準機能を示します。XAデータ・ソースはXA接続のファクトリです。Oracle JDBCは、OracleXADatasourceクラスを介してXADataSourceインタフェースを実装します。OracleXADatasourceクラスのgetConnection( )メソッドは、基礎となるデータ・ソースへのXA接続を戻します。SQLJでは、データベースへの接続は、DefaultContextクラスまたはConnectionContextクラスを介して取得できます。数種類のSQLエンティティを使用した接続の場合は、接続コンテキストの宣言によって、接続コンテキスト・クラスをさらに定義すると利便性が高まります。

コード例では、XADatasourceの作成方法に続いて、データ・ソースからのJDBC接続の作成方法を次の順に示します。

- XAリソース1の開始

- XAリソース2の開始

- 最初の接続オブジェクトを使用したDML操作の実行

- XAリソース1の終了

- XAリソース2の終了

- リソース1の準備

- リソース2の準備

- コミット1

- コミット2

注意:
次のコードは完全な構文例ではありません。XADatasourceの作成および使用に関連するコードのみが含まれます。

例: XADatasourceの作成およびXADatasourceを使用したJDBC接続の作成

import javax.sql.*;
import javax.transaction.*;
import javax.transaction.xa.*;
...
import oracle.jdbc.driver.*;
import oracle.jdbc.xa.OracleXid;
import oracle.jdbc.xa.OracleXAException;
import oracle.jdbc.xa.client.*;
…………
#sql context MyContext;
#sql iterator Iterator2 (String job_id, String job_title);
#sql iterator Iterator3 (String region_id, String region_name);
…………
class XA3mod{
public static void main (String args [])throws SQLException{
try{
/*create an XADataSource instance*/
OracleXADataSource oxds = new OracleXADataSource();
oxds.setURL(url);
oxds.setUser("hr");
oxds.setPassword("hr");
/*get an XA connection to the underlying data source*/
javax.sql.XAConnection pc1  = oxds.getXAConnection();
/*use the same data source */
javax.sql.XAConnection pc2  = oxds.getXAConnection();
/*get the Physical Connections*/
java.sql.Connection conn1 = pc1.getConnection();
java.sql.Connection conn2 = pc2.getConnection();
/*an application may access data through multiple database connections. Each database connection is enlisted
with the transaction manager as a transactional resource. The transaction manager obtains an XAResource
for each connection participating in a global transaction */
XAResource oxar1 = pc1.getXAResource();
XAResource oxar2 = pc2.getXAResource();
/*create the Xids With the Same Global Ids. The Xid interface is a Java mapping of the X/Open transaction
identifier XID structure*/
Xid xid1 = createXid(1);
Xid xid2 = createXid(2);
/*start the Resources. This would start work on behalf of a transaction branch specified in xid1 and xid2.
The transaction manager uses the start method to associate the global transaction with the resource,
and it uses the end method to disassociate the transaction from the resource */
oxar1.start (xid1, XAResource.TMNOFLAGS);
oxar2.start (xid2, XAResource.TMNOFLAGS);
/*Do something with conn1 */
DoSomeWork (conn1);
/*END both the branches */
xar1.end(xid1, XAResource.TMSUCCESS);
xar2.end(xid2, XAResource.TMSUCCESS);
/*Prepare the RMs. The Oracle XA library interface follows the two-phase commit protocol. Preparing the transactions
is the first step in this protocol. The two phase commit protocol is explained in detail in the glossary section. */
int prp1 =  oxar1.prepare (xid1);
int prp2 =  oxar2.prepare (xid2);
boolean do_commit = true;
if(!((prp1==XAResource.XA_OK)||(prp1==XAResource.XA_RDONLY)))
do_commit = false;
if(!((prp2==XAResource.XA_OK)||(prp2==XAResource.XA_RDONLY)))
do_commit = false;
/*issue a commit on all transactions only if all the transactions completed without and errors. Rollback even
if a single transaction failed.*/
if (prp1 == XAResource.XA_OK)
if (do_commit)
oxar1.commit (xid1, false);
else
oxar1.rollback (xid1);
if (prp2 == XAResource.XA_OK)
if (do_commit)
oxar2.commit (xid2, false);
else
oxar2.rollback (xid2);
/* close connections */
conn1.close(); conn1 = null;
conn2.close(); conn2 = null;
pc1.close();   pc1 = null;
pc2.close();   pc2 = null;
} catch (XAException xae){
if (xae instanceof OracleXAException) {
System.out.println("XA Error is " + ((OracleXAException)xae).getXAError());
System.out.println("SQL Error is " +((OracleXAException)xae).getOracleError());
}
}
} //end class

次の例に、OracleXADatasourceから取得したJDBC接続を使用する様々なSQLJメソッドを示します。

XA Datasourceから取得したJDBC接続を使用するOracle.connect( )メソッドの使用例

private static void DoSomeWork (java.sql.Connection conn) throws SQLException{
String chr = "XA_CERT";
Oracle.connect(conn);
#sql  {insert into xa_test values (1,:chr)};
try{
Iterator3 iter = null;
#sql iter = {SELECT id,name FROM xa_test};
while (iter.next( )){
System.out.print(iter.id());
System.out.print(" ");
System.out.println(iter.name());
}
}
catch (Exception e){
System.out.println(e);
e.printStackTrace();
}
}

XA Datasourceから取得したJDBC接続を使用するOracle.getConnection( )メソッドの使用例

private static void DoSomeWork (java.sql.Connection conn) throws SQLException{
String chr = "XA_CERT";
DefaultContext  ctx = Oracle.getConnection(conn);
#sql [ctx]  {insert into xa_test values (1,:chr)};
try{
Iterator3 iter = null;
#sql [ctx] iter = {SELECT id,name FROM xa_test};
while (iter.next( )){
System.out.print(iter.id());
System.out.print(" ");
System.out.println(iter.name());
}
}
catch (Exception e){
System.out.println(e);
e.printStackTrace();
}
}

XA Datasourceから取得したJDBC接続を使用するDefaultContextコンストラクタの使用例

private static void DoSomeWork (java.sql.Connection conn) throws SQLException{
String chr = "XA_CERT";
DefaultContext  ctx = new DefaultContext(conn)
#sql [ctx]  {insert into xa_test values (1,:chr)};
try{
Iterator3 iter = null;
#sql [ctx] iter = {SELECT id,name FROM xa_test};
while (iter.next( )){
System.out.print(iter.id());
System.out.print(" ");
System.out.println(iter.name());
}
}
catch (Exception e){
System.out.println(e);
e.printStackTrace();
}
}

ConnectionContextを渡すことによるDefaultContextコンストラクタの使用例。ConnectionContextは、XA Datasourceから取得したJDBC接続を介して作成されます。

private static void DoSomeWork (java.sql.Connection conn) throws SQLException{
String chr = "XA_CERT";
MyContext myctx1= new MyContext (conn);
DefaultContext  ctx = new DefaultContext(myctx1);
#sql [ctx]  {insert into xa_test values (1,:chr)};
try{
Iterator3 iter = null;
#sql [ctx] iter = {SELECT id,name FROM xa_test};
while (iter.next( )){
System.out.print(iter.id());
System.out.print(" ");
System.out.println(iter.name());
}
}
catch (Exception e){
System.out.println(e);
e.printStackTrace();
}
}

ConnectionContextを渡すことによるOracle.connect( )メソッドの使用例。ConnectionContextは、XA Datasourceから取得したJDBC接続を介して作成されます。

private static void DoSomeWork (java.sql.Connection conn) throws SQLException{
String chr = "XA_CERT";
MyContext myctx1= new MyContext (conn);
Oracle.connect(myctx1);
#sql {insert into xa_test values (1,:chr)};
try{
Iterator3 iter = null;
#sql iter = {SELECT id,name FROM xa_test};
while (iter.next( )){
System.out.print(iter.id());
System.out.print(" ");
System.out.println(iter.name());
}
}
catch (Exception e){
System.out.println(e);
e.printStackTrace();
}
}

ConnectionContextを渡すことによるOracle. getConnection( )メソッドの使用例。ConnectionContextは、XA Datasourceから取得したJDBC接続を介して作成されます。

private static void DoSomeWork (java.sql.Connection conn) throws SQLException{
String chr = "XA_CERT";
MyContext myctx1= new MyContext (conn);
DefaultContext  ctx = Oracle.getConnection(myctx1);
#sql [ctx]  {insert into xa_test values (1,:chr)};
try{
Iterator3 iter = null;
#sql [ctx] iter = {SELECT id,name FROM xa_test};
while (iter.next( )){
System.out.print(iter.id());
System.out.print(" ");
System.out.println(iter.name());
}
}
catch (Exception e){
System.out.println(e);
e.printStackTrace();
}
}

DefaultContextクラスのsetDefaultContext( )メソッドは、XA Datasourceから取得したJDBC接続を介して作成されたコンテキストの設定にも使用されます。

DefaultContext.setDefaultContext(ctx);

XA Datasourceから取得したJDBC接続を渡すことによるConnectionContextコンストラクタの使用例

private static void DoSomeWork (java.sql.Connection conn) throws SQLException{
String chr = "XA_CERT";
MyContext myctx1= new MyContext (conn);
#sql [myctx1]  {insert into xa_test values (1,:chr)};
try{
Iterator3 iter = null;
#sql [myctx1] iter = {SELECT id,name FROM xa_test};
while (iter.next( )){
System.out.print(iter.id());
System.out.print(" ");
System.out.println(iter.name());
}
}
catch (Exception e){
System.out.println(e);
e.printStackTrace();
}
}

ConnectionContextを渡すことによるConnectionContextコンストラクタの使用例。ConnectionContextは、XA Datasourceから取得したJDBC接続を介して作成されます。

private static void DoSomeWork (java.sql.Connection conn) throws SQLException{
String chr = "XA_CERT";
MyContext myctx= new MyContext (conn);
MyContext myctx1= new MyContext (myctx);
#sql [myctx1]  {insert into xa_test values (1,:chr)};
try{
Iterator3 iter = null;
#sql [myctx1] iter = {SELECT id,name FROM xa_test};
while (iter.next( )){
System.out.print(iter.id());
System.out.print(" ");
System.out.println(iter.name());
}
}
catch (Exception e){
System.out.println(e);
e.printStackTrace();
}
}

実行コンテキスト

実行コンテキストはsqlj.runtime.ExecutionContextクラスのインスタンスで、SQL操作が実行されるコンテキストを提供します。実行コンテキスト・インスタンスは、SQLJアプリケーションの各SQL操作に暗黙的にまたは明示的に対応付けられています。

ExecutionContextクラスには、次の機能に対するメソッドが含まれています。

- 実行制御操作は、後続のSQL操作のセマンティクスを変更します。

- 実行ステータス操作は、最新のSQL操作の結果を示します。

- 実行取消し操作は、現在実行しているSQL操作を終了します。

- バッチ更新操作は、バッチの有効化と無効化、バッチ制限の設定、および更新カウントの取得を行います。

- セーブポイント操作は、セーブポイントの設定、セーブポイントのロールバック、およびセーブポイントの解放を行います。

- 閉包操作は、実行コンテキスト・インスタンスを終了してリソースのリークを回避します。

注意:
必要に応じて追加のクラスを宣言する接続コンテキスト・クラスとは異なり、実行コンテキスト・クラスは1つだけです。実行コンテキストはすべてExecutionContextクラスのインスタンスです。接続コンテキストという用語が通常は宣言済のクラスを指すのに対し、実行コンテキストという用語は常にExecutionContextクラスのインスタンスを指します。このドキュメントでは、混乱を避けるために、接続コンテキスト・クラス、接続コンテキスト・インスタンス、および実行コンテキスト・インスタンスと明記しています。

ここでは、次の項目について説明します。

- 実行コンテキストと接続コンテキストとの関係

- 実行コンテキスト・インスタンスの作成と指定

- 実行コンテキストの同期

- 実行コンテキストのメソッド

- 実行コンテキストとマルチスレッドの関係

実行コンテキストと接続コンテキストとの関係

各接続コンテキスト・インスタンスには、暗黙的にデフォルトの実行コンテキスト・インスタンスが対応付けられています。このインスタンスを取得するには、接続コンテキスト・インスタンスのgetExecutionContext()メソッドを使用します。

1つの接続コンテキスト・インスタンスに必要な実行コンテキスト・インスタンスは、1つのみです。ただし、次の場合を除きます。

- 1つの接続コンテキスト・インスタンスで複数のスレッドを使用している場合
マルチスレッドを使用している場合は、各スレッドにその実行コンテキスト・インスタンスが必要です。

- 同じコンテキスト・インスタンスを使用する複数のSQLJ文で、SQL実行制御の異なる操作を指定する場合

- 同じ接続コンテキスト・インスタンスを使用する複数のSQL操作から、異なるSQLのステータス情報を保持する場合
同じ実行コンテキスト・インスタンスを使用する一連のSQL操作を実行すると、各操作からのステータス情報によって前の操作からのステータス情報が上書きされます。

実行コンテキスト・インスタンスは接続コンテキスト・インスタンスと関連付けられているように見えますが(各接続コンテキスト・インスタンスがデフォルトの実行コンテキスト・インスタンスを持ち、特定のSQLJ文に対して接続コンテキスト・インスタンスおよび実行コンテキスト・インスタンスを一緒に指定可能な場合)、実際には独立して動作します。同じ接続コンテキスト・インスタンスを使用する文で異なる実行コンテキスト・インスタンスを使用可能であり、その逆も同様です。

たとえば、マルチスレッドによって、スレッドごとに別の実行コンテキスト・インスタンスを使用している場合、1つの接続コンテキスト・インスタンスで複数の実行コンテキスト・インスタンスを使用すると便利です。また、シングル・スレッド方式のプログラムを使用し、同じSQL制御パラメータをすべての接続コンテキスト・インスタンスに適用する場合は、1つの明示的な実行コンテキスト・インスタンスで複数の接続コンテキスト・インスタンスを使用できます。

関連項目:
「実行コンテキストのメソッド」

複数の実行コンテキスト・インスタンスを1つの設定コンテキスト・インスタンスで使用するには、ExecutionContextクラスのインスタンスを追加し、SQLJ文で正しく指定する必要があります。

実行コンテキスト・インスタンスの作成と指定

デフォルト以外の実行コンテキスト・インスタンスを特定の接続コンテキスト・インスタンスで使用するには、別の実行コンテキスト・インスタンスを作成する必要があります。ExectionContextコンストラクタには、入力パラメータがありません。次に例を示します。

ExecutionContext myExecCtx = new ExecutionContext();

次に、特定のSQLJ文で使用するためにこの実行コンテキスト・インスタンスを指定できます(接続コンテキスト・インスタンスも指定します)。一般的な構文は次のとおです。

#sql [<conn_context><, ><exec_context>] { SQL operation };

たとえば、接続コンテキスト・クラスのMyConnCtxClassを宣言およびインスタンス化して、インスタンスmyConnCtxを作成した場合は、次の文を使用することもできます。

#sql [myConnCtx, myExecCtx] { DELETE FROM emp WHERE sal > 30000 };

myConnCtxに別の接続コンテキスト・インスタンスを使用したり、myExecCtxに別の実行コンテキスト・インスタンスを使用できます。

次のように、デフォルトの接続コンテキスト・インスタンスを使用して、実行コンテキスト・インスタンスを指定することも可能です。

#sql [myExecCtx] { DELETE FROM emp WHERE sal > 30000 };

注意:

- 実行コンテキスト・インスタンスを指定しないで接続コンテキスト・インスタンスを指定した場合は、その接続コンテキスト・インスタンスのデフォルトの実行コンテキスト・インスタンスが使用されます。

- 接続コンテキスト・インスタンスを指定しないで実行コンテキスト・インスタンスを指定した場合は、その実行コンテキスト・インスタンスには、アプリケーションのデフォルトの接続コンテキスト・インスタンスが使用されます。

- 接続コンテキスト・インスタンスと実行コンテキスト・インスタンスの両方を指定しなかった場合は、SQLJではデフォルトの接続コンテキスト・インスタンスとデフォルトの実行コンテキスト・インスタンスが使用されます。

実行コンテキストの同期

ExecutionContextメソッドは、すべてsynchronizedメソッドです。そのため、ISO標準コード生成の場合は、ある文がすでに使用されている実行コンテキスト・インスタンスを使用しようとすると、最初の文の処理が終了するまで次の文がブロックされます。

これについては、クライアント・アプリケーションでのマルチスレッド化の状況などが関係します。別のスレッドで使用されている実行コンテキスト・インスタンスの使用を試みたスレッドは、ブロックされます。このようなブロックを避けるには、使用する各スレッドに対して、別の実行コンテキスト・インスタンスを指定する必要があります。

関連項目:
「SQLJでのマルチスレッド」

ただし、デフォルトのOracle固有コード生成には適用されません。パフォーマンス上の理由から、SQLJでは、Oracle固有生成コードのExecutionContextインスタンスに対する同期が追加実行されません。そのため、必ず、1つの実行コンテキスト・インスタンスを複数のスレッドで使用しないようにする必要があります。複数のスレッドで同じ実行コンテキストを使用すると、ブロック化ではなくてアプリケーションで、不正な結果やNullPointer例外などのエラーが発生します。

もう1つの例外はサーバーでのみ発生する再帰型の場合です。再帰的コールの場合、1つのスレッド内の複数のSQLJ文は、同時に同じ実行コンテキスト・インスタンスを使用できます。たとえば、SQLJストアド・プロシージャまたはストアド・ファンクションに、別のSQLJストアド・プロシージャまたはストアド・ファンクションへのコールが含まれている場合などです。この両方のストアド・プロシージャでデフォルトの実行コンテキスト・インスタンスが使用されている場合、最初のプロシージャでコールされるSQLJ文でその実行コンテキストが使用されている間も、2番目のプロシージャのSQLJ文でその実行コンテキストが使用されます。このことは許可されています。

関連項目:
「サーバーでの再帰的SQLJコール」

実行コンテキストのメソッド

ここでは、ExecutionContextクラスのpublicメソッドについて説明し、例を示します。

- 状態メソッド

- 制御メソッド

- 取消しメソッド

- バッチ更新メソッド

- セーブポイント・メソッド

- クローズ・メソッド

- 例: ExecutionContextメソッドの使用

状態メソッド

次に示す実行コンテキスト・インスタンスのメソッドを使用すると、そのインスタンスを使用して完了した最新のSQL操作に関するステータス情報を取得できます。

- SQLWarning getWarnings(): java.sql.SQLWarningオブジェクトを戻します(この実行コンテキスト・インスタンスで完了した最新のSQL操作から報告された最初の警告が含まれています)。警告は連鎖的に戻されます。実行コンテキスト・インスタンスのgetWarnings()メソッドを使用して最初の警告を取得し、各SQLWarningオブジェクトのgetNextWarning()メソッドを使用して次の警告を取得します。この連鎖には、SQL操作の実行中に生成されるすべての警告が含まれています。

- int getUpdateCount(): バッチ更新が有効な場合を除いて、これは、この実行コンテキスト・インスタンスで完了した最後のSQL操作で更新された行数を示すint値を戻します。最後のSQL操作がデータ操作言語(DML)文ではなかった場合は、ゼロ(0)を戻します。最後のSQL操作でイテレータまたは結果セットが生成された場合に、QUERY_COUNT定数を戻します。最後のSQL操作が実行完了前に終了された場合、またはこの実行コンテキスト・インスタンスで操作が試行されていない場合は、EXCEPTION_COUNT定数を戻します。
バッチ可能なアプリケーションの場合、getUpdateCount()からの戻り値は、バッチ関連の定数値(NEW_BATCH_COUNT、ADD_BATCH_COUNTまたはEXEC_BATCH_COUNT)のいずれかになります。

関連項目:
「実行コンテキストの更新カウント」

制御メソッド

次に示す実行コンテキスト・インスタンスのメソッドを使用すると、そのインスタンスを使用して実行される以降のSQL操作(まだ開始されていない操作)を制御できます。

- int getMaxFieldSize(): この実行コンテキスト・インスタンスを使用したSQL操作から戻される最大データ量(バイト単位)を示すint値を戻すメソッド。このメソッドが適用されるのは、BINARY、VARBINARY、LONGVARBINARY、CHAR、VARCHARまたはLONGVARCHAR型の列のみです。
デフォルトでは、このパラメータは0(ゼロ)に設定されます。これは、サイズに上限がないことを示します。

- setMaxFieldSize(int): int値を入力パラメータとして取り、フィールド・サイズの上限を変更するメソッド。

- int getMaxRows(): この実行コンテキスト・インスタンスを使用して作成されたJDBC結果セットまたはSQLJイテレータに格納できる最大行数を示すint値を戻すメソッド。上限を超えた場合、エラー・メッセージや警告は出力されずに、超えた分の行が削除されます。
デフォルトでは、このパラメータは0(ゼロ)に設定されます。これは、行数に上限がないことを示します。

- setMaxRows(int): int値を入力パラメータとして取り、最大行数を変更するメソッド。

- int getQueryTimeout(): この実行コンテキスト・インスタンスを使用したSQL操作のタイムアウト時間(秒単位)を示すint値を戻すメソッド。SQL操作がこの期限を過ぎた場合、SQL例外が発生します。
デフォルトでは、このパラメータは0(ゼロ)に設定されます。これは、問合せにタイムアウトの期限がないことを示します。

- setQueryTimeout(int): int値を入力パラメータとして取り、問合せのタイムアウトの期限を変更するメソッド。

- int getFetchSize(): このExecutionContextオブジェクトから生成されたイテレータ・オブジェクトに対して既存のフェッチ・サイズである行数を取得するメソッド。このExecutionContextオブジェクトに、setFetchSize()をコールしてフェッチ・サイズを設定する作業が行われていない場合、戻り値は0(ゼロ)となります。setFetchSize()メソッドをコールすることによって、このExecutionContextオブジェクトにより正のフェッチ・サイズが設定された場合、戻り値はsetFetchSize()で指定したフェッチ・サイズとなります。

- setFetchSize(int): より多くの行が必要な場合にフェッチされる行数に関して、SQLJランタイムにヒントを与えるメソッド。指定した行数は、このExecutionContextオブジェクトを使用して作成したイテレータにのみ影響します。0(ゼロ)を指定すると、実装に依存したデフォルト値がフェッチ・サイズとして使用されます。

- int getFetchDirection(): フェッチしているデータのデフォルトの方向と、このExecutionContextオブジェクトから生成されるスクロール可能なイテレータ・オブジェクトのデフォルトの方向を取得するメソッド。このExecutionContextオブジェクトにsetFetchDirection()をコールすることによってフェッチ方向が設定されていない場合、戻り値はFETCH_FORWARDとなります。

- setFetchDirection(int): スクロール可能なイテレータ・オブジェクトの行が処理される方向に関して、SQLJランタイムにヒントを与えるメソッド。ヒントは、このExecutionContextオブジェクトを使用して作成されるスクロール可能なイテレータ・オブジェクトにのみ適用されます。デフォルト値は次のとおりです。

sqlj.runtime.ResultSetIterator.FETCH_FORWARD.

このメソッドは、与えられた方向がFETCH_FORWARD、FETCH_REVERSEまたはFETCH_UNKNOWN(int定数)のいずれでもない場合に、SQLExceptionをスローします。

取消しメソッド

マルチスレッド環境でSQL操作を取り消す場合や、バッチ更新が有効化されているときに保留文を一括で取り消す場合には、次のメソッドを使用します。

- cancel(): マルチスレッド環境において、あるスレッドで実行中のSQL操作を取り消すには、このメソッドを別のスレッドで操作します。このメソッドを使用すると、この実行コンテキスト・インスタンスを使用して開始した未完了の最終操作が取り消されます。この実行コンテキスト・インスタンスを使用した実行中の文が存在しない場合、このメソッドは機能しません。
バッチ可能な環境で保留文を一括で取り消すには、このメソッドを使用します。バッチが空にされて、バッチ内の文は実行されません。既存のバッチを取り消した場合、次に出現したバッチ可能な文は、新規のバッチに追加されます。

関連項目:
「バッチの取消し」

バッチ更新メソッド

アプリケーションでパフォーマンス強化の機能を使用する場合は、次のメソッドを使用してバッチ更新を制御します。

- int[] executeBatch(): 保留文を一括実行し、int型の更新カウントの配列を戻すメソッド。

関連項目:
「実行コンテキストの更新カウント」、「明示的および暗黙的なバッチ実行」および「バッチ実行中のエラー状態」

- int getBatchLimit(): その時点でのバッチ制限を示すint値を戻すメソッド。バッチ制限がある場合、一括されている文の数が上限に達したバッチは、暗黙的に実行されます。
デフォルトのバッチ制限は、ExecutionContext静的定数値UNLIMITED_BATCH(バッチ制限なし)に設定されます。

関連項目:
「バッチ制限の設定」

- int[] getBatchUpdateCounts(): 最後に実行されたバッチの更新カウントを示すint型の配列を戻すメソッド。このメソッドは、バッチを暗黙的に実行する場合に有効です。

関連項目:
「実行コンテキストの更新カウント」

- boolean isBatching(): バッチ更新の実行可否を示すブール値を戻すメソッド。
これは、現在未完了のバッチがあるかどうかを示しているのではありません。バッチが新規に作成、追加または実行されたかどうかを確認するには、getUpdateCount()メソッドを使用してください。

- setBatching(boolean): バッチ更新を有効化するためのブール値を取るメソッド。
バッチ更新機能は、デフォルトでは無効になります。

関連項目:
「文キャッシングの有効化と無効化(Oracle固有コードの場合)」

- setBatchLimit(int): 現行のバッチ制限を設定するための入力として、0(ゼロ)でない正のint値を取るメソッド。代入可能な値としては、UNLIMITED_BATCH(制限なし)と、AUTO_BATCH(バッチ制限はSQLJランタイムで動的に判定される)の2つがあります。

関連項目:
「バッチ更新機能」

セーブポイント・メソッド

Oracle SQLJ実装は、JDBC 3.0セーブポイントをサポートします。セーブポイントはExecutionContextインスタンスに格納され、SQLJのセーブポイント文をサポートするために次のpublicメソッドがあります。

- Object oracleSetSavepoint(ConnectionContextImpl, String)
セーブポイントを登録し、Objectインスタンスとして戻します。このメソッドでは、sqlj.runtime.ref.ConnectionContextImplクラスのインスタンスおよびセーブポイント名を指定する文字列として接続コンテキストを取ります。

Oracle SQLJ実装は、java.sql.Savepointインタフェースを拡張するoracle.jdbc.OracleSavepointクラスのインスタンスとして、セーブポイントをインスタンス化します。Savepointインタフェースには、Java Development Kit (JDK) 1.4が必要です。このメソッドに対してObjectインスタンスを使用することで、JDK 1.4が必要なくなります。

- void oracleRollbackToSavepoint (ConnectionContextImpl, Object)
指定されているセーブポイントまでの変更をロールバックします。このメソッドでは、接続コンテキストをConnectionContextImplのインスタンスとして取り、セーブポイントをObjectインスタンスとして取ります。

- void oracleReleaseSavepoint(ConnectionContextImpl, Object)
指定されているセーブポイントを解放します。このメソッドでは、接続コンテキストをConnectionContextImplのインスタンスとして取り、セーブポイントをObjectインスタンスとして取ります。

通常、これらのメソッドを直接使用するかわりに、SQLJのセーブポイント文を使用します。

クローズ・メソッド

Oracle SQLJ実装では、ExecutionContextクラスのclose()メソッドに拡張機能が用意されています。

- close(): リソースのリークを回避するには、次のすべての状況に該当する場合にこのメソッドを使用します。

- Oracle固有コード生成を使用している場合。

- 接続コンテキスト・インスタンスを介して使用可能なデフォルトのインスタンスを使用するのではなく、ExecutionContextインスタンスを明示的に作成して使用している場合。

- ExecutionContextインスタンスを使用してSQLJロールバック文またはコミット文を明示的に発行していない場合。

#sql [ec] { COMMIT };
#sql [ec] { ROLLBACK };

- ExecutionContextインスタンスでexecuteBatch()をコールしていない場合。

このような状況下では、ExecutionContextインスタンス上でバッチ可能文がオープンしたままとなる可能性があり、そのうちにデータベース・カーソルを使い果たすことがあります。これを回避するには、次の例のようにclose()メソッドを使用します。

Execution Context ec = new ExecutionContext();
...
try {
...
#sql [ec] { SQL operation };
...
} finally { ec.close(); }

注意:
明示的に宣言されるかわりに実行コンテキスト・インスタンスが接続コンテキスト・インスタンスに関連付けられている場合は、基になるJDBC接続のクローズと一緒に、または別に接続コンテキスト・インスタンスをクローズすると、実行コンテキスト・インスタンス上に残っているすべての文が自動的に終了されます。

例: ExecutionContextメソッドの使用

次のコードは、ExecutionContextメソッドの使用方法の一例です。

ExecutionContext execCtx =
DefaultContext.getDefaultContext().getExecutionContext();

// Wait only 3 seconds for operations to complete
execCtx.setQueryTimeout(3);

// delete using execution context of default connection context
#sql { DELETE FROM emp WHERE sal > 10000 };

System.out.println
("removed " + execCtx.getUpdateCount() + " employees");

実行コンテキストとマルチスレッドの関係

1つの実行コンテキストで複数のスレッドを使用しないでください。複数のスレッドを使用した場合に、2つのSQLJ文で同じ実行コンテキストが同時に使用されると、最初の文の処理が完了するまで2番目の文がブロックされます。また、最初の操作からのステータス情報が、その情報が取り出される前に上書きされることがあります。

そのため、1つの接続コンテキスト・インスタンスで複数のスレッドを使用している場合は、次の手順で操作を行ってください。

1. スレッドごとに一意の実行コンテキスト・インスタンスをインスタンス化します。

2. #sql文で実行コンテキストを指定し、各スレッドで該当の実行コンテキストを使用するようにします。

スレッドごとに別の接続コンテキスト・インスタンスを使用している場合、実行コンテキスト・インスタンスをインスタンス化して、指定する必要はありません。接続コンテキスト・インスタンスごとに、そのインスタンスに対するデフォルトの実行コンテキスト・インスタンスが暗黙的に対応付けられているためです。

注意:
パフォーマンス上の理由から、SQLJでは、Oracle固有生成コードのExecutionContextインスタンスに対する同期が追加実行されません。そのため、必ず、1つの実行コンテキスト・インスタンスを複数のスレッドで使用しないようにする必要があります。複数のスレッドで同じ実行コンテキストを使用すると、ブロック化ではなくてアプリケーションで、不正な結果やNullPointer例外などのエラーが発生します。

SQLJでのマルチスレッド

ここでは、SQLJのサポート、マルチスレッドの要件、マルチスレッドと実行コンテキスト・インスタンスとの関係について説明します。

SQLJを使用して、マルチスレッド・アプリケーションを記述できます。ただし、SQLJアプリケーションでマルチスレッドを使用すると、JDBCドライバまたは専用のデータベース・アクセス用のデバイスになんらかの制限が発生します。この制限には、同期に関する制限も含まれています。

スレッドごとに異なる実行コンテキスト・インスタンスを使用してください。それには、次の2通りの方法があります。

- SQLJ文に接続コンテキスト・インスタンスを指定し、スレッドごとに異なる接続コンテキスト・インスタンスが使用されるようにします。接続コンテキスト・インスタンスごとに、デフォルトの実行コンテキスト・インスタンスが自動的に対応付けられます。

- 同じ接続コンテキスト・インスタンスで複数のスレッドを使用している場合は、実行コンテキスト・インスタンスを追加して宣言します。次に、スレッドごとに異なる実行コンテキスト・インスタンスが使用されるように、SQLJ文で実行コンテキスト・インスタンスを指定します。

関連項目:
「接続コンテキスト・インスタンスと実行コンテキスト・インスタンスの指定」

Oracle JDBCドライバのいずれかを使用している場合は、必要に応じて、同じ接続コンテキスト・インスタンスを複数のスレッドで使用できますが、これは、異なる実行コンテキスト・インスタンスが指定されて、直接見える同期要求がない場合に限られます。ただし、データ・アクセスは順次処理される点に注意してください。データには、常に1つのスレッドのみがアクセスします。同期は、スレッドを通じて実行されるSQL操作の様々な段階の制御フローを指します。たとえば、各文で入力パラメータはバインドされて、文が実行され、出力パラメータをバインドできます。JDBCドライバの中には、これらの段階が入り混じらないように特別な配慮が必要がものもあります。

ISO標準コード生成の場合、あるスレッドが、別の操作で使用されている実行コンテキストを使用するSQL操作を実行すると、現行の操作が完了するまでスレッドがブロックされます。実行コンテキストが2つのスレッド間で共有されている場合、一方のスレッドで実行されたSQL操作の結果は、もう一方のスレッドで認識できます。両方のスレッドがSQL操作を実行している場合、競合状態が発生する可能性があります。つまり、一方のスレッドが元の結果を処理する前に、そのスレッドの実行結果がもう一方のスレッドの実行結果で上書きされる場合があります。このため、複数のスレッドが同じ実行コンテキスト・インスタンスを共有することは不可能です。

注意:
前述の説明は、デフォルトのOracle固有コード生成には適用されません。パフォーマンス上の理由から、SQLJでは、Oracle固有生成コードのExecutionContextインスタンスに対する同期が追加実行されません。そのため、必ず、1つの実行コンテキスト・インスタンスを複数のスレッドで使用しないようにする必要があります。複数のスレッドで同じ実行コンテキストを使用すると、ブロック化ではなくてアプリケーションで、不正な結果やNullPointer例外などのエラーが発生します。

マルチスレッド: MultiThreadDemo.sqlj

次は、マルチスレッドを使用したSQLJアプリケーションの例です。データが永続的に変更されるのを防ぐために、ROLLBACK操作の実行後に接続を終了します。

import java.sql.SQLException;
import java.util.Random;
import sqlj.runtime.ExecutionContext;
import oracle.sqlj.runtime.Oracle;
/**
Each instance of MultiThreadDemo is a thread that gives all employees
a raise of some ammount when run.  The main program creates two such
instances and computes the net raise after both threads have completed.
**/
class MultiThreadDemo extends Thread
{
double raise;
static Random randomizer = new Random();

public static void main (String args[])
{
try {
// set the default connection to the URL, user, and password
// specified in your connect.properties file
Oracle.connect(MultiThreadDemo.class, "connect.properties");
double avgStart = calcAvgSal();
MultiThreadDemo t1 = new MultiThreadDemo(250.50);
MultiThreadDemo t2 = new MultiThreadDemo(150.50);
t1.start();
t2.start();
t1.join();
t2.join();
double avgEnd = calcAvgSal();
System.out.println("average salary change: " + (avgEnd - avgStart));
} catch (Exception e) {
System.err.println("Error running the example: " + e);
}
try { #sql { ROLLBACK }; Oracle.close(); } catch (SQLException e) { }
}
static double calcAvgSal() throws SQLException
{
double avg;
#sql { SELECT AVG(sal) INTO :avg FROM emp };
return avg;
}
MultiThreadDemo(double raise)
{
this.raise = raise;
}
public void run()
{
// Since all threads will be using the same default connection
// context, each run uses an explicit execution context instance to
// avoid conflict during execution
try {
delay();
ExecutionContext execCtx = new ExecutionContext();
#sql [execCtx] { UPDATE EMP SET sal = sal + :raise };
int updateCount = execCtx.getUpdateCount();
System.out.println("Gave raise of " + raise + " to " +
updateCount + " employees");
} catch (SQLException e) {
System.err.println("error updating employees: " + e);
}
}
// delay is used to introduce some randomness into the execution order
private void delay()
{
try {
sleep((long)Math.abs(randomizer.nextInt()/10000000));
} catch (InterruptedException e) {}
}
}

イテレータ・クラスの実装と拡張機能

ここでは、イテレータ・クラスの実装方法、および基本メソッド以外に使用可能な追加機能について説明します。内容は次のとおりです。

- イテレータ・クラスの実装と機能

- イテレータ宣言でのIMPLEMENTS句の使用

- イテレータ・クラスの拡張のサポート

- 結果セット・イテレータ

- スクロール可能なイテレータ

イテレータ・クラスの実装と機能

宣言した名前付きイテレータ・クラスは、SQLJトランスレータによって生成され、sqlj.runtime.NamedIteratorインタフェースが実装されます。NamedIteratorインタフェースを実装しているクラスには、位置ではなく名前で、イテレータ列をデータベース列にマッピングする機能があります。

宣言した位置イテレータ・クラスは、SQLJトランスレータによって生成され、sqlj.runtime.PositionedIteratorインタフェースが実装されます。PositionedIteratorインタフェースを実装しているクラスには、名前ではなく位置で、イテレータ列をデータベース列にマッピングする機能があります。

NamedIteratorインタフェースとPositionedIteratorインタフェースの両方、そしてすべての生成されたSQLJイテレータ・クラスは、sqlj.runtime.ResultSetIteratorインタフェースを実装または拡張します。

すべてのSQLJイテレータでは、ResultSetIteratorインタフェースで次のメソッドが指定されます。

- close(): イテレータを終了するメソッド

- ResultSet getResultSet(): 基になるJDBC結果セットをイテレータから抽出するメソッド

- boolean isClosed(): イテレータが終了しているかどうかを判定するメソッド

- boolean next(): イテレータの次の行に移動するメソッド(移動できる有効な行がある場合、trueが戻り値)

PositionedIteratorインタフェースは、次のメソッド仕様部を位置イテレータに追加します。

- boolean endFetch(): 位置イテレータの最後の行に到達したかどうかを判定するメソッド

next()メソッドを使用して名前付きイテレータおよびアクセッサ・メソッドの行を進んでデータを取得します。名前付きイテレータ・クラスのSQLJ生成では、各イテレータ列に対してアクセッサ・メソッドが定義されますが、各メソッドの名前は対応する列名と同じになります。たとえば、name列を宣言すると、name()メソッドが生成されます。

FETCH INTO文をendFetch()メソッドと一緒に使用して、位置イテレータの行を進んで、データを取得します。FETCH INTO文では、暗黙的にnext()メソッドがコールされます。特別なFETCH CURRENT構文を使用していない場合は、next()メソッドを位置イテレータで明示的に使用しないでください。このFETCH INTO文では、イテレータ列番号に従って名前付けされたアクセッサ・メソッドも暗黙的にコールされます。位置イテレータ・クラスのSQLJ生成では、各イテレータ列のアクセッサ・メソッドが定義されますが、各メソッドの名前は列の位置と対応します。

関連項目:
「FETCH CURRENT構文: JDBC結果セットからSQLJイテレータへ」

close()メソッドを使用して、操作の終了したイテレータを終了します。getResultSet()メソッドは、SQLJとJDBCの連係動作の中心となるメソッドです。

関連項目:
「SQLJイテレータとJDBC結果セットの連係動作」

注意:
かわりに、ResultSetIteratorインスタンスまたはScrollableResultSetIteratorインスタンスを弱い型指定のイテレータとして直接使用できます。(ScrollableResultSetIteratorは、ResultSetIteratorを拡張します。)これは、JDBC結果セットに変換することのみが目的で、名前付きまたは位置イテレータの機能が不要である場合に、便利な方法です。また、SQLJのFETCH CURRENT構文でもアクセスできます。

イテレータ宣言でのIMPLEMENTS句の使用

イテレータ宣言でインタフェースを実装すると便利な場合があります。たとえば、イテレータ・クラスがあり、そのクラスで1つ以上の列へのアクセスを制限するとします。SQLJで生成された名前付きイテレータ・クラスには、イテレータの各列にアクセッサ・メソッドがあります。特定の列へのアクセスを制限する必要がある場合に、アクセッサ・メソッドのサブセットのみでインタフェースを作成できるときは、イテレータ・クラス型のインスタンスを公開するのではなく、そのインタフェース型のインスタンスをユーザーに公開します。

たとえば、従業員データの名前付きイテレータを作成し、それにENAME(従業員名)、EMPNO(従業員番号)およびSAL(給与)の各列を定義するとします。その場合、次のように指定します。

#sql iterator EmpIter (String ename, int empno, float sal);

この文を実行すると、ename()、empno()およびsal()の各アクセッサ・メソッドが定義されたクラスEmpIterが生成されます。

SAL列にアクセスできないようにするとします。ename()メソッドおよびempno()メソッドはあるが、sal()メソッドはないEmpIterIntfcインタフェースを作成できます。前述の宣言のかわりに、次のイテレータ宣言の使用も可能です(EmpIterIntfcがmypackageパッケージ内にあるとします)。

#sql iterator EmpIter implements mypackage.EmpIterIntfc
(String emame, int empno, float sal);

EmpIterIntfcインスタンスからしかユーザーがデータにアクセスできないようにアプリケーションをコーティングすると、SAL列にはアクセスできなくなります。

イテレータ・クラスの拡張のサポート

SQLJは、イテレータ・クラスの拡張機能をサポートしています。この拡張は、問合せおよび問合せの結果へ追加できる機能なので、非常に便利です。

イテレータ・サブクラスに関する主要な要件の1つは、sqlj.runtime.RTResultSetインスタンスを入力として取るpublicコンストラクタを宣言することです。SQLJランタイムでは、問合せ結果をサブクラスのインスタンスに割り当てる際にこのコンストラクタがコールされるためです。しかしもっと重要なのは、必要な機能を指定することです。

元のイテレータ・クラス(使用するサブクラスのスーパークラス)の機能を使用することも可能です。たとえば、各問合せ結果の中で次に進むときは、super.next()メソッドをコールすることも可能です。

結果セット・イテレータ

SQLJイテレータの強い型指定の機能が必要ない場合があります。

そのような場合は、sqlj.runtime.ResultSetIterator型のインスタンスを直接使用して、問合せデータを取得できるため、名前付きイテレータ・クラスや位置イテレータ・クラスを宣言する必要はありません。かわりに、ResultSetIteratorを拡張するsqlj.runtime.ScrollableResultSetIterator型を使用できます。これにより、SQLJのスクロール可能なイテレータ機能を使用できます。強い型指定のイテレータではなく、結果セット・イテレータを使用すると、イテレータ・クラスを宣言しなくて済むかわりに、SQLJ SELECT操作に対する厳密な分類のチェックを実行できなくなります。

すべての名前付きイテレータ・クラスと位置イテレータ・クラスは、ResultSetIteratorインタフェースに基づいており、このインタフェースでgetResultSet()メソッドおよびclose()メソッドが指定されます。SQLJを使用して結果セット・イテレータ・インスタンスを処理する場合は、ScrollableResultSetIteratorインスタンスおよびFETCH CURRENT構文を使用します。

関連項目:
「FETCH CURRENT構文: JDBC結果セットからSQLJイテレータへ」

JDBCを使用して結果セット・イテレータ・インスタンスを処理する場合は、そのgetResultSet()メソッドを使用して、基になる取得した結果セットを処理することができます。結果セット・イテレータをその基になる結果セットを介して処理する場合、操作の終了後に、結果セットではなく結果セット・イテレータを終了する必要があります。結果セット・イテレータを終了すると結果セットも終了しますが、結果セットを終了しても結果セット・イテレータは終了しません。

関連項目:
「弱い型指定のイテレータ(ResultSetIterator)の使用と変換」

注意:
Oracle SQLJ実装では、結果セット・イテレータのホスト式としての使用と、FETCH文でのカーソル表現をサポートしています。この機能は、Oracle9i データベースより前のデータベースではサポートされていません。

スクロール可能なイテレータ

SQLJのISO規格では、スクロール可能なJDBC結果セットのためのJDBC 2.0仕様に合せて作成された機能によって、スクロール可能なイテレータをサポートしています。Oracle SQLJ実装では、この機能がサポートされています。

関連項目:
『Oracle Database JDBC開発者ガイドおよびリファレンス』

スクロール可能なイテレータの宣言

イテレータをスクロール可能として設定するには、イテレータの宣言に次の句を追加します。

implements sqlj.runtime.Scrollable

これにより、SQLJトランスレータでScrollableインタフェースを実装したイテレータが生成されます。次に、スクロール可能な名前付きイテレータ宣言の例を示します。

#sql public static MyScrIter implements sqlj.runtime.Scrollable
(String ename, int empno);

SQLJトランスレータによりMyScrIterクラスに対して生成されたコードは、スクロール可能なインタフェースのすべてのメソッドを自動的にサポートします。

スクロール可能なイテレータの更新検出

基になるデータへの変更を検出できるように、スクロール可能な結果セットと同様に、スクロール可能なイテレータを宣言できます。Oracle SQLJ実装のスクロール可能なイテレータのsensitivity設定は、デフォルトではINSENSITIVEであり、基になるデータにどのような変更があっても検出されません。ただし、with句を使用して、この設定を変更できます。次の例では、更新検出を指定して、前の例を拡張しています。

#sql public static MyScrIter implements sqlj.runtime.Scrollable
with (sensitivity=SENSITIVE)
(String ename, int empno);

注意:
implements句はwith句の前に置く必要があります。

SQLJ規格ではASENSITIVEも設定可能であり、この設定はデータベースのデフォルトのsensitivityを受け入れることを意味します。ただし、OracleではsensitivityをASENSITIVEに設定すると、デフォルト設定のINSENSITIVEが使用されることになります。

前述の宣言がある場合、MyScrIterインスタンスはデータ変更に反応し、フェッチ・サイズ・ウィンドウなどの要因によって変わります。

関連項目:
スクロール可能な結果セットの詳細は、『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

スクロール可能なインタフェース

ここでは、sqlj.runtime.Scrollableインタフェースの重要なメソッドを説明します。

スクロール可能なインタフェースのフェッチ方向についてのヒントを提供します。次のメソッドは、実行コンテキスト上のみでなくスクロール可能なイテレータ上でも定義されます。ExecutionContextインスタンスを使用して、デフォルトの方向がスクロール可能なイテレータの生成で使用されるようにします。

- setFetchDirection(int): 行が処理される方向に関して、SQLJランタイムにヒントを与えるメソッド。方向は、sqlj.runtime.ResultSetIterator.FETCH_FORWARD、FETCH_REVERSEまたはFETCH_UNKNOWNのいずれかである必要があります。
ExecutionContextで方向に対する値を指定しない場合、FETCH_FORWARDがデフォルトとして使用されます。

- int getFetchDirection(): その時点でのデータ行をフェッチする方向(前述の整数の定数のいずれか)を取り出すメソッド。

また、基になる結果セットにイテレータ・オブジェクトの現在の位置情報を戻す、スクロール可能なイテレータのメソッドもいくつかあります。これらのメソッドはすべて、イテレータの基となる結果セットに行が含まれない場合は常にfalseを戻します。

- boolean isBeforeFirst(): イテレータ・オブジェクトが結果セットの最初の行の前にあるかどうかを識別するメソッド。

- boolean isFirst(): イテレータ・オブジェクトが結果セットの最初の行にあるかどうかを識別するメソッド。

- boolean isLast(): イテレータ・オブジェクトが結果セットの最後の行にあるかどうかを識別するメソッド。isLast()メソッドをコールすると、負荷が高くなる場合がありますが、これは、JDBCドライバで現在の行が結果セットの最終行であるかどうかを判別するために、1つ先の行をフェッチする必要がある場合があるためです。

- boolean isAfterLast(): イテレータ・オブジェクトが結果セットの最後の行より後にあるかどうかを識別するメソッド。

注意:
ナビゲーションのその他のメソッドも、Scrollableインタフェースで定義されており、同様に使用できます。

スクロール可能な名前付きイテレータ

名前付きイテレータでは、Scrollableインタフェースで定義されたナビゲーション・メソッドを使用して、結果セットの行を移動できます。前述のように、スクロールしないイテレータには、次のナビゲーション・メソッドのみがあります。

- boolean next(): 結果セットの最終行にイテレータ・オブジェクトを移動するメソッド。

関連項目:
「名前付きイテレータの使用」

追加のナビゲーション・メソッドは、スクロール可能な名前付きイテレータで使用できます。これらのメソッド・ファンクションは、next()と類似した機能を実行します。その際、結果セットの実際の行上にイテレータを配置しようとします。イテレータが有効な行に配置された場合はtrueを、そうでない場合はfalseを戻します。さらに、結果セット内の最初の行の前または最終行の後にイテレータ・オブジェクトを配置すると、イテレータ・オブジェクトがそれぞれ最初の前、最後の後の位置に配置されます。

次のメソッドがサポートされます。

- boolean previous(): 結果セットの以前の行にイテレータ・オブジェクトを移動するメソッド。

- boolean first(): 結果セットの最初の行にイテレータ・オブジェクトを移動するメソッド。

- boolean last(): 結果セットの最終行にイテレータ・オブジェクトを移動するメソッド。

- boolean absolute(int): 結果セットの指定された行番号にイテレータ・オブジェクトを移動するメソッド。最初の行は1、2番目の行は2というように数えられます。行番号がマイナスの場合、イテレータ・オブジェクトは、結果セットの最終行に対する相対的な行位置に移動します。たとえば、absolute(-1)をコールすると、イテレータ・オブジェクトは最終行に配置され、absolute(-2)をコールすると最後から2番目の行に配置されることになります。

- boolean relative(int): 現在の位置からプラスまたはマイナスのいずれかの相対行番号へイテレータ・オブジェクトを移動するメソッド。relative(0)のコールは有効ですが、イテレータの位置は変わりません。

- void beforeFirst(): 結果セットの冒頭、つまり最初の行の前にイテレータ・オブジェクトを移動するメソッド。結果セットに行がない場合は、機能しません。

- void afterLast(): 結果セットの最後、つまり最終行の後にイテレータ・オブジェクトを移動するメソッド。結果セットに行がない場合は、機能しません。

注意:
beforeFirst()メソッドおよびafterLast()メソッドは、イテレータ・オブジェクトを結果セット上の実際の行に配置しないため、voidを戻します。

スクロール可能な位置イテレータ

位置イテレータの汎用的なFETCH構文は、「位置イテレータの使用」を参照してください。次に例を示します。

#sql { FETCH :iter INTO :x, :y, :z };

これは、実際には次の構文の省略バージョンです。

#sql { FETCH NEXT FROM :iter INTO :x, :y, :z  };

結果セットの以前の行、最初の行または最後の行に移動する別のパターンです。ただし、移動メソッドがモデル化された後のJDBC 2.0ではprevious()が使用されています。SQLを基本としたFETCHではPRIORが採用されています。この矛盾を忘れた場合でも、Oracle Database 11g SQLJトランスレータではFETCH PREVIOUSも受け入れられます。

構文は次のとおりです。

#sql { FETCH PRIOR FROM :iter INTO :x, :y, :z  };
#sql { FETCH FIRST FROM :iter INTO :x, :y, :z  };
#sql { FETCH LAST FROM :iter INTO :x, :y, :z  };

数値を渡して絶対的または相対的な移動を行う構文もあります。特定の行(絶対行)に移動したり、その時点での位置から前または後ろに移動することができます。構文は次のとおりです。

#sql { FETCH ABSOLUTE :n FROM :iter INTO :x, :y, :z  };
#sql { FETCH RELATIVE :n FROM :iter INTO :x, :y, :z  };

注意:
このような構文を作成した場合、FETCHが有効な行へ移動できずに値を取得することに失敗した場合でも、イテレータのendFetch()メソッドは常にtrueを戻します。

必ずホスト式を使用して、移動を指定してください。数値の定数のみを使用することはできません。次の構文ではなく、

#sql { FETCH RELATIVE 0 FROM :iter INTO :x, :y, :z };

このように記述する必要があります。

#sql { FETCH RELATIVE :(0) FROM :iter INTO :x, :y, :z  };

このコマンドはイテレータの位置を変更しません。イテレータが有効な行にある場合、このコマンドは変数に代入します。

注意:
ナビゲーション・メソッドとFETCH CURRENT構文を組み合せることによって、スクロール可能な位置イテレータで移動できます。

FETCH CURRENT構文: JDBC結果セットからSQLJイテレータへ

既存のJDBCプログラムをできるだけ修正せずにSQLJで書き換えたい場合を想定します。

JDBC結果セットでは、next()、previous()、absolute()などの移動メソッドのみを使用します。名前付きイテレータを使用してSQLJ内でこれを迅速にモデル化できます。ただし、このためには、SQL結果セットのすべての列に適切な名前が必要です。実際は、結果セットの多くの(すべてではないにしても)列でエイリアス名が必要となります。この方法は、問合せテキストを加工しないでおく場合は、使用できません。

別の方法は、問合せソースを変更しないために、結果セットの位置イテレータ型を定義する方法です。ただし、このアプローチでは、プログラムのコントロールフロー・ロジックを変更する必要があります。次のJDBCコードのサンプルで確認します。

ResultSet rs = ... // execute ...query...;
while (rs.next()) {
x := rs.getXxx(1); y:=rs.getXxx(2);
...process...
}

これで、次の行をSQLJに変換します。

MyIter iter;
#sql iter = { ...query... };
while(true) {
#sql { FETCH :iter INTO :x, :y };
if (iter.endFetch()) break;
...process...
}

スクロール可能なイテレータ上での任意の移動を想定した場合、プログラム・ロジックへの変換はより困難になります。位置イテレータは名前付きイテレータの移動コマンドをすべて実装しているため、これを利用し、イテレータから変数を代入させるためにRELATIVE :(0)を使用できます。

MyIter iter;
#sql iter = { ...query... };
while (iter.next()) {
#sql { FETCH RELATIVE :(0) FROM :iter INTO :x, :y };
...process...
}

これで、元の問合せおよび元のプログラム・ロジックをそのまま利用できます。ただし、このアプローチにはまだデメリットが1つあります。つまり、このプロパティが実際に必要でない場合でも、MyIterイテレータ型には、Scrollableインタフェースを実装する必要があります。これに対処するため、Oracle SQLJ実装は次の構文拡張機能をサポートしています。

#sql { FETCH CURRENT FROM :iter INTO :x, :y, :z  };

この構文の場合、スクロール可能なイテレータと同様にスクロールしないイテレータに対してもJDBCの例をSQLJに書き換えられます。

AnyIterator ai;
#sql ai = { ...query... };
while (ai.next()) {
#sql { FETCH CURRENT FROM :ai INTO :x, :y };
...process...
}

スクロール可能な結果セット・イテレータ

Oracle SQLJ実装での弱い型指定の結果セットへのサポートには、スクロール可能な結果セット・イテレータ型が含まれています。

package sqlj.runtime;
public interface ScrollableResultSetIterator
extends ResultSetIterator
implements Scrollable
{ }

この型はsqlj.runtime.ResultSetIteratorを拡張しているため、「結果セット・イテレータ」のメソッドがサポートされています。

また、sqlj.runtime.Scrollableインタフェースも実装されたため、「スクロール可能なインタフェース」および「スクロール可能な名前付きイテレータ」に説明されているメソッドがサポートされています。

さらに、スクロール可能な結果セット・イテレータでは、「FETCH CURRENT構文: JDBC結果セットからSQLJイテレータへ」に説明されているFETCH CURRENT構文がサポートされています。

次のJDBCコードを考えます。

Statement st = conn.createStatement("SELECT ename, empid FROM emp");
ResultSet rs = st.executeQuery();
while (rs.next()) {
x = rs.getString(1);
y = rs.getInt(2);
}
rs.close();

SQLJ結果セット・イテレータを使用して、同じ内容を次のコードで記述できます。

sqlj.runtime.ResultSetIterator rsi;
#sql rsi = { SELECT ename, empid FROM emp };
while (rsi.next()) {
#sql { FETCH CURRENT FROM :rsi INTO :x, :y };
}
rsi.close();

スクロール機能を活用して、次のコードを記述することもできます。

sqlj.runtime.ScrollableResultSetIterator srsi;
#sql srsi = { SELECT ename, empid FROM emp };
srsi.afterLast();
while (srsi.previous()) {
#sql { FETCH CURRENT FROM :srsi INTO :x, :y };
}
srsi.close();

詳細なトランザクション制御

SQLJでは、トランザクションのアクセス・モードと分離レベルを指定できる、SQL SET TRANSACTION文がサポートされています。標準SQLJでは、READ ONLYおよびREAD WRITEアクセス・モード設定がサポートされていますが、Oracle JDBC実装ではREAD ONLYはサポートされていません。ただし、アクセス権を設定して、アクセス・モードと同じ効果を得ることができます。分離レベルとしては、SERIALIZABLE、READ COMMITTED、READ UNCOMMITTEDおよびREPEATABLE READを設定できます。ただし、Oracle SQL実装では、READ UNCOMMITTEDまたはREPEATABLE READはサポートされていません。

READ WRITEは、標準SQLとOracle SQL実装のデフォルトのアクセス・モードです。READ COMMITTEDはOracle SQL実装でのデフォルトの分離レベルです。SERIALIZABLEは標準SQLでのデフォルトの分離レベルです。

ここでは詳細を示します。

- SET TRANSACTION構文

- アクセス・モードの設定

- 分離レベルの設定

- JDBC接続クラスのメソッドの使用

関連項目:
「基本的なトランザクション制御」

SET TRANSACTION構文

SQLJのSET TRANSACTION文の構文は次のようになります。

#sql { SET TRANSACTION <access_mode>, <ISOLATION LEVEL isolation_level> };

この文に接続コンテキスト・インスタンスを指定しなかった場合は、デフォルトの接続が適用されます。SET TRANSACTIONを使用する場合、それがDML文の前に定義され、トランザクション内で最初の文であることが必要です。つまり、データベースへの接続、あるいは最新のCOMMITまたはROLLBACK以降、最初の文であることが必要です。

標準SQLJで設定したアクセス・モードや分離レベルは、以降のトランザクション開始時に明示的にリセットしないかぎり、トランザクション全体にわたって有効のままになっています。標準SQLJ SET TRANSACTION文では、最初に分離レベルを指定することも、アクセス・モードのみ、または分離レベルのみを指定することも可能です。たとえば、次のように指定します。

#sql { SET TRANSACTION READ WRITE };

#sql { SET TRANSACTION ISOLATION LEVEL SERIALIZABLE };

#sql { SET TRANSACTION READ WRITE, ISOLATION LEVEL SERIALIZABLE };

#sql { SET TRANSACTION ISOLATION LEVEL READ COMMITTED, READ WRITE };

SET TRANSACTION文には、デフォルト接続を適用することも、特定の接続コンテキスト・インスタンスも指定できます。

#sql [myCtxt] { SET TRANSACTION ISOLATION LEVEL SERIALIZABLE };

SQLJでは、1つのSET TRANSACTION文で、アクセス・モードと分離レベルの両方を設定できます。これは、サーバー・マネージャやSQL*Plusなどの他のOracle SQLツールには当てはまらず、1つの文にアクセス・モードと分離レベルのいずれか一方しか設定できません。

アクセス・モードの設定

READ WRITEとREAD ONLYの各アクセス・モード設定(サポートされている場合)の機能は次のとおりです。

- READ WRITE (デフォルト): READ WRITEトランザクションでは、ユーザーはデータベースを更新できません。SELECT、INSERT、UPDATEおよびDELETEのすべてを実行できます。

- READ ONLY(Oracle JDBC実装でもサポートされています): READ ONLYトランザクションの場合、データベースの更新はユーザーに許可されていません。SELECTは実行できますが、INSERT、UPDATE、DELETEおよびSELECT FOR UPDATEは実行できません。

分離レベルの設定

READ COMMITTED、SERIALIZABLE、READ UNCOMMITTEDおよびREPEATABLE READの各分離レベルには(サポートされている場合)、次の機能があります。

- READ UNCOMMITTED: dirty read、non-repeatable read、phantom readのすべてが許可されます。

- READ COMMITTED(デフォルト): dirty readは許可されませんが、non-repeatable readとphantom readは許可されます。トランザクションに、他のトランザクションで行をロックするDML文が含まれている場合、そのトランザクションで必要な行のロックが他のトランザクションによって解除されるまで、文がブロックされます。

- REPEATABLE READ: dirty readとnon-repeatable readは許可されませんが、phantom readは許可されます。

- SERIALIZABLE: dirty read、non-repeatable read、phantom readのすべてが許可されません。トランザクション内のDML文では、トランザクション開始後に変更がコミットされたリソースを更新できません。そのようなDML文は、失敗します。

dirty readは、トランザクションBがトランザクションAによって更新された行にアクセスし、その後でトランザクションAがその更新をロールバックした場合に起こります。その結果、トランザクションBは、実際にはデータベースにコミットされていないデータを扱っていることになります。

non-repeatable readは、トランザクションAが行を取得し、次にトランザクションBがその行を更新し、その後でトランザクションAが同じ行を再度取得した場合に起こります。トランザクションAは同じ行を2回取得しますが、取得した内容が異なります。

phantom readは、トランザクションAが特定の条件を満たす行のセットを取得し、次にトランザクションAの条件を満たす行をトランザクションBが挿入または更新し、その後でトランザクションAが条件に基づいて行を取得した場合に起こります。トランザクションAは追加された行を扱っていることになります。その行をphantomと呼びます。

4つの分離レベルは、次の順で移行します。

SERIALIZABLE > REPEATABLE READ > READ COMMITTED > READ UNCOMMITTED

たとえば、Oracle Database 11g を使用している場合に、REPEATABLE READやREAD UNCOMMITTEDを設定できない場合、上位の(1つ右の)分離レベルを設定して、必要な分離レベルがカバーされるようにします。

関連項目:
『Oracle Databaseアドバンスト・アプリケーション開発者ガイド』

JDBC接続クラスのメソッドの使用

必要に応じて、接続コンテキスト・インスタンスの基になるJDBC接続インスタンスのメソッドを使用して、トランザクションのアクセス・モードと分離レベルにアクセスし、それらを設定できます。ただし、これらのJDBCメソッドを使用したSQLJコードは、移植性が高くないので、お薦めしません。

次は、アクセス・モードと分離レベルを設定するConnectionクラスのメソッドです。

- abstract int getTransactionIsolation(): カレント・トランザクションの分離レベルを示す、次のいずれかの定数の値を戻すメソッド
TRANSACTION_NONE TRANSACTION_READ_COMMITTED TRANSACTION_SERIALIZABLE TRANSACTION_READ_UNCOMMITTED TRANSACTION_REPEATABLE_READ

- abstract void setTransactionIsolation(int): 前述のいずれかの定数を入力パラメータとして取り、トランザクションの分離レベルを設定するメソッド

- abstract boolean isReadOnly(): トランザクションがREAD ONLYの場合はtrueを戻します。トランザクションがREAD WRITEの場合は、falseを戻します。

- abstract void setReadOnly(boolean): trueが入力された場合は、トランザクションのアクセス・モードをREAD ONLYに設定します。falseが入力された場合は、アクセス・モードをREAD WRITEに設定します。

SQLJとJDBCの連係動作

通常、SQLJ文は静的SQL操作で使用されます。Oracle Database 11gでは動的SQLをサポートする拡張機能もありますが、別の方法として、動的操作のためにJDBCコードをSQLJアプリケーション内で使用することも可能であり、この方が移植性が高くなります。また、JDBCコードをSQLJアプリケーションで使用すると便利になるだけでなく、それを使用する必要がある状況もあります。このような理由から、SQLJでは、SQLJ文とJDBC文を同時に使用して、SQLJコンストラクトとJDBCコンストラクトが連係動作できるようになっています。

SQLJとJDBC間のトランザクションでは、次の2つが特に有用です。

- SQLJ接続コンテキストとJDBC接続間のトランザクション

- SQLJイテレータとJDBC結果セット間のトランザクション

関連項目:
『Oracle Database JDBC開発者ガイドおよびリファレンス』

ここでは、次の項目について説明します。

- SQLJ接続コンテキストとJDBC接続の連係動作

- SQLJイテレータとJDBC結果セットの連係動作

SQLJ接続コンテキストとJDBC接続の連係動作

SQLJでは、SQLJ接続コンテキスト・インスタンスからJDBC接続インスタンスに変換することも、その逆に変換することも可能です。

注意:
SQLJ接続コンテキストとJDBC接続間で変換する場合、この2つのオブジェクトは基になる同じ物理接続を共有していることに注意してください。

接続コンテキストからJDBC接続への変換

JDBC操作をSQLJで確立したデータベース接続によって実行する場合(たとえば、アプリケーションでJDBC接続オブジェクトを戻すライブラリ・ルーチンをコールする場合)、SQLJ接続コンテキスト・インスタンスをJDBC接続インスタンスに変換する必要があります。

SQLJアプリケーションの接続コンテキスト・インスタンスには、sqlj.runtime.ref.DefaultContextクラスのインスタンスの場合も、宣言済の接続コンテキスト・クラスのインスタンスの場合も、基になるJDBC接続インスタンスとそのJDBC接続インスタンスを戻すgetConnection()メソッドが含まれています。JDBC操作を使用する場合は、JDBC接続インスタンスを使用してJDBC文オブジェクトを作成します。

次は、getConnection()メソッドの使用方法の例です。

import java.sql.*;

...
DefaultContext ctx = new DefaultContext
("jdbc:oracle:thin:@localhost:1521/myservice", "scott", "tiger", true);
...
(SQLJ operations through SQLJ ctx connection context instance)
...
Connection conn = ctx.getConnection();
...
(JDBC operations through JDBC conn connection instance)
...

接続コンテキスト・インスタンスは、DefaultContextクラスのインスタンスでも、宣言した任意の接続コンテキスト・クラスのインスタンスでもかまいません。

デフォルトのSQLJ接続の基になるJDBC接続を取得する場合は、getConnection()をDefaultContext.getDefaultContext()コールから直接使用できます。その場合、getDefaultContext()で事前にデフォルトの接続として初期化したDefaultContextインスタンスを戻し、getConnection()でその基になるJDBC接続インスタンスを戻します。この場合、DefaultContextインスタンスを明示的に使用する必要はないため、Oracle.connect()メソッドを使用することもできます。このメソッドは、暗黙的にインスタンスを生成し、それをデフォルト接続にします。

関連項目:
「接続の際の考慮事項」および「Oracleクラスについて」

次に例を示します。

import java.sql.*;

...
Connection conn = Oracle.connect
("jdbc:oracle:thin:@localhost:1521/myservice",
"scott", "tiger").getConnection();
...
(JDBC operations through JDBC conn connection instance)
...

例: 動的SQLに対するJDBCとSQLJ接続の連係動作

次は、デフォルトのSQLJ接続コンテキスト・インスタンスの基になるJDBC接続インスタンスを使用して、JDBC内で動的SQL操作を実行するメソッドの例です。JDBCのjava.sql.Connection、java.sql.PreparedStatementおよびjava.sql.ResultSetオブジェクトによって、動的操作が実行されます。かわりに、動的SQL操作のOracle SQLJ拡張機能を使用できます。

関連項目:
『Oracle Database JDBC開発者ガイドおよびリファレンス』および「動的SQLのサポート」

import java.sql.*;

public static void projectsDue(boolean dueThisMonth) throws SQLException {

// Get JDBC connection from previously initialized SQLJ DefaultContext.
Connection conn = DefaultContext.getDefaultContext().getConnection();

String query = "SELECT name, start_date + duration " +
"FROM projects WHERE start_date + duration >= sysdate";
if (dueThisMonth)
query += " AND to_char(start_date + duration, 'fmMonth') " +
" = to_char(sysdate, 'fmMonth') ";

PreparedStatement pstmt = conn.prepareStatement(query);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
System.out.println("Project: " + rs.getString(1) + " Deadline: " +
rs.getDate(2));
}
rs.close();
pstmt.close();
}

この例をSQLJの動的SQL機能と結果セット・イテレータからのFETCH機能を使用するように修正する場合は、「例5: 動的SQLと結果セット・イテレータからのFETCH」を参照してください。

JDBC接続から接続コンテキストへの変換

JDBC Connectionインスタンスとして接続を開始した後で、それをSQLJ接続コンテキスト・インスタンスとして使用する場合(たとえば、コンテキスト式でこのインスタンスを使用して、SQLJ実行文で使用する接続を指定する場合)は、JDBC接続インスタンスをSQLJ接続コンテキスト・インスタンスに変換します。

DefaultContextクラスとすべての宣言済の接続コンテキスト・クラスに定義されたコンストラクタは、JDBC接続インスタンスを入力パラメータとして取り、SQLJ接続コンテキスト・インスタンスを生成します。

たとえば、JDBC接続インスタンスconnをインスタンス化し、定義してある場合に、宣言済のSQLJ接続コンテキスト・クラスMyContextのインスタンスに対して、同じ接続を使用するとします。その場合は、次のように指定します。

...
#sql context MyContext;
...
MyContext myctx = new MyContext(conn);
...

共有接続について

SQLJ接続コンテキスト・インスタンスとそれに関連付けされたJDBC接続インスタンスは、基になる同じ物理接続を共有します。そのため、次の状況が発生します。

- 接続コンテキストgetConnection()メソッドを使用して、SQLJ接続コンテキスト・インスタンスからJDBC接続インスタンスを取得すると、この接続コンテキスト・インスタンスの状態がConnectionインスタンスに継承されます。特に、Connectionインスタンスは、接続コンテキスト・インスタンスの自動コミットの設定を保持します。

- (Connectionインスタンスを入力パラメータとしてとる接続コンテキスト・コンストラクタを使用して) JDBC接続インスタンスからSQLJ接続コンテキスト・インスタンスを作成すると、Connectionインスタンスの状態がこの接続コンテキスト・インスタンスに継承されます。特に、接続コンテキスト・インスタンスは、Connectionインスタンスの自動コミットの設定を継承します。デフォルトでは、JDBC接続インスタンスの自動コミットはtrueに設定されますが、この設定はConnectionインスタンスのsetAutoCommit()メソッドで変更できます。

- SQLJ接続コンテキスト・インスタンスとそれに関連付けされたJDBC接続インスタンスがある場合、一方のインスタンスのセッション状態を変更するメソッドをコールすると、もう一方のインスタンスにも影響します。実際に変更されるのは、基になる共有セッションのためです。

- 物理接続は1つのみであるため、その基になるトランザクションのセットも1つのみとなっています。ある接続インスタンスでCOMMITまたはROLLBACK操作を行うと、基になる接続を共有している他の接続インスタンスにも影響します。

注意:
同一のJDBC接続インスタンスから複数のSQLJ接続コンテキスト・インスタンスを作成すると、各インスタンスで基になる物理接続を共有することも可能となります。このようにすると、プログラム・モジュール間で同じ種類のトランザクションを共有する場合などに便利なことがあります。ただし、この場合にも前に述べた注意があてはまるので注意してください。

共有接続の終了

(getConnection()メソッドを使用して) SQLJ接続コンテキスト・インスタンスからJDBC接続インスタンスを取得する場合も、(接続コンテキスト・コンストラクタを使用して) JDBC接続インスタンスからSQLJ接続コンテキスト・インスタンスを作成する場合も、接続コンテキスト・インスタンスのみを終了する必要があります。デフォルトでは、接続コンテキスト・インスタンスのclose()メソッドをコールすると、関連付けられたJDBC接続インスタンスと、基になる物理接続が終了し、その接続に関連付けられたすべてのリソースが解放されます。

関連付けられたJDBC接続インスタンスを終了せずにSQLJ接続コンテキスト・インスタンスを終了する場合(たとえば、Connectionインスタンスが、直接または他の接続コンテキスト・インスタンスによって、別の場所で使用されている場合)、次のようにブール値の定数KEEP_CONNECTIONをclose()メソッドに指定できます(ここでは、接続コンテキスト・インスタンスctxを前提としています)。

ctx.close(ConnectionContext.KEEP_CONNECTION);

KEEP_CONNECTIONを指定しないと、デフォルトで、それに関連付けされたJDBC接続インスタンスが終了します。一方、JDBC接続インスタンスの終了を明示的に指定するには、次のようにします。

ctx.close(ConnectionContext.CLOSE_CONNECTION);

KEEP_CONNECTIONおよびCLOSE_CONNECTIONは、sqlj.runtime.ConnectionContextインタフェースのstatic定数です。

JDBC接続インスタンスのみを終了しても、関連付けられたSQLJ接続コンテキスト・インスタンスは終了されません。基になる物理接続は終了します。ただし、接続コンテキスト・インスタンスのリソースは、ガベージ・コレクションが行われるまで解放されません。

注意:

- 基になる1つのJDBC接続が複数の接続コンテキスト・インスタンスで共有される場合、最後のオープン接続コンテキスト・インスタンス以外のすべての接続を終了するには、KEEP_CONNECTIONを使用します。

- 接続コンテキスト・インスタンスを終了しようとしたときに、その基になるJDBC接続がすでに終了している場合、または基になる接続を終了しようとするときに、その接続がすでに終了している場合は、エラー・メッセージが生成されます。エラー・メッセージが表示された場合は、JDBC接続が単独でJDBCコードによって終了されていないこと、および基になる接続を使用するSQLJ接続コンテキスト・インスタンスでコールされた、先行するすべてのclose()でKEEP_CONNECTIONパラメータが使用されていることを確認します。

SQLJイテレータとJDBC結果セットの連係動作

SQLJでは、SQLJイテレータからJDBC結果セットに、またはその逆に変換できます。SQLJ文のデータを選択する場合に、強い型指定のイテレータが特に必要のないときは、SQLJでJDBC結果セットに変換可能な、弱い型指定のイテレータを使用してもかまいません。

結果セットから名前付きイテレータまたは位置イテレータへの変換

JDBC結果セットの操作は、様々な状況で活用できます。たとえば、JDBCに別のパッケージが実装されており、結果セットを介してしかデータにアクセスできない場合、またはResultSetMetaData情報がどの結果セットにも使用できるように記述されたルーチンであるために、その情報が必要な場合などです。これ以外に、SQLJアプリケーションから、JDBC結果セットを戻り値とするストアド・プロシージャを起動する場合も挙げられます。

動的結果セットに構造がある場合は、それをイテレータとして操作して、そのイテレータの提供する強い型指定のパラダイムを使用します。

SQLJでは、既存のJDBC結果セット・オブジェクトを変換することで、名前付きイテレータ・オブジェクトまたは位置イテレータ・オブジェクトに移入できます。これは、結果セットをイテレータにキャストする処理であるといえます。この処理を反映する構文は次のようになります。

#sql iter = { CAST :rs };

これにより、結果セット・オブジェクトrsがSQLJ実行文にバインドされ、結果セットが変換され、イテレータiterに結果セット・データが設定されます。

次に、その例を示します。myEmpQuery()は、RSClassクラスのstatic Javaファンクションで、JDBC結果セット・オブジェクトを戻り値とする問合せが定義されているとします。

import java.sql.*;
...
#sql public iterator MyIterator (String ename, float sal);
...
ResultSet rs;
MyIterator iter;
...
rs = RSClass.myEmpQuery();
#sql iter = { CAST :rs };
...
(process iterator)
...
iter.close();
...

この例では、名前付きイテレータのかわりに、位置イテレータを使用することもできます。同じ機能が得られます。

次の規則は、JDBC結果セットをSQLJイテレータに変換し、データを処理する場合に適用されます。

- 位置イテレータを変換する場合、結果セットとイテレータの列数が同じであることが必要です。また、型が正しくマッピングする必要があります。

- 名前付きイテレータに変換する場合、結果セットに少なくともイテレータと同じ数の列が必要であり、イテレータのすべての列が名前と型で一致する必要があります。結果セットとイテレータの列の数が同じではない場合、SQLJトランスレータによって警告が生成されますが、-warn=nostrictオプションが設定されている場合を除きます。

- キャストされている結果セットでは、java.sql.ResultSetインタフェースを実装する必要があります。クラスoracle.jdbc.OracleResultSetでは、標準結果セット・クラスと同様に、このインタフェースが実装されています。

- キャストを受け取るイテレータは、publicと宣言されたイテレータ・クラスのインスタンスであることが必要です。

- 変換前でも変換後でも、結果セットからデータにアクセスしないでください。データには、イテレータのみからアクセスします。

- •操作が終了した後、結果セットではなくイテレータを終了します。イテレータを終了すると結果セットも終了しますが、結果セットを終了してもイテレータは終了しません。JDBCと連係している場合は、必ずSQLJエンティティを終了してください。

名前付きイテレータまたは位置イテレータから結果セットへの変換

当初はSQLJで定義した問合せが必要だったときでも、最終的には結果セットの方が必要になる場合があります。

注意:
SQLJでは、わかりやすくて簡単な構文が使用されています。ただし、結果を動的に処理する場合、または結果セットを入力パラメータとして取る既存のJavaメソッドを使用する場合もあります。

イテレータを結果セットに変換するために、名前付きイテレータ・クラスでも位置イテレータ・クラスでも、すべてのSQLJイテレータ・クラスはgetResultSet()メソッドで生成されます。このメソッドを使用すると、イテレータ・オブジェクトの基になるJDBC結果セット・オブジェクトが戻り値になります。

次は、getResultSet()の使用方法の例です。

import java.sql.*;

#sql public iterator MyIterator (String ename, float sal);

...
MyIterator iter;
...
#sql iter = { SELECT * FROM emp };
ResultSet rs = iter.getResultSet();
...
(process result set)
...
iter.close();
...

次の規則は、SQLJイテレータをJDBC結果セットに変換し、データを処理する場合に適用されます。

- イテレータ・データを結果セットに書き込む場合、結果セットからのみデータにアクセスする必要があります。変換前でも変換後でも、イテレータに直接アクセスしないでください。

- 操作が終了した後、結果セットではなく元のイテレータを終了します。イテレータを終了すると結果セットも終了しますが、結果セットを終了してもイテレータは終了しません。JDBCと連係している場合は、必ずSQLJエンティティを終了してください。

弱い型指定のイテレータ(ResultSetIterator)の使用と変換

「名前付きイテレータまたは位置イテレータから結果セットへの変換」で説明した状況においても、強い型指定のイテレータが必要ない場合があります。問合せにSQLJ構文を使用し、結果セットからデータを動的に処理できることが必要です。その場合は、sqlj.runtime.ResultSetIterator型を直接使用して問合せデータを受け取ることができます。

JDBC文と標準の結果セットではなく、SQLJ文とResultSetIteratorを使用すると、SQLJのSELECT構文を簡略化できます。

次は、弱い型指定の結果セット・イテレータの使用方法と変換方法の例です。

import sqlj.runtime.*;
import java.sql.*;

...
ResultSetIterator rsiter;
...
#sql rsiter = { SELECT * FROM table };
ResultSet rs = rsiter.getResultSet();
...
(process result set)
...
rsiter.close();
...

注意:
Oracle SQLJ実装では、next()メソッドとFETCH CURRENT構文を使用して、結果セット・イテレータで移動できます。さらに、スクロール可能な結果セット・イテレータの場合、ナビゲーション・メソッドがサポートされています。

動的SQLのサポート

Oracle SQLJ実装には、動的SQL(事前定義されずリアルタイムに変更できる操作)をサポートする拡張機能があります。SQLJ文に埋め込まれた動的SQL式は、メタ・バインド式と呼ばれます。

注意:
JDBCコードを使用することは、Oracle Database 11gの動的SQLのためのオプションであり、コードの移植性がかかわる場合はお薦めする方法ですが、動的SQLのためのSQLJサポートでは、SQLJを簡略化された1つのデータ・アクセス用APIとして使用できます。

ここでは、次の項目について説明します。

- メタ・バインド式

- SQLJ動的SQLの例

メタ・バインド式

メタ・バインド式は、SQLJ文で動的SQL用に使用されますが、静的SQL句が使用されています。メタ・バインド式には、String型のJava識別子、または実行時に変換される文字列の値のJava式が含まれます。さらに、SQLJではオンラインでセマンティクス・チェックを実行するので、変換時のチェックに使用するために、必要に応じてメタ・バインド式に静的SQL置換コードを指定します。

メタ・バインド式: 使用方法と制限事項の概要

次のいずれかの項目のかわりにメタ・バインド式を使用できます。

- 表名

- SELECT文の列名(列の別名が指定されている場合は、別名を除く)

- WHERE句条件の一部またはすべて

- データ定義言語(DDL)やDML文のロール名、スキーマ名、カタログ名またはパッケージ名

- SQLリテラル値またはSQL式

メタ・バインド式では、次の制限事項に注意してください。この制限事項は、SQLJトランスレータでSQL操作の種類を確認して、SQLJ文全体の構文分析を実行するためのものです。

- メタ・バインド式は、SQLJ文の中で、コメント以外の最初のSQL操作として使用できません。

- メタ・バインド式には、SQLJ SELECT INTO文のINTOトークンを使用できません。また、メタ・バインド式を拡張して、SELECT INTO式のINTOリストにすることもできません。

- メタ・バインド式は、次のいずれの種類のSQLまたはSQLJの命令および句では使用できません。使用できない命令および句は、CALL、VALUES、PSM SET、COMMIT、ROLLBACK、FETCH INTOおよびCASTです。

メタ・バインド式: 構文と動作

次にメタ・バインド式の一般的な構文を示します。

:{ Java_bind_expression }

または

:{ Java_bind_expression :: SQL_replacement_code }

空白はオプションであることに注意してください。SQLJ文のSQL命令内には複数のメタ・バインド式を使用できます。

Javaバインド式

Javaバインド式は次のいずれかになります。

- String型のJava識別子

- 文字列を評価するJava式

メタ・バインド式内のJavaバインド式には、標準のJava字句解析ルールが適用され、SQLJホスト式と同様の構文が使用されます。ただし、ホスト式と異なり、メタ・バインド式内のJavaバインド式はカッコで囲まれません。これは、SQL置換コードがある場合に、::トークンがJavaバインド式とSQLコードのセパレータとして機能するためです。SQL置換コードがない場合、閉じカッコ(})が終了記号として機能します。いずれの場合も、曖昧さはありません。

注意:
Javaバインド式内またはメタ・バインド式の:と{の間には、モード指定子(IN、OUTまたはINOUT)を指定できません。

SQL置換コード

SQL置換コード句は、0(ゼロ)以上のSQLトークンで構成されています。次の要件と制限事項を参照してください。

- SQL規則に準拠していることが必要です。

- 中カッコ({ })を1組で使用する必要があります(SQLのコメント、定数または識別子の一部に使用される場合は例外です)。

- SQL命令内にSQLJホスト式やネストしたメタ・バインド式を使用できません。

注意:
SQL置換コードを空白にすることは可能です。

変換時の動作

SQL置換コード(空白文字列のみの場合も)がメタ・バインド式にある場合は、変換時にSQLコードによってメタ・バインド式が置換されます。SQL置換コードの目的は、SQLJトランスレータでオンライン・セマンティクス・チェックを実行できるようにすることです。

SQLJ文内のメタ・バインド式にSQL置換コード句がない場合は、SQLJトランスレータでその文に対するオンライン・セマンティクス・チェックを実行できません。その文には構文チェックのみが実行されます。

実行時の動作

実行時に各メタ・バインド式は、Javaバインド式の評価によって置換されます。Javaバインド式の評価がnullになる場合、動的SQL文全体が未定義になります。

SQLJの動的SQLの例

ここでは、SQLJコードでの動的SQLの使用例を示します。

例1

...
int x = 10;
int y = x + 10;
int z = y + 10;
String table = "new_Emp";
#sql { INSERT INTO :{table :: emp} VALUES (:x, :y, :z) };
...

変換時のSQL操作は次のようになります。

INSERT INTO emp VALUES (10, 20, 30);

SQLJによって、emp表があるスキーマに対してオンライン・セマンティクス・チェックが実行されます。ランタイム・スキーマにnew_Empのみが存在し、アプリケーション実行まで作成されません。

実行時のSQL操作は次のようになります。

INSERT INTO new_Emp VALUES (10, 20, 30);

例2

...
String table = "new_Emp";
String query = "ename LIKE 'S%' AND sal>1000";
#sql myIter = { SELECT * FROM :{table :: emp2}
WHERE :{query :: ename='SCOTT'} };
...

変換時のSQL操作は次のようになります。

SELECT * FROM emp2 WHERE ename='SCOTT';

SQLJによって、emp2表があるスキーマに対してオンライン・セマンティクス・チェックが実行されます。

実行時のSQL操作は次のようになります。

SELECT * FROM new_Emp WHERE ename LIKE 'S%' AND sal>1000;

例3

...
double raise = 1.12;
String col = "comm";
String whereQuery = "WHERE "+col+" IS NOT null";
for (int i=0; i<5; i++)
{
#sql { UPDATE :{"emp"+i :: emp}
SET :{col :: sal} = :{col :: sal} * :raise :{whereQuery ::} };
}
...

変換時のSQL操作は次のようになります。

UPDATE emp SET sal = sal * 1.12;

SQLJによって、emp表があるスキーマに対してオンライン・セマンティクス・チェックが実行されます。SQL置換コードは空白なので、変換時にWHERE句はありません。

実行時にSQL操作が次のように5回実行されます。

UPDATE emp0 SET comm = comm * 1.12 WHERE comm IS NOT null;
UPDATE emp1 SET comm = comm * 1.12 WHERE comm IS NOT null;
UPDATE emp2 SET comm = comm * 1.12 WHERE comm IS NOT null;
UPDATE emp3 SET comm = comm * 1.12 WHERE comm IS NOT null;
UPDATE emp4 SET comm = comm * 1.12 WHERE comm IS NOT null;

例4

...
double raise = 1.12;
String col = "comm";
String whereQuery = "WHERE "+col+" IS NOT null";
for (int i=0; i<10; i++)
{
#sql { UPDATE :{"emp"+i}
SET :{col :: sal} = :{col :: sal} * :raise :{whereQuery ::} };
}
...

例3と例4の実行時の動作は同じです。ただし、変換時には違いがあります。例4では、最初のメタ・バインド式のSQL置換コードがないため(:{"emp"+i})、SQLJでオンライン・セマンティクス・チェックを実行できません。

例5: 動的SQLと結果セット・イテレータからのFETCH

この例は、JDBC文のかわりにSQLJ文を使用して、「例: 動的SQLに対するJDBCとSQLJ接続の連係動作」を修正しています。またこの例では、結果セット・イテレータからFETCH CURRENT機能を使用しています。

import java.sql.*;

public static void projectsDue(boolean dueThisMonth) throws SQLException {

ResultSetIterator rsi;
String andClause = (dueThisMonth) ?
" AND to_char(start_date + duration, 'fmMonth' ) "
+ " = to_char(sysdate, 'fmMonth') "
: "";
#sql rsi = { SELECT name, start_date + duration FROM projects
WHERE start_date + duration >= sysdate :{andClause :: } };
while (rsi.next())
{
String name = null;
java.sql.Date deadline = null;
#sql { FETCH CURRENT FROM :rsi INTO :name, :deadline };
System.out.println("Project: " + name + "Deadline: " + deadline);
}
rsi.close();
}

実行計画の修正

環境の変化によってアプリケーションのパフォーマンスも変化するリスクがある場合は、Oracleのアウトライン機能を使用できます。アウトラインは、SQL文と関連付けられた一連のオプティマイザ・ヒントとして実装されます。文に対してアウトラインの使用を有効にすると、格納されたヒントを自動的に考慮して、ヒントに従って実行計画の生成が試みられます。アウトラインを、デフォルトのアウトラインか、クライアント指定のアウトラインかによって、いくつかのカテゴリにグループ化し、使用されるアウトラインのカテゴリを制御すると、アウトラインの管理およびデプロイメントを単純化することができます。USE_STORED_OUTLINESにカテゴリ名またはTRUEを設定すると、アウトラインのヒントが、各文の実行中に使用されます。

関連項目:
アウトラインの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

新しいアウトラインのオプションをtrueまたはカテゴリ名に設定してファイルを変換すると、次の処理が実行されます。

1. 入力SQLJファイルに存在するすべてのSQL文に対して、CREATE OUTLINE文を含むSQLファイルが作成されます。

2. SQL文、アウトライン名、アウトラインSQL文、アウトライン・カテゴリおよびステータス情報を含むログ・ファイルが生成されます。

3. -runoutline optionを指定すると、入力ファイルが正常に変換された後、生成されたSQLファイルが実行されます。

アウトラインを作成するには、次のSQL文を使用できます。

- SELECT

- DELETE

- UPDATE

- INSERT ... SELECT

- CREATETABLE...ASSELECT

アウトラインの作成時には、次の制限事項があります。

- MERGE文にアウトラインは作成できません。

- 複数表のINSERT文にアウトラインは作成できません。

- アウトラインのSQL文に、リモート・オブジェクトに対するDML操作を含めることはできません。

アウトライン生成のオプション

注意:
アウトライン・オプションは、オンライン・チェックが終了した場合にのみ有効になります。

SQLJプログラムabc.sqljに次のコード例が含まれることを確認します。

{
#sql iter = {SELECT * FROM emp WHERE empno=:var;}
#sql iter1 = {SELECT * FROM dept};
}

次のようにSQLJプログラムをコンパイルします。

%sqlj -url=jdbc:oracle:oci8:@ -user=scott -outline=abccat abc.sqlj
Password: password

前述のSQLJコード例で生成されたSQLファイルabc_sqlj.sqlは、次のようになります。

CREATE OR REPLACE OUTLINE abccat_abc_sqlj_0001 FOR CATEGORY abccat ON SELECT * FROM emp WHERE empno=:B1
/* abccat_abc_sqlj_0001 */;

CREATE OR REPLACE OUTLINE abccat_abc_sqlj_0002 FOR CATEGORY abccat ON SELECT * FROM dept
/* abccat_abc_sqlj_0002 */;

正常に変換された後、-outlineオプションによって、2つのファイル(SQLファイルおよびLOGファイル)が生成されます。生成されたSQLファイル名の形式は、次のようになります。

<filename>_<filetype>.sql

たとえば、ファイル名abc.sqljで生成されたSQLファイルの名前はabc_sqlj.sqlです。

アウトライン名およびコメントとして使用される一意の識別子の形式は、次のようになります。

<categoryname >_<filename>_<filetype>_<sequence no.>

順序番号は0001から9999の範囲の4桁の数字です。SQLJプログラムに9999を超えるSQL文が含まれる場合は、「アウトラインの順序番号の最大数を超えています」というエラーが発生します。たとえば、カテゴリ名がabccatの場合、abc.sqljに対して生成される一意識別子の形式はabccat_abc_sqlj_0001です。

注意:
同じコメントが、実行時に使用される生成済のJavaファイルまたはクラス・ファイルのSQLに追加されます。

アウトラインをtrueに設定すると、デフォルトのカテゴリを使用してアウトラインが格納されます。

%sqlj -user=scott -url=jdbc:oracle:oci8:@ -outline=true abc.sqlj
Password: password

この場合、生成されたSQLファイルabc_sqlj.sqlは、次のようになります。

CREATE OR REPLACE OUTLINE default_abc_sqlj_0001 ON SELECT * FROM emp WHERE empno=:B1 /* default_abc_sqlj_0001 */;

CREATE OR REPLACE OUTLINE default_abc_sqlj_0002 ON SELECT * FROM dept /* default_abc_sqlj_0002 */;

次のコマンドを使用して、アウトライン名を特定の接頭辞に設定できます。

%sqlj -user=scott -url=jdbc:oracle:oci8:@ -outline=abccat -outlineprefix=pref1 abc.sqlj
Password: password

この場合、生成されたSQLファイルabc_sqlj.sqlは、次のようになります。

CREATE OR REPLACE OUTLINE pref1_0001 FOR CATEGORY abccat ON SELECT * FROM emp WHERE empno=:B1 /* pref1_0001 */';

CREATE OR REPLACE OUTLINE pref1_0002 FOR CATEGORY abccat ON SELECT * FROM dept /* pref1_0002 */';

注意:
次を実行すると、複数のファイルをoutlineprefixオプションで変換できます。

%sqlj -outline=abccat -outlineprefix=pref1,pref2,pref3 abc.sqlj def.sqlj fgh.sqlj

現在、アウトライン名の長さの上限は30バイトです。このため、生成されたアウトライン名が30バイトを超える場合、「アウトライン名が上限を超えています。-outlineprefixオプションを使用してください」というSQLJエラーがスローされます。この場合、-outlineオプションを使用するには、前の例に示したように-outlineprefixオプションをコールする必要があります。SQLJで生成したアウトライン名を使用せずに、データベース・サーバーでアウトライン名を生成するには、-outlineprefixオプションにnoneを設定します。次に例を示します。

%sqlj -user=scott -url=jdbc:oracle:oci8:@ -outline=abccat -outlineprefix=none abc.sqlj
Password: password

この場合、生成されたSQLファイルabc_sqlj.sqlは、次のようになります。

CREATE OR REPLACE OUTLINE FOR CATEGORY abccat ON SELECT * FROM emp WHERE empno=:B1 /* abccat_abc_sqlj_0001 */';

CREATE OR REPLACE OUTLINE FOR CATEGORY abccat ON SELECT * FROM dept /* abccat_abc_sqlj_0002 */';

複数のファイルを-outlineprefixオプションを指定して変換するには、次のコマンドを使用します。

%sqlj -user=scott -url=jdbc:oracle:oci8:@ -outline=abccat -outlineprefix=pref1,pref2 abc.sqlj def.sqlj
Password: password

SQLJファイルがパッケージの一部で、-outlineprefixオプションを指定していない場合は、パッケージ名がアウトライン名およびコメントに追加されます。たとえば、abc.sqljがxyz.def.fghパッケージの一部である場合、コマンド%sqlj -url=jdbc:oracle:oci8:@ -user=scott/password -outline=abccat abc.sqljを実行して生成されたSQLファイルabc_sqlj.sqlは、次のようになります。

CREATE OR REPLACE OUTLINE abccat_xyz$def$fgh$abc_sqlj_0001 FOR CATEGORY abccat ON SELECT * FROM emp WHERE empno=:B1
/* abccat_xyz$def$fgh$abc_sqlj_0001 */;

CREATE OR REPLACE OUTLINE abccat_xyz$def$fgh$abc_sqlj_0002 FOR CATEGORY abccat ON SELECT * FROM dept
/* abccat_xyz$def$fgh$abc_sqlj_0002 */;

正常に変換が終了した後、生成されたSQLファイルをトランスレータによって実行するには、runoutlineオプションにtrueを設定します。デフォルトはfalseです。次に例を示します。

%sqlj -user=scott -url=jdbc:oracle:oci8:@ -outline=default -runoutline=true abc.sqlj
Password: password

ここで、SQLコード計画をエクスポートまたは修正するためにアウトライン名を取得する場合は、手動でまたはツールを使用してOL$表から取得できます。コメントはSQL文を一意に識別するため、SQL問合せのコメントを使用して適切なSQL文を検索し、アウトライン名を識別できます。

表7-1に、アウトラインを生成するためにトランスレータに渡すすべてのオプションおよび値を示します。

表7-1 アウトラインを生成するオプションおよび値

オプション名

オプション値

-outline

true<category name>

-outlineprefix

none<prefix name>|none<prefix name 1, prefix name 2,…>

-runoutline

true|false

関連項目:
アウトラインの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

生成されるLOGファイルの名前

生成されるファイルの名前の形式は、次のようになります。

<filename>_<filetype>.log

たとえば、abc.sqljを変換する場合、生成されるログ・ファイルはabc_sqlj.log.になります。

生成されるLOGファイルの形式

次のコード例があるとします。

#sql iter = {SELECT * FROM emp WHERE empno=:var };
#sql iter1 = {SELECT * FROM dept };

前述のコードに対して生成されるログ・ファイルは、次のようになります。

CATERGORY abccat
Source SQL_1
SELECT * FROM emp WHERE empno=:B1
OUTLINE NAME
abccat_abc_sqlj_0001
OUTLINE SQL_1
CREATE OR REPLACE OUTLINE abccat_abc_sqlj_0001 FOR CATEGORY abccat ON SELECT * FROM emp WHERE empno = :B1
/* abccat_abc_sqlj_0001 */
STATUS success
Source SQL_2
SELECT * FROM dept
OUTLINE NAME
abccat_abc_sqlj_0002
OUTLINE SQL_2
CREATE OR REPLACE OUTLINE abccat_abc_sqlj_2 FOR abccat ON SELECT * FROM dept
/* abccat_abc_sqlj_2 */
STATUS fail

前述の例では、生成されるログ・ファイルの形式について、次のことを示しています。

- カテゴリは、生成されるアウトラインのカテゴリを意味します。

- ソースは、アウトラインが生成されるSQL文を意味します。

- アウトライン名は、生成されるアウトラインの名前です。

- ステータスは、ソースとして使用されるSQL文の実行ステータスです。正常に実行されると、ステータスはsuccessになります。それ以外は、failになります。

構成ファイル

構成ファイルには、次のように様々なコマンドライン・オプションを設定できます。

sqlj.outline

- パラメータ名: outline

- パラメータ・タイプ: String

- 許容値: {true|category_name}

- デフォルト値: true

- 詳細: SQL文に対するアウトラインSQLファイルを生成して、次の場所に格納する必要があります。

- 値がデフォルトのtrueの場合はDEFAULTカテゴリ

- category_nameが示されている場合は該当するカテゴリ

このオプションを使用しないと、アウトラインSQLファイルは生成されません。

- その他のパタメータへの依存性: このオプションが設定されているときは、オンライン・チェックをフルにする必要があります。

sqlj.runoutline

- パラメータ名: runoutline

- パラメータ・タイプ: boolean

- 許容値: {true|false}

- デフォルト値: false

- 詳細: runoutline=trueに設定されている場合、生成されるSQLファイルは、正常に変換が終了した後でトランスレータによって実行される必要があります。

- その他のパタメータへの依存性: このオプションが設定されているときは、オンライン・チェックをフルにして、アウトライン・オプションを設定する必要があります。

sqlj.outlineprefix

- パラメータ名: outlineprefix

- パラメータ・タイプ: String

- 許容値: {prefix name}, none

- 詳細: このオプションを設定すると、生成されるSQLのアウトライン名は、<prefix>_<seqno>に設定されます。このオプションをプロパティ・ファイルのnone以外の値に設定すると、1つのSQLJファイルのみがトランスレータに渡されます。このオプションをnoneに設定すると、create outline文をサーバーで実行する際にシステムによってアウトライン名が生成されます。また、–outlineprefixをnoneに設定すると、複数のファイルをトランスレータに渡すことができます。

- その他のパタメータへの依存性: このオプションが設定されているときは、オンライン・チェックをフルにして、アウトライン・オプションを設定する必要があります。

8 トランスレータのコマンドラインとオプション

ソース・コードの作成後、SQLJトランスレータでこのコードを変換する必要があります。この章では、SQLJトランスレータのコマンドライン、オプションおよびプロパティ・ファイルについて説明します。内容は次のとおりです。

- トランスレータのコマンドラインとプロパティ・ファイル

- 基本的なトランスレータ・オプション

- 高度なトランスレータ・オプション

- トランスレータによる代替環境のサポートとオプション

トランスレータのコマンドラインとプロパティ・ファイル

sqljスクリプトによってJava Virtual Machine(JVM)を起動し、SQLJトランスレータのクラス名sqlj.tools.SqljをJVMに渡します。トランスレータの起動や、コマンドラインとプロパティ・ファイルの解析などは、JVMによって実行されます。ここでは、スクリプトの実行をSQLJの実行と呼び、スクリプトのコマンドラインをSQLJコマンドラインと呼びます。

コマンドラインの代表的な構文は、次のとおりです。

% sqlj <optionlist> filelist

optionlist は、SQLJオプションの設定値をスペースで区切って並べたものです。Javaインタプリタ、コンパイラおよびカスタマイザに渡すオプションには、接頭辞を付けます。

filelist は、SQLJトランスレータで処理するファイルをスペースで区切って並べたものです。.sqlj、.java、.serまたは.jarを指定できます。ファイル名には、*ワイルドカードを使用できます。たとえば、Foo*.sqljでは、Foo1.sqlj、Foo2.sqljおよびFoobar.sqljが検索されます。

注意:

- オプションを指定する位置は、必ずしもファイル・リストの前である必要はありません。オプションは、コマンドラインのどの箇所に指定した場合にも正常に処理されます。

- すべてのコマンドラインのオプションは、変換されるすべてのファイルに適用されます。ファイル固有のオプションは設定できません。

ファイル・リストに.classファイルは指定しないでください。SQLJトランスレータがSQLJソース・ファイル中の変数の型解決に必要なクラスを見つけられるように、CLASSPATHを設定してください。-checksourceフラグが使用できる場合(デフォルト設定)、SQLJトランスレータでは、CLASSPATH内のコンパイルされていない.javaファイルで必要なクラスも検索できます。

関連項目:
「型解決を目的としたソース・チェック(-checksource)」

注意:
ただ単にsqljと入力してスクリプトを実行すると、使用頻度の最も高いSQLJオプション一覧が表示できます。処理対象ファイルを指定しない場合も、スクリプト実行のたびにこのオプション一覧が表示されます。つまり-helpフラグを設定した場合と同じ結果になります。

ここでは、次の項目について説明します。

- SQLJのオプション、フラグおよび接頭辞

- コマンドラインの構文と処理

- プロパティ・ファイルによるオプション設定

- 環境変数SQLJ_OPTIONSによるオプションの設定

- オプション設定の優先順位

SQLJのオプション、フラグおよび接頭辞

ここでは、SQLJトランスレータに対して指定できるオプションについて説明します。ブール型オプションは、フラグと呼ばれます。JVM(SQLJスクリプトから起動)、およびJavaコンパイラとSQLJプロファイル・カスタマイザ(JVMから起動)に渡すオプションには、接頭辞を付けます。

SQLJオプションの概説

次の表8-1は、SQLJトランスレータでサポートされているオプションの一覧です。次のカテゴリに分類されています。

- 基本カテゴリのフラグとオプション。詳細は、「基本的なトランスレータ・オプション」を参照してください。

- 「高度」カテゴリのフラグ、オプションおよび接頭辞。詳細は、「高度なトランスレータ・オプション」を参照してください。

- 環境カテゴリのフラグとオプション。詳細は、「トランスレータによる代替環境のサポートとオプション」を参照してください。このカテゴリのフラグとオプションは、非標準のJVM、コンパイラまたはカスタマイザを使用するためのものです。

- javacカテゴリのオプションは、SQLJがコンパイラ接頭辞なしで直接認識するjavacコンパイラ・オプションです。javacオプションはJavaコンパイラ(通常はjavac)に渡され、その一部はSQLJトランスレータ設定にも影響します。詳細は、「javacのオプションのサポート」を参照してください。

表8-1 SQLJトランスレータのオプション

オプション

説明

デフォルト

カテゴリ

-bind-by-identifier

指定されたSQLJ文の中で複数回出現する同一のホスト変数を、単一のバインドとして処理するフラグです。

FALSE

高度

-C

Javaコンパイラに渡すオプションに付ける接頭辞です。

なし

高度

-cache

オンライン・セマンティクス・チェックの結果のキャッシングを有効化します(キャッシングすると、データベースへのラウンドトリップが削減されます)。

FALSE

高度

-checkfilename

ソース・ファイル名とそのソース・ファイル中のPublicクラス(定義済の場合)の名前とが対応していない場合に、変換時に警告を出すかどうかを指定します。

TRUE

環境

-checksource

状況によってはクラス・ファイルに加えてソース・ファイルも、SQLJの型解決の検査対象に指定します。

TRUE

高度

-classpath

JVMとJavaコンパイラに対してCLASSPATHを指定します(javacにも渡されます)。コマンドラインでのみ指定できます。

なし

基本

-codegen

コード生成のモードを指定します。oracleで直接Oracle Java Database Connectivity(JDBC)コールによるOracle固有コード生成を指定し、isoでISO標準SQLJコード生成を指定します。

oracle

基本

-compile

Javaのコンパイル処理を有効化/無効化します。対象は、SQLJの現在の実行で生成されたまたは以前に生成された.javaファイル、あるいはコマンドラインで指定された.javaファイルです。

TRUE

高度

-compiler-executable

使用するJavaコンパイラを指定します。

javac

環境

-compiler-encoding-flag

-encoding値が設定されている場合に、この設定をJavaコンパイラに渡すかどうかをSQLJに指示します。

TRUE

環境

-compiler-output-file

Javaコンパイラの出力を書き込むファイルを指定します。このオプションを設定しないと、コンパイラの出力は標準出力に送られます。

なし

環境

-compiler-pipe-output-flag

javac.pipe.outputシステム・プロパティを設定するかどうかをSQLJに指示します。このフラグを設定すると、Javaコンパイラがエラーとメッセージを、STDERRではなく、STDOUTに出力します。

TRUE

環境

-components

Oracle Dynamic Monitoring Service(DMS)で使用するコンポーネント(パッケージおよびクラス)のインストルメント処理を指定します。これは、インストルメントが-instrumentオプションを使用して有効になっていることが前提です。変換されるすべてのコンポーネントをインストルメントするにはallを指定します。

all

基本

-d

SQLJで生成される.serプロファイル・ファイル(生成される場合)およびコンパイラで生成される.classファイルの出力先ディレクトリを指定します(javacにも渡されます)。

空

(.classファイルの場合は.javaファイルのディレクトリを使用し、.serファイルの場合は.sqljファイルのディレクトリを使用します。)

基本

-default-customizer

使用するプロファイル・カスタマイザを判断します。クラス名を指定します。

oracle.sqlj. runtime.util. OraCustomizer

環境

-default-url-prefix

URL設定のデフォルト接頭辞を設定します。

jdbc:oracle:thin:

基本

-depend

javacに渡され、-checksourceが有効になります。プロパティ・ファイルに設定されている場合は-Cコンパイラ接頭辞が必要です。

なし

javac

-deprecation

javacにのみ渡されます。プロパティ・ファイルに設定されている場合は-Cコンパイラ接頭辞が必要です。

なし

javac

-dir

SQLJにより生成される.javaファイルの出力ディレクトリを設定します。

空

(.sqlj入力ファイルのディレクトリが使用されます。)

基本

-driver

登録するJDBCドライバ・クラスを判断します。クラス名またはクラス名のカンマ区切りのリストを指定します。

oracle.jdbc.OracleDriver

基本

-encoding

SQLJとコンパイラでグローバリゼーション・サポートに使用するエンコーディングを指定します。javacにも渡されます。コマンドラインでは、-eを使用できます。

JVMのfile.encodingの設定

基本

-explain

トランスレータのエラー・メッセージに原因と処置情報の表示を要求するフラグです。

FALSE

基本

-fixedchar

CHARデータと比較するために文字列をWHERE句にバインドするときに、空白埋めを考慮するフラグです。

FALSE

基本

-g

javacに渡され、-linemapが有効になります。プロパティ・ファイルに設定されている場合は-Cコンパイラ接頭辞が必要です。

なし

javac

-help-help-long-help-alias

SQLJオプションの名前、説明および現行値に関する様々なレベルの情報を表示するフラグです。コマンドラインでのみ指定できます。-helpのかわりに-hを指定できます。

無効

基本

-instrument

Oracle DMSで使用する変換済ファイルをインストルメントするかどうかを指定します。

FALSE

基本

-jdblinemap

-linemapオプションの改良型です。Sun社のjdbデバッガで使用されます。

FALSE

基本

-J

JVMに渡すオプションに付ける接頭辞です。コマンドラインでのみ指定できます。

なし

高度

-linemap

生成されたJavaクラス・ファイルと元のSQLJコード間での行番号のマッピングを有効化します。

FALSE

基本

-n

コマンドライン全体を(SQLJ_OPTIONSでの設定を含めて)、SQLJトランスレータに渡されたとおりにエコーし、トランスレータでは実行しないことをsqljスクリプトに指示します。-vm=echoと同じ結果になります。コマンドラインでのみ指定できます。

無効

基本

-ncharconv

Stringホスト変数のNCHAR列へのバインドを実行します。

FALSE

基本

-nowarn

javacに渡され、-warn=noneを設定します。プロパティ・ファイルに設定されている場合は-Cコンパイラ接頭辞が必要です。

なし

javac

-O

javacに渡されると、-linemapは無効化されます。プロパティ・ファイルに設定されている場合は-Cコンパイラ接頭辞が必要です。

なし

javac

-offline

セマンティクス・チェックに使用するオフライン・チェッカを判断します。クラスの完全修飾名のリストを指定します。

oracle.sqlj.checker.OracleChecker

高度

-online

セマンティクス・チェックに使用するオンライン・チェッカを判断します。クラスの完全修飾名を指定します。(オンライン・チェックを有効にするには、-userの設定も必要です。)

oracle.sqlj.checker.OracleChecker

高度

-optcols

パフォーマンスが最適化されるようにイテレータ列型およびサイズ定義を有効化します。トランスレータでOracle固有コード生成に直接使用されるか、Oracleカスタマイザにユーザー、パスワード、URLの設定とともに転送されてISOコード生成に使用されます。

FALSE

基本

-optparams

JDBCリソース割当てが最適化されるようにパラメータ・サイズ定義を有効化します(-optparamdefaultsと併用します)。トランスレータでOracle固有コード生成に直接使用されるか、Oracleカスタマイザに転送されてISOコード生成に使用されます。

FALSE

基本

-optparamdefaults

特定のデータ型にパラメータ・サイズのデフォルトを設定します(-optparamsと併用します)。トランスレータでOracle固有コード生成に直接使用されるか、Oracleカスタマイザに転送されてISOコード生成に使用されます。

FALSE

基本

-P

SQLJプロファイル・カスタマイザに渡すオプションに付ける接頭辞です。

なし

高度

-parse

オフラインSQLパーサーを有効にするオプションです。使用可能な設定は、both、online-only、offline-only、noneまたは代替パーサーを実装するJavaクラス名です。

注意: このオプションの設定によっては、-userオプションの効果が無視され、オンライン・セマンティクス・チェックも無効になります。

both

高度

-passes

コンパイルを挟んで、SQLJを2回実行することをsqljスクリプトに指示します。コマンドラインでのみ指定できます。

FALSE

環境

-password

オンライン・セマンティクス・チェック用のデータベース接続のユーザー・パスワードを設定します。-pはコマンドラインで指定できます。

なし

基本

-profile

ISOコード生成の場合に、現在のSQLJの実行で生成されるプロファイル・ファイルのプロファイル・カスタマイズ処理を有効化または無効化します。

TRUE

高度

-props

オプション設定のコマンドラインの代替方法として、プロパティ・ファイルを指定します。(sqlj.propertiesも読み込まれます。)コマンドラインでのみ指定できます。

なし

基本

-ser2class

ISOコード生成の場合に、生成した.serプロファイルを.classファイルに変換するようにSQLJに指示します。

FALSE

高度

-status

実行中のステータス・メッセージの表示をSQLJに要求します。-statusのかわりに、コマンドラインで-vを指定できます。

FALSE

基本

-url

オンライン・セマンティクス・チェック用のデータベース接続のURLを設定します。

jdbc:oracle:oci:@

基本

-user

オンライン・セマンティクス・チェックを有効にし、データベース接続のユーザー名(およびパスワードとURL)を設定します。-uはコマンドラインで指定できます。

なし(オンライン・セマンティクス・チェックはありません。)

基本

-verbose

javacに渡されると、-statusが有効になります。プロパティ・ファイルに設定されている場合は-Cコンパイラ接頭辞が必要です。

なし

javac

-version-version-long

SQLJおよびJDBCドライバのバージョン情報に関する様々なレベルの情報を表示するフラグです。コマンドラインでのみ設定できます。

無効

基本

-vm

JVMを指定してSQLJトランスレータの実行に使用します。コマンドラインでのみ指定できます。

java

環境

-warn

各種のSQLJ警告を有効化または無効化するフラグのカンマ区切りリストです。個別フラグは、cast/nocast、precision/noprecision、nulls/nonulls、portable/noportable、strict/nostrictおよびverbose/noverboseです。グローバル・フラグはall/noneです。

cast precision nulls noportable strict noverbose

基本

オプション、フラグおよび接頭辞に関する注意

次の注意事項があります。

- 前の表の「説明」列で「コマンドラインのみ」と示されているフラグ、オプションおよび接頭辞は、プロパティ・ファイルでは設定できません。

- コマンドラインのオプション名は、他に渡されるオプションも含めて、大/小文字が区別され、通常はすべて小文字にします。通常、オプション値も大/小文字が区別されます。

- いくつかのオプションは、表8-1に示すとおり、Oracleのloadjavaユーティリティとの互換性をサポートするために、コマンドラインで代替構文を使用できます。

- SQLJの大半のオプションは、プロパティ・ファイルでも設定できます。

- 環境変数SQLJ_OPTIONSをコマンドラインのかわりに使用するか、またはコマンドラインと併用して、オプションを設定できます。

- このマニュアルの説明では、ほとんどの場合、ブール・フラグの設定値をtrueまたはfalseで示していますが、yes/no、on/offまたは1/0でも有効化/無効化を行えます。

関連項目:
「コマンドラインの構文と処理」

-passwordオプションに関する注意

psなどのユーティリティにより他のユーザーがパスワードを傍受しないようにパスワードを指定するには、次のいずれかの方法を選択します。

- -password引数を省略します。この場合、コマンドラインでパスワードを入力するように求められます。password引数は、オペレーティング・システムには表示されません。

- パスワードの設定をプロパティ・ファイルに追加し、このプロパティ・ファイルを使用するようにSQLJトランスレータを設定します。つまり、パスワードをオペレーティング・システムに公開しなくても、SQLJ変換スクリプトを実行することができます。

- JDeveloperでSQLJを使用します。この方法では、オペレーティング・システムにパスワードは公開されません。

loadjava互換オプション

JavaおよびSQLJアプリケーションをOracle Database 11g インスタンスにロードするためのloadjavaユーティリティとの互換のために、コマンドラインでの指定時に、次の代替構文が指定したオプション用に認識されます。

- -e(-encoding)

- -h(-help)

- -p(-password)

- -u(-user)

- -v(詳細メッセージの出力。-statusに相当。)

loadjava構文との一貫性を完全に保持するには、次のように等号(=)のかわりにスペースを使用してこれらのオプションを設定します。

-u scott -v -e SJIS

注意:
この代替オプション構文はコマンドラインまたは環境変数SQLJ_OPTIONSでのみ認識されます。プロパティ・ファイルでは認識されません。

関連項目:
loadjavaユーティリティの概要は、『Oracle Database Java開発者ガイド』を参照してください。

javacのオプションのサポート

SQLJは、Sun社のJava Development Kit(JDK)のJavaコンパイラjavacのオプション設定を次のようにサポートしています。

- 値を伴う一部のjavacオプションは、SQLJのオプションと一体化しています(-classpath、-d、-encoding)。

- 値を伴うその他のjavacオプションについては、コンパイラに値を正確に渡すように特別な処理が実装されました(-bootclasspath、-extdirs、-target)。これらのオプションには、コンパイラの接頭辞が必要です。これらのオプションがSQLJの操作に影響することはありません。

- javacのフラグは、コマンドラインではcompiler接頭辞なしで認識されます(-depend、-deprecation、-g、-nowarn、-O、-verbose)。これらのフラグの一部は、SQLJトランスレータ・フラグの設定にも影響を与えます。

表8-2に要約を示します。表に注記されているように、コンパイラ接頭辞が必須の場合もありますが、これらのオプションはすべてSQLJコマンドラインまたはプロパティ・ファイルに設定できます。

注意:

- デフォルトの場合、javacは、送信されたプラットフォームのブートストラップ・クラスと拡張クラスに対して、クラスをコンパイルします。一方、javacは、異なるJavaプラットフォームのブートストラップ・クラスと拡張クラスに対するクロスコンパイル・クラスもサポートします。javacの-bootclasspathオプションと-extdirsオプションは、クロスコンパイル専用です(JDK 1.5.x)。

- デフォルトでは、javacは、javacが取得されたJDKバージョンと互換性がある.classファイルを生成します。-targetオプションを使用して、この設定を変更します。

表8-2 SQLJによるjavacオプションのサポート

コマンドライン・オプション(-Cが記されている場合は-C接頭辞付き)

説明

SQLJとの関連

-C-bootclasspath

指定されている一連のブートストラップ・クラスに対するクロスコンパイルをjavacに指示します。

なし

-classpath

javacとJVMのCLASSPATHを設定します。

SQLJのオプションも設定します。

-d

.classファイルとSQLJプロファイル・ファイルの出力ディレクトリを設定します。

SQLJのオプションも設定します。

-depend

依存性のある古いファイルの再帰的コンパイルをjavacに指示します。

SQLJ -checksourceオプションを有効化します。

-deprecation

非推奨のAPIが使用されている出力ソースの位置をjavacに指示します。

なし

-encoding

SQLJとjavacの両方に対してエンコーディングを設定します。

SQLJのオプションも設定します。

-C-extdirs

指定されている拡張ディレクトリに対するクロスコンパイルをjavacに指示します。

なし

-g

javacデバッグ情報を生成します。

SQLJ -linemapオプションを有効化します。

-nowarn

警告を生成しないことをjavacに指示します。

SQLJ -warn=noneオプションを設定します。

-O

javacに最適化を指示します。

SQLJ -linemapオプションを無効化します。

-C-target

指定のJDKバージョン・レベル以上のJVMでのみ動作するように.classファイルを生成することをjavacに指示します。

なし

-verbose

javacにリアルタイム・ステータス・メッセージの生成を指示します。

SQLJ -statusオプションを有効化します。

javacオプションの設定値と機能の詳細は、javacのマニュアルを参照してください。

javacオプションの構文に関する注意事項

javacオプションの構文に関して、次の注意事項があります。

- JavaコンパイラのCLASSPATHとSQLJを実行するJVMのCLASSPATHを異なる値に設定する場合は、前者に-C接頭辞、後者に-J接頭辞を使用して個別に設定する必要があります。それ以外の場合、接頭辞は不要です。

- -dまたは-encodingコンパイラ・オプションを指定するときに、-C接頭辞を付けないでください。SQLJとコンパイラは、-dと-encodingで同じ設定を使用します。

- 必要に応じて-C接頭辞を-depend、-deprecation、-g、-nowarn、-Oおよび-verboseに使用できます。

- SQLJのオプションでもあるオプション(-classpath、-dおよび-encoding)を除くすべてのjavacオプションは、プロパティ・ファイルに設定する場合にはcompile.接頭辞が必要です。

- 一貫性を保持するために、値を伴うオプションには等号(=)を使用することをお薦めします。ただし、コンパイラ接頭辞(コマンドラインでは-C、プロパティ・ファイルではcompile.)を使用する場合はスペースも使用できます。

例

次の構文は、-C-bootclasspath、-C-extdirsおよび-C-targetオプションの使用例です。折り返されて表示されていますが、全体が1行で入力されています。

% sqlj -vm=/usr/local/packages/jdk1.5.2/bin/java
-compiler-executable=/usr/local/packages/jdk1.5.2/bin/javac
-C-bootclasspath=/usr/local/packages/jdk1.5.1/jre/lib/rt.jar
-C-extdirs="" -C-target=1.1.8 Demo.sqlj

プロファイル・カスタマイザのオプション

プロファイル・カスタマイザのオプションであるカスタマイザ・ハーネスのフロントエンド、Oracleデフォルトのカスタマイザおよびデバッグやデプロイメント時のセマンティクス・チェックに使用する特別なカスタマイザの詳細は、「カスタマイズおよび専用カスタマイザ」を参照してください。これは、ISO標準コード生成の場合(-codegen=iso)にのみ使用します。

コマンドラインの構文と処理

スクリプトsqljの実行によって発生するイベントの一般的なシーケンスは、「SQLJ変換処理」を参照してください。ここでは、コマンドラインの概要説明として、変換処理の詳細を説明します。

コマンドライン引数の使用方法

通常、コマンドラインでは次の構文を使用します。

% sqlj <optionlist> filelist

JVMを起動するときに、sqljスクリプトからJVMにすべてのコマンドライン引数が渡されます。JVMは渡された引数を該当機能(Javaコンパイラやプロファイル・カスタマイザなど)に渡します。

オプションとフラグの設定値は等号(=)を使用して指定しますが、簡略化するために、フラグを有効にする場合は=trueを指定する必要はありません。フラグ名の入力のみで十分です。ただし、フラグを無効にするには、=falseを指定する必要があります。フラグが前の値から切り替わらないためです。次に例を示します。

行マッピングを有効にするには、-linemap=trueまたは単に-linemapを指定します。

行マッピングを無効化するには、-linemap=falseを指定します。

注意:
コマンドラインまたはプロパティ・ファイルで同じオプションを2回以上指定すると、最後の値が使用されます。

オプション・リストの引数

オプション・リストの引数は、次のように使用されます。

- 接頭辞-J、-Cまたは-Pが付いていないオプションはSQLJのオプションです(直接サポートされるコンパイラ・オプションは除きます)。SQLJトランスレータを起動するときに、JVMからSQLJトランスレータに渡されます。

- -J接頭辞が付くオプションはJVMのオプションで、JVMでそのまま使用されます。これらのオプションは、コマンドラインまたは環境変数SQLJ_OPTIONSで指定する必要があります。トランスレータ・オプションと同様に、オプションの設定では次のように等号(=)を使用します。

-J-Djavac.pipe.output=true

JavaコンパイラのCLASSPATHとSQLJを実行するJVMのCLASSPATHを異なる値に設定する場合は、前者に-C接頭辞、後者に-J接頭辞を使用して個別に設定する必要があります。

- -C接頭辞が付いたオプションはJavaコンパイラのオプションで、JVMがコンパイラを起動するときに、JVMからコンパイラに渡されます。値をとるコンパイラ・オプションには特別なサポートが必要なため、javacオプションに対して実装されました。これらについても、次のように等号を使用できます(空白でも機能します)。

-C-bootclasspath=/usr/local/packages/jdk1.5.1/jre/lib/rt.jar

- オプションに-P接頭辞を付けると、SQLJプロファイル・カスタマイザのオプションになり、JVMがカスタマイザを起動するときに、カスタマイザに渡されます。これは、ISO標準コード生成(-codegen=iso)の場合にのみ使用します。トランスレータ・オプションと同様に、オプションの設定では次のように等号(=)を使用します。

-P-user=scott

SQLJでの自動実行の対象でないプロファイルのカスタマイズは、高度な機能といえます。

関連項目:
付録A「カスタマイズおよび専用カスタマイザ」

ファイル・リストの引数

ファイル・リストの解析、ワイルドカード文字の処理およびファイル名の展開は、SQLJフロントエンドによって行われます。デフォルトのファイル処理は、次のように展開されます。

- .sqljファイルがSQLJトランスレータ、JavaコンパイラおよびSQLJプロファイル・カスタマイザによって処理されます(プロファイル・カスタマイザは-codegen=isoの場合のみ)。

- .javaファイルがJavaコンパイラによって処理されます。SQLJトランスレータは、このファイルを使用して型を解決します。

- .serプロファイルと.jarファイルは、プロファイル・カスタマイザでのみ処理されます(-codegen=isoの場合のみ)。

コマンドラインで.sqljファイルと.javaファイルを一緒に指定することも、.serファイルと.jarファイルを一緒に指定することも可能ですが、この2つのカテゴリを一緒には指定できません。.sqljファイルと.javaファイル間に依存関係がある場合、つまり互いのコードにアクセスする必要がある場合は、SQLJの各実行時に、依存し合うすべてのファイルをコマンドラインに入力する必要があります。別々のSQLJ実行に対して指定することはできません。これは、SQLJがすべての型を解決できなくなるためです。

注意:
コマンドラインで.javaファイル名を入力する方法以外に、-checksourceオプションを有効にし、その後で.javaファイルがCLASSPATHに含まれていることを確認する方法もあります。

ソース間の競合防止

SQLJトランスレータでは、同一ディレクトリの同一クラスを複数のソース・ファイルで定義できないようになっています。コマンドラインのファイル・リストに同じ.sqljファイルまたは.javaファイルへの参照が複数あると、2番目以降の参照がすべてコマンドラインから破棄されます。また、リスト内の.javaファイルと.sqljファイルのベース名とディレクトリが同じときに、-dirオプションを指定しないと、.sqljファイルのみが処理されます。この処理は、ワイルドカード文字にも適用されます。

次のコマンドラインの例について考えてみます(%はシステム・プロンプトです)。カレント・ディレクトリ/myhome/mypackageに、ファイルFoo.sqljとFoo.javaがあるとします。

% sqlj Foo.sqlj /myhome/mypackage/Foo.sqlj

両方の参照先が同じファイルなので、トランスレータは/myhome/mypackage/Foo.sqljをコマンドラインから破棄します。

% sqlj Foo.sqlj Foo.java

トランスレータはFoo.javaをコマンドラインから破棄します。そうしないと、このコマンドラインは、トランスレータがFoo.javaとの読み書きを両方とも同時に実行することになります。

% sqlj Foo.*

この場合も、トランスレータはFoo.javaをコマンドラインから破棄します。そうしないと、トランスレータはFoo.sqljとFoo.javaの両方を検索するので、書込み先と読込み元が同時にFoo.javaになります。

% sqlj -dir=outdir -d=outclasses Foo.sqlj Foo.java

これは問題ありません。生成されるFoo.javaはoutdirサブディレクトリにあり、読み取られるFoo.javaは/myhome/mypackageディレクトリにあるためです。Foo.javaとFoo.sqljで異なるパッケージ内のクラスを定義すると仮定すると、Javaコンパイルで作成される.classファイルは、outclassesディレクトリの階層下の異なるサブディレクトリに配置されることになります。

このようにコマンドラインが処理されるので、次のようなコマンドを入力しても、問題なく実行されます。(問題のあるファイル参照は自動的に破棄されます。)

% sqlj *.sqlj *.java

この処理は様々な状況で利用できます。

コマンドラインの例と結果

次に、コマンドラインの例を示します(%はシステム・プロンプトです)。この例では、コマンドライン構文の完全な例を示すために、いくつか高度な概念が使用されていますが、これについてはこの章の後半で詳細に説明します。

% sqlj -J-Duser.language=ja  -warn=none -J-prof -encoding=SJIS *Bar.sqlj Foo*.java

このsqljスクリプトはJVMを起動して、JVMにSQLJトランスレータのクラス名を渡し、コマンドラインの引数を渡します。JVMは、SQLJのオプションをトランスレータとコンパイラに渡します。JVMに対するオプション(-Jが付いたオプション)がある場合、このスクリプトは、トランスレータのクラス・ファイル名の前に、このオプションをJVMに渡します(これは、Javaを手動で起動する場合に、クラス・ファイル名の入力の前に、Javaオプションを入力するのと同様です)。この例では、デフォルトのOracle固有コード生成を使用しているため、カスタマイズはありません。

前述の処理が完了すると、ユーザーが次のように入力したときと同じ結果になります(SushiBar.sqlj、DiveBar.sqlj、FooBar.javaおよびFooBaz.javaがすべてカレント・ディレクトリにある場合)。

% java -Duser.language=ja -prof sqlj.tools.Sqlj -warn=none -encoding=SJIS SushiBar.sqlj DiveBar.sqlj FooBar.java FooBaz.java

このコマンドラインは折り返されて表示されていますが、全体が1行で入力されています。

関連項目:
「Java Virtual Machine(JVM)に渡すオプション(-J)」

コマンドラインを実行せずにエコーする場合

SQLJの-nオプション(または-vm=echo)を使用して、sqljスクリプトによって生成され、SQLJトランスレータに渡されるコマンドラインが、実行されずに、エコーされます。これには、環境変数SQLJ_OPTIONSおよびコマンドラインの設定値が含まれますが、プロパティ・ファイルの設定値は含まれません。

関連項目:
「コマンドラインのエコー(-n)」

プロパティ・ファイルによるオプション設定

コマンドラインのかわりに、プロパティ・ファイルでも、SQLJトランスレータ、JavaコンパイラおよびSQLJプロファイル・カスタマイザに対してオプションを指定できます。

Javaコンパイラを別のJVMで実行し、このJVMに対してコンパイル処理オプションを指定する場合も、プロパティ・ファイルで指定できます。SQLJでの変換後、コンパイラの実行時に、オプションがJVMに渡されます。ただし、一般的にはコマンドラインで-C-J接頭辞を使用して、コンパイラのJVMに渡します。

SQLJの次のオプション、フラグおよび接頭辞を設定するために、プロパティ・ファイルを使用することはできません。

- -classpath

- -help、-help-long、-help-alias、-C-help、-P-help

- -J

- -n

- -passes

- -props

- -version、-version-long

- -vm

たとえば、JVMに対するオプションはプロパティ・ファイルで指定できません。プロパティ・ファイルの読込みが、JVMの起動後に実行されるためです。

また、プロパティ・ファイルでは、loadjavaとの互換性のためにコマンドラインでは認められているオプションの略称は使用できません(-e、-h、-p、-u、-v)。

注意:
SQLJのプロパティ・ファイルの説明は、サーバー側SQLJではなく、クライアント側SQLJを対象にしています。サーバー側のSQLJオプションの指定はメカニズムが異なり、オプションの小規模なサブセットのみがサポートされます。詳細は、「サーバー側の埋込みトランスレータでサポートされるオプション」を参照してください。

プロパティ・ファイルの構文

プロパティ・ファイルでは、1行に1つのオプションを設定します。SQLJのオプション行、コンパイラのオプション行およびカスタマイザのオプション行を混在できます。SQLJフロントエンドによってオプション行が解析され、適切に処理されます。

次に、各種オプションの構文を示します。

- 各SQLJオプションの前に、ハイフンではなくsqlj.(ピリオドまで)を付けます。この接頭辞で始まるオプションのみがSQLJトランスレータに渡されます。次に例を示します。

sqlj.warn=none
sqlj.linemap=true

- 各Javaコンパイラ・オプションの前に、-C-ではなく、接頭辞compile.(ピリオドまで)を付けます。この接頭辞で始まるオプションがJavaコンパイラに渡されます。次に例を示します。

compile.verbose
compile.bootclasspath=/usr/local/packages/jdk1.5.1/jre/lib/rt.jar

- 汎用的なプロファイル・カスタマイズ・オプション(どのカスタマイザにも適用されるオプション)には、-P-ではなく、接頭辞profile.(ピリオドまで)を付けます。この接頭辞で始まるオプションのみがプロファイル・カスタマイザに渡されます。次に例を示します。

profile.backup
profile.user=scott/tiger

特定のカスタマイザに対するオプションを指定するには、次のようにprofile.Cを使用します。

profile.Csummary
profile.Coptparamdefaults=VAR%(50),LONG%(500),RAW_TYPE()

Oracleのデフォルト・カスタマイズの対象でないプロファイルのカスタマイズは、高度な機能といえます。

関連項目:
付録A「カスタマイズおよび専用カスタマイザ」

- コメント行はシャープ記号(#)で始めます。次に例を示します。

# Comment line.

- 空白行も使用できます。

コマンドラインと同じように、プロパティ・ファイルでもフラグの有効化/無効化をtrue/false、on/off、1/0、またはyes/noで指定できます。フラグを有効にするには、次のようにフラグ名の入力のみで十分です。設定値の入力は必要ありません。

sqlj.linemap

注意:
一貫性を保持するために、プロパティ・ファイル内の値を伴うオプションには(スペースが使用できる場合にも)等号(=)を使用することをお薦めします。

プロパティ・ファイルの簡単な例

プロパティ・ファイルの設定例を示します。

# Set user and JDBC driver
sqlj.user=scott
sqlj.driver=oracle.jdbc.OracleDriver

# Turn on the compiler verbose option
compile.verbose

この設定は、次のSQLJコマンドラインに相当します。

% sqlj -user=scott -driver=oracle.jdbc.OracleDriver -C-verbose

プロパティ・ファイル: デフォルト以外の接続コンテキスト・クラス

宣言した接続コンテキスト・クラスSourceContextの設定値をプロパティ・ファイルで指定する例を示します。

# JDBC driver
sqlj.driver=oracle.jdbc.OracleDriver

# Oracle 9.2 on spock.natdecsys.com
sqlj.user@SourceContext=sde
sqlj.password@SourceContext=fornow
sqlj.url@SourceContext=jdbc:oracle:thin:@207.67.155.3:1521/myservice

# Warning settings
sqlj.warn=all

# Cache
sqlj.cache=on

デフォルトのプロパティ・ファイル

SQLJコマンドラインでプロパティ・ファイルを指定したどうかに関係なく、SQLJフロントエンドでsqlj.propertiesというファイルが検索されます。このファイルの検索は、Javaホーム・ディレクトリ、ユーザー・ホーム・ディレクトリ、およびカレント・ディレクトリの順番で実行されます。見つかった各sqlj.propertiesファイルが順番に処理され、オプションの前の設定値は新しい設定値でオーバーライドされます。つまり、カレント・ディレクトリにあるsqlj.propertiesファイルで設定されたオプション値によって、ユーザー・ホーム・ディレクトリまたはJavaホーム・ディレクトリにあるsqlj.propertiesファイルで設定されたオプション値がオーバーライドされます。

関連項目:
「オプション設定の優先順位」

環境変数SQLJ_OPTIONSによるオプションの設定

Oracle SQLJ実装では、コマンドラインのかわりに環境変数SQLJ_OPTIONSを使用して、SQLJオプションを設定できます。「コマンドラインのみ」と示されているオプションは、プロパティ・ファイルでは設定できませんが、SQLJ_OPTIONS変数を使用すると設定できます。

SQLJ_OPTIONS変数では、あらゆるSQLJオプションを設定できますが、この変数で設定したオプション値は、JVMに渡されます。この変数は、同じ設定値を繰り返し使用するコマンドライン専用オプション(-classpathなど)に特に便利です。

次に、SQLJ_OPTIONS設定の例を示します。

-vm=jview -J-verbose

SQLJ_OPTIONSを使用すると、SQLJによってSQLJ_OPTIONSの設定値が、SQLJコマンドラインの先頭(他のコマンドライン・オプション設定の前)に、順番に挿入されます。

注意:
通常、SQLJ_OPTIONSの構文はコマンドラインの構文と同じですが、これはオペレーティング・システムによって異なります。オペレーティング・システム固有の制限が存在することもあります。たとえばMicrosoft Windows 95では、「コントロール パネル」の「システム」の「ハードウェア環境」タブを使用します。また、Windows 95では変数の設定に等号(=)を使用できないため、SQLJでは=のかわりに#を使用してSQLJ_OPTIONSを設定できます。詳細は、使用するオペレーティング・システムのドキュメントを参照してください。

オプション設定の優先順位

SQLJでは、オプション値が次の順に設定されます。

1. オプションをデフォルト値に設定します(デフォルト値がある場合)。

2. Javaのホーム・ディレクトリでsqlj.propertiesファイルを探します。見つかると、このファイルの指定に基づき、オプションを設定します。

3. ユーザーのホーム・ディレクトリでsqlj.propertiesファイルを探します。見つかると、このファイルの指定に基づき、オプションを設定します。

4. カレント・ディレクトリでsqlj.propertiesファイルを探します。見つかると、このファイルの指定に基づき、オプションを設定します。

5. 環境変数SQLJ_OPTIONSでオプション設定を探し、見つかったオプション設定をコマンドラインの先頭に挿入します。SQLJ_OPTIONSの指定どおりに、オプションを設定します。

6. コマンドラインでオプション設定を探し、この指定に基づき、オプション値を設定します。SQLJはコマンドラインを処理しながら、-propsオプションで指定されているファイルを調べ、その指定に基づき、オプション値を設定します。

注意:

- 同じオプションが複数回設定されていると、前の設定値が後の設定値によって上書きされます。

- sqlj.propertiesファイルのオプション設定は、上から下に読み込まれます。つまり、下方のエントリが上方のエントリより優先されます。

- コマンドラインの-propsオプションでプロパティ・ファイルを指定すると、このファイルのオプション設定がコマンドラインの-propsオプションの位置に挿入されます。

- SQLJでは、コマンドラインのオプションが、-propsファイルから挿入されたオプションも含めて、左から右に読み取られます。つまり、後(右方)の設定値が前(左方)の設定値より優先されます。

例

SQLJを次のように実行するとします。

% sqlj -user=scott -props=myprops.properties -dir=/home/java

ファイルmyprops.propertiesはカレント・ディレクトリにあり、次の値が設定されているものとします。

sqlj.user=tony
sqlj.dir=/home/myjava

これらの設定値は、コマンドラインの-propsオプションの指定位置に挿入されているかのように処理されます。したがって、userオプションの設定値としては、scottエントリよりtonyエントリが優先され、dirオプションの設定値としては、/home/myjavaエントリより/home/javaエントリが優先されます。

基本的なトランスレータ・オプション

ここでは、SQLJの実行時に指定できる基本的なフラグとオプションの構文と機能について説明します。ここで説明するオプションは、標準の操作モードで実行できます。プロパティ・ファイルでも指定できるオプションの構文も示します。

ここでは、次の項目について説明します。

- 基本的なコマンドライン専用オプション

- 出力ファイルとディレクトリのオプション

- 接続オプション

- レポートと行マッピングのオプション

- DMSのオプション

- コード生成、最適化およびCHAR比較のオプション

関連項目:

- 「プロパティ・ファイルによるオプション設定」

- 「高度なトランスレータ・オプション」

- 「トランスレータによる代替環境のサポートとオプション」

基本的なコマンドライン専用オプション

次の基本的なオプションはSQLJのコマンドラインまたは環境変数SQLJ_OPTIONSでのみ指定できます。

- -props

- -classpath

- -help、-help-long、-help-alias、-P-help、-C-help

- -version、-version-long

- -n

これらのオプションは、プロパティ・ファイルでは指定できません。コマンドライン専用フラグ(-help、-versionおよび-n)では、=true構文を使用できません。これらのフラグを有効にするには、次のようにフラグ名のみを入力します。

sqlj -version-long

注意:
コマンドラインまたはSQLJ_OPTIONSでのみ設定可能な高度なオプション、フラグおよび接頭辞として、-J、-passesおよび-vmがあります。

入力プロパティ・ファイル(-props)

-propsオプションでは、SQLJがオプション設定を読み取るプロパティ・ファイルを指定します。コマンドラインの構文は、次のとおりです。

-props=filename

次に例を示します。

-props=myprops.properties

Java Virtual Machine(JVM)とコンパイラで使用するCLASSPATH(-classpath)

Javaの大半のJVMおよびコンパイラへの対応として、SQLJはコマンドラインで指定された-classpathオプションを認識します。このオプションの設定では、ほとんどのJVMまたはコンパイラと同じようにスペースを使用することも、他のSQLJオプションと同じように等号(=)を使用することも可能です。この例(両方ともUNIX環境で実行)を次に示します。

-classpath .:$ORACLE_HOME/jdbc/lib/ojdbc5.jar:$ORACLE_HOME/sqlj/lib/translator.jar:$ORACLE_HOME/sqlj/lib/runtime12.jar

-classpath= .:$ORACLE_HOME/jdbc/lib/ojdbc5.jar:$ORACLE_HOME/sqlj/lib/translator.jar:$ORACLE_HOME/sqlj/lib/runtime12.jar

-classpathオプションは、JVMとJavaコンパイラの両方に対して、JavaのCLASSPATHを設定します。それぞれ別のCLASSPATHを使用する場合は、SQLJの-Jおよび-C接頭辞を使用します。

関連項目:
「オプション設定を他の実行可能プログラムに渡す接頭辞」

注意:
この章で説明する他のオプションと同様、-classpathオプションの設定で=を使用しても、このオプション文字列がJVMおよびコンパイラに渡されるときに=が削除されます。これは、JVMおよびコンパイラのオプション設定では、=構文がサポートされないためです。

コマンドラインの構文は、次のとおりです。

sqlj -classpath=class_path

次に例を示します。

sqlj -classpath=$ORACLE_HOME/jdbc/lib/ojdbc5.jar:$ORACLE_HOME/sqlj/lib/translator.jar:$ORACLE_HOME/sqlj/lib/runtime2.jar

SQLJのオプション情報(-help)

コマンドラインで-helpフラグを次のように設定して、SQLJオプションに関する表示情報の詳細度を指定できます。

- -help

- -help-long

- -help-alias

このオプションを有効にするには、次のようにコマンドラインで設定します。

% sqlj -help

% sqlj -help-long

% sqlj -help-alias

これらの形式のいずれかで-helpフラグを指定した場合、コマンドラインでファイル名などのオプションを指定しても、入力ファイルの変換は実行されません。SQLJでは、トランスレータの実行とヘルプ表示のどちらか一方を想定しており、両方を同時に実行することはできません。

プロファイル・カスタマイザまたはJavaコンパイラに関する説明を表示するには、次のように-Pおよび-C接頭辞を付けてヘルプを要求します。-helpフラグと同じように、カスタマイザまたはコンパイラのヘルプを要求すると、変換されません。

% sqlj -P-help

% sqlj -C-help

他のコマンドライン専用フラグと同様に、-help (および-P-helpと-C-help)では、=true構文を使用できません。有効にするには、フラグ名のみを入力します。

注意:

- loadjavaユーティリティとの互換用に、-helpのかわりに-hをコマンドラインで指定できます。

- 単一のコマンドラインで-helpフラグを複数設定できます。-P-helpと-C-helpも設定できます。

- -Pと-Cは通常、プロパティ・ファイルで設定できますが、-P-helpと-C-helpはコマンドライン専用です。

- 処理対象ファイルを指定しないでSQLJを実行した場合も、ヘルプが表示されます。つまり、-helpの設定時と同じ結果になります。

最も基本的なヘルプを表示するには、-helpを指定します。次の情報が表示されます。

- 使用頻度が最も高いSQLJオプションの概要

- 指定できるその他の-helpフラグ値のリスト

-help-longを設定すると、SQLJオプションの詳細情報が一覧表示されます。具体的には、各オプションに関して次の情報が表示されます。

- オプション名

- オプションの型(intやStringなど、オプションの入力値としてのJava型)

- 説明

- 現行の値

- 現行の値の設定方法(コマンドライン、プロパティ・ファイルまたはデフォルト)

注意:
オプション設定の結果を確認するには、そのオプションと-help-longオプションを同一のコマンドラインで指定します。この機能は、特に複雑なオプション(-warnなど)を指定する場合やオプションを組み合せる場合に便利です。

-help-aliasを設定すると、loadjavaユーティリティ対応として、コマンドラインでサポートされている略称が一覧表示されます。

コマンドラインの構文は、次のとおりです。

sqlj help_flag_settings

次に例を示します。

sqlj -help
sqlj -help -help-alias
sqlj -help-long
sqlj -warn=none,null -help-long
sqlj -help-alias

デフォルトでは、これらの設定は無効になっています。

SQLJのバージョン番号(-version)

コマンドラインで-versionフラグを次の値に設定して、表示するSQLJおよびJDBCドライバのバージョンに関して様々なレベルの情報の表示を指定します。

- -version

- -version-long

このオプションを有効にするには、次のようにコマンドラインで設定します。

% sqlj -version

% sqlj -version-long

-versionオプションを使用すると、コマンドラインでファイル名などのオプションを指定しても、入力ファイルの変換は行われません。SQLJでは、トランスレータの実行とバージョン情報の表示のどちらか一方を想定しており、両方を同時に実行することはできません。コマンドラインに入力したプロパティ・ファイルなどはすべて無視されます。他のコマンドライン専用フラグと同様に、-versionには、=true構文を使用できません。このフラグを有効にするには、フラグ名のみを入力します。

-versionを設定すると、次のようにSQLJのリリース番号が表示されます。

sqlj -version
Oracle SQLJ Release 11.2.0.1.0 Production
Copyright  1997, 2008, Oracle Corporation. All Rights Reserved.

-version-longを設定すると、SQLJとSQLJランタイム・ライブラリのリリース、JDBCドライバのリリース番号(見つかった場合)、Java環境に関する情報が表示されます。たとえば、Oracle JDBCを使用している場合は、このオプションで次のように表示されます。

sqlj -version-long
Oracle SQLJ Release 11.2.0.1.0 Production
Copyright  1997, 2008, Oracle Corporation. All Rights Reserved.
JDBC version: Oracle JDBC driver version 11.2 (11.2.0.1.0)
Java version: 1.6 (1.6.0_04)

このフラグによって、SQLJのインストールと、現在使用しているJDBCやJDKのバージョンを確認できます。コマンドラインの構文は、次のとおりです。

sqlj version_flag_settings

次に例を示します。

sqlj -version
sqlj -version -version-long
sqlj -version-long

デフォルトでは、これらの設定は無効になっています。

コマンドラインのエコー(-n)

-nフラグをコマンドラインで指定すると、sqljスクリプトは、SQLJトランスレータに渡されるコマンドライン全体(SQLJ_OPTIONSの設定を含む)を作成し、SQLJトランスレータでは実行しないでユーザーにエコーするように指示されます。これには、SQLJトランスレータを実行するために起動されるJVM名の取得とエコー、およびトランスレータのクラス名全体のエコーも含まれます。プロパティ・ファイルの設定値は含まれません。

次の内容が表示されます。

- 略称で入力したオプション名を完全に展開した名前(loadjava対応の-uなどの略称が展開され、完全な名前が表示されます。)

- コマンドの文字列全体が構築されてトランスレータに渡されるときのオプションの並び順

- SQLJ_OPTIONSの設定とコマンドラインの設定の競合の可能性

-nオプションは、コマンドラインまたはSQLJ_OPTIONS変数のどこにでも指定できます。他のコマンドライン専用フラグと同様に、-nには、=true構文を使用できません。このフラグを有効にするには、フラグ名のみを入力します。

次の場合を想定してください。SQLJ_OPTIONSで次のように設定します。

-user=scott/tiger@jdbc:oracle:thin:@ -classpath=/myclasses/bin

次のコマンドラインを入力します。

% sqlj -n -e SJIS myapp.sqlj

次のエコーが表示されます。

java -classpath /myclasses/bin sqlj.tools.Sqlj -user=scott/tiger@jdbc:oracle:thin:@ -C-classpath=/myclasses/bin
-encoding=SJIS myapp.sqlj

全体が1行で入力されていることに注意してください。

注意:

- コマンドラインでパスワードをエコーすることは安全な方法ではありません。

- -nのかわりに、-vm=echoと入力することも可能です。

- オプション設定を確認するもう1つの効果的な方法は、-help-longフラグを使用することです。これによって、すべてのオプションの現行の設定が表示されますが、その中には、コマンドラインで設定したその他のオプションと、プロパティ・ファイルおよびSQLJ_OPTIONSの設定値も含まれます。

コマンドラインの構文は、次のとおりです。

-n

次に例を示します。

-n

デフォルトでは、この設定は無効になっています。

出力ファイルとディレクトリのオプション

-encodingで、SQLJの入力および出力ソース・ファイルのエンコーディングを指定します。次のオプションで、SQLJの出力ファイルを格納するディレクトリを指定します。

- -d

- -dir

入力および出力ソース・ファイルの文字エンコーディング(-encoding)

-encodingオプションで、エンコーディングを指定します。このエンコーディングは、.sqljおよび.java入力ファイルとグローバリゼーション・サポートの目的で生成される.javaファイルに適用されます。javacとの互換性を確保するため、コマンドラインでこのオプションを設定するときに、次の例のように空白または等号(=)を使用できます。

-encoding=SJIS

-encoding SJIS

ただし、プロパティ・ファイルでsqlj.encodingを指定するときは、スペースではなく=を使用します。

-compiler-encoding-flagがオンの場合、このオプションを指定すると、Javaコンパイラにも渡されます。Javaコンパイラは、この値に基づき、処理する.javaファイルの文字エンコーディングを指定します。

留意点を次に挙げます。

- -classpathおよび-dオプションと同様、-encodingオプションの設定で=を使用しても、このオプション文字列がJVMおよびコンパイラに渡される際に=が削除されます。JVMとコンパイラでは、オプション設定に=を使用できないためです。

- loadjavaユーティリティ対応として、コマンドラインで指定した-eは-encodingとして認識されます。

- Javaプロパティ・ファイル(sqlj.propertiesやconnect.propertiesなど)には、-encodingオプションを使用できません。プロパティ・ファイルでは、常に8859_1エンコーディングを使用します。これは、特別なSQLJの機能ということではなく、一般的なJavaの機能です。ただし、Unicodeのエスケープ・シーケンスなら、プロパティ・ファイルで使用できます。ネイティブ・コードのファイル用のエスケープ・シーケンスを作成するには、native2asciiユーティリティを使用します。

関連項目:
「native2asciiによるソース・ファイルの文字エンコーディングの変換」

コマンドラインの構文は、次のとおりです。

-encoding=Java_character_encoding

次に例を示します。

-encoding=SJIS

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.encoding=Java_character_encoding

次にその例を示します。

sqlj.encoding=SJIS

デフォルトでは、このオプションはJVMシステム・プロパティfile.encodingに設定されます。

.serおよび.classファイルの出力ディレクトリ(-d)

-dオプションは、SQLJトランスレータで生成されるプロファイルのルート出力ディレクトリを指定するもの(ISO標準コード生成、つまり-codegen=isoの場合にのみ関係する)ですが、コンパイラで生成される.classファイルのルート出力ディレクトリを指定するためにJavaコンパイラにも渡されます。プロファイルが.serファイルとして生成されるか(デフォルト)、.classファイルとして生成されるか(-ser2classオプションが有効な場合)は、-dオプションによる配置とは無関係できます。

ディレクトリを指定すると、このディレクトリの下の該当パッケージに出力ファイルが生成されます。たとえば、ソース・ファイルがa.b.cパッケージにあるときに、/mydirディレクトリを指定すると、出力ファイルが/mydir/a/b/cディレクトリに格納されます。相対ディレクトリ・パスを指定すると、カレント・ディレクトリからの相対になります。

javac対応として、コマンドラインでこのオプションを指定するときは、次のようにスペースまたは等号(=)を使用できます(次の例では、どちらも/rootを生成されたプロファイル・ファイルのルート・ディレクトリとしています)。

-d=/root

-d /root

ただし、プロパティ・ファイルで-dを指定するときは、スペースではなく=を使用します。次に例を示します。

sqlj.d=/root

カレント・ディレクトリが/root/home/mydirのときに、次のように-dオプションで相対ディレクトリ・パスmysubdir/myothersubdirを指定すると、/root/home/mydir/mysubdir/myothersubdirをルート・ディレクトリとして、プロファイル・ファイルが生成されます。

-d=mysubdir/myothersubdir

標準構文も使用できます。つまり、次のように、カレント・ディレクトリをピリオド1個で、1レベル上のディレクトリをピリオド2個で表現できます。

-d=.

-d=../paralleldir

-dオプションに何も指定しないと、生成された.classファイルは、SQLJで生成された.javaファイルの-dirオプションに従って、対応する.javaファイルと同じディレクトリに格納されます。生成された.serファイルは、対応する.sqljファイルと同じディレクトリに格納されます。

注意:

- -dを次のように無指定にすることも可能です(プロパティ・ファイル中の設定値をオーバーライドする場合)。

-d=

- この説明では、ファイル・セパレータとしてスラッシュ(/)を使用しています。ただし、このようなオプションを実際に指定するときは、JVMのfile.separatorシステム・プロパティで指定したオペレーティング・システムのファイル・セパレータを使用する必要があります。

- -classpathおよび-encodingオプションと同様、-dオプションの設定で等号(=)を使用しても、このオプション文字列がJVMおよびコンパイラに渡される際に=が削除されます。JVMとコンパイラでは、オプション設定に=を使用できないためです。

コマンドラインの構文は、次のとおりです。

-d=directory_path

次に例を示します。

-d=/topleveldir/mydir

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.d=directory_path

次に例を示します。

sqlj.d=/topleveldir/mydir

このオプションにはデフォルト値はありません。

.javaファイルの出力ディレクトリ(-dir)

SQLJトランスレータで生成する.javaファイルのルート・ディレクトリは、-dirオプションで指定します。ディレクトリを指定すると、このディレクトリの下の該当パッケージに出力ファイルが生成されます。たとえば、ソース・ファイルがa.b.cパッケージにあるときに、/mydirディレクトリを指定すると、出力ファイルが/mydir/a/b/cディレクトリに格納されます。相対ディレクトリ・パスを指定すると、カレント・ディレクトリからの相対になります。

次の簡単な例では、/rootをルート・ディレクトリとして.javaファイルが生成されます。

-dir=/root

カレント・ディレクトリが/root/home/mydirで、次のように-dirオプションに相対ディレクトリ・パスmysubdir/myothersubdirを設定しているとします。

-dir=mysubdir/myothersubdir

/root/home/mydir/mysubdir/myothersubdirが生成された.javaファイルのルート・ディレクトリになります。

標準構文も使用できます。つまり、次のように、カレント・ディレクトリをピリオド1個で、1レベル上のディレクトリをピリオド2個で表現できます。

-dir=.

-dir=../paralleldir

-dirオプションを指定しないと、元の.sqljソース・ファイルと同じディレクトリにファイルが生成されます(カレント・ディレクトリには生成されません)。.sqljソース・ディレクトリを出力ディレクトリとして指定する(プロパティ・ファイルなどで行った他の-dir設定を無効にする)には、次のように-dirオプションを使用します。

-dir=

注意:
-dオプションでなく、-dirオプションを指定した場合は、その際に-dirで指定したディレクトリに、生成済の.classファイルが一緒に格納されます。ただし、生成済の.serファイルの格納先は、.sqljファイルと同じディレクトリとなります。

コマンドラインの構文は、次のとおりです。

-dir=directory_path

次に例を示します。

-dir=/topleveldir/mydir

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.dir=directory_path

次に例を示します。

sqlj.dir=/topleveldir/mydir

このオプションにはデフォルト値はありません。

接続オプション

オンライン・セマンティクス・チェック用のデータベース接続の際は、次のオプションを使用します。

- -user

- -password

- -url

- -default-url-prefix

- -driver

- driver_name

SQLJトランスレータは、アプリケーション実行時と同じデータベースまたはスキーマに接続する必要はありません。アプリケーションのソース・コード中の接続情報は、SQLJオプションの接続情報とは別々に指定できます。実際に、デプロイメント環境が開発時とテスト時には使用できないことがあります。

オンライン・セマンティクス・チェックとユーザー名(-user)

データベース接続を行わない簡単なセマンティクス・チェックをオフライン・チェックと呼びます。接続が必要となる、より詳細なセマンティクス・チェックをオンライン・チェックと呼びます。オンライン・チェックでは、SQLJの強い型指定パラダイムの主要メリットの1つが提供されます。つまり、互換性のない型によって、通常であればランタイムSQL例外となるものが、ユーザーがアプリケーションを実行する前の変換中に捕捉されます。

-userオプションを使用すると、オンライン・セマンティクス・チェックが有効になり、基本スキーマのユーザー名(スキーマ名)を指定できます。基本スキーマとは、トランスレータに提供されるサンプル・データベース・スキーマであり、トランスレータでチェック実行時に使用されます。-userオプションは、パスワードとURLの指定にも使用できます(これに対し、-passwordと-urlオプションは別々に使用します)。

-userフラグ以外では、オンライン・セマンティクス・チェックを有効化および無効化できません。SQLJでは、-userオプションの有無によって、オンライン・セマンティクス・チェックを有効化および無効化します。

注意:

- SQLJの-parseオプションの設定によっては、-userオプションの効果が無視され、オンライン・セマンティクス・チェックも無効になります。

- loadjavaユーティリティ対応として、-userのかわりに-uをコマンドラインで指定できます。

- ユーザー名には文字/または@を使用できません。

- コマンドラインでユーザー名を指定するときは、次のように=のかわりにスペースを使用できます。

-user scott/password
-user@CtxClass scott/password
-u scott/password
-u@CtxClass scott/password

- 文字@を使用したパスワードは、-userオプションでは設定できません。-userと-passwordをそれぞれ別に設定する必要があります。

- ログイン名がDBAグループのメンバーである場合、SYSDBAとして、SYSスキーマに接続する特別な権限があります。この場合、ユーザー名SYSまたはINTERNALを指定できます。

- ISOコード生成では、トランスレータの-user設定がプロファイル・カスタマイザに転送されますが、カスタマイザのuser設定によって無視されることもあります。

次に、-userオプションの最も基本的な使用方法を示します。

-user=scott

DefaultContextクラスのデフォルト接続などのインスタンスのみを使用すると、設定値がすべてのSQLJ実行文に適用されます。この例では、scottスキーマに対してオンライン・チェックが行われます。

パスワードまたはURL(あるいはその両方)をユーザー名と一緒に次の構文で指定することも可能です(パスワードの前に/を付け、URLの前に@を付けます)。

-user=scott/password

-user=scott@jdbc:oracle:oci:@

-user=scott/password@jdbc:oracle:oci:@

URLを-urlオプションで指定し、パスワードを対話形式または-passwordオプションで指定する方法もあります。

オンライン・セマンティクス・チェックを無効化するには、次のように-userオプションを空の文字列に設定します。

-user=

デフォルト接続やDefaultContextクラスの他のインスタンスのみを使用すると、この設定値がすべてのSQLJ実行文に適用されます。

オンライン・セマンティクス・チェックの無効化は、プロパティ・ファイルで有効にしたオンライン・チェックをコマンドラインでオーバーライドする場合や、デフォルトのプロパティ・ファイルで有効にしたオンライン・チェックをユーザー指定のプロパティ・ファイル(-propsオプションで指定)でオーバーライドする場合などに便利です。

専用のユーザー名URL.CONNECTもあります。このユーザー名を使用して、URLで接続のユーザーとパスワードなどの詳細を指定できます。

関連項目:
「オンライン・セマンティクス・チェックに使用する接続URL(-url)」

アプリケーションでさらに接続コンテキスト・クラスを宣言して使用する場合は、これらのクラスのインスタンスを使用するSQLJ実行文をテストするときに-userを使用できます。次のように、特定の接続コンテキスト・クラス(CtxClassなど)のオンライン・チェックを行うユーザー名を指定します。

-user@CtxClass=scott

この指定では、CtxClassの接続コンテキストのインスタンスが指定されているすべてのSQLJ実行文に対して、scottスキーマのオンライン・チェックが行われます。

デフォルトの接続コンテキスト・クラスの場合と同様、次のように特定の接続コンテキスト・クラスに対するパスワードまたはURLを-userで指定できます。

-user@CtxClass=scott/password@jdbc:oracle:oci:@

接続コンテキスト・クラスCtxClassは、ソース・コード中に宣言するか、あらかじめ.classファイルにコンパイルしておく必要があります。

各接続コンテキスト・クラスに対してオンライン・チェックの有効化やユーザー名の設定を行う場合、そのクラスごとに-userオプションを個別に指定します。次に示したように、この設定は他のユーザーには反映されません。次に例を示します。

-user@CtxClass1=user1 -user@CtxClass2=user2 -user@CtxClass3=user3

アプリケーションで複数の接続コンテキスト・クラスを使用する場合、クラスを指定しない-user設定は、DefaultContextクラスだけでなく、-user設定を指定しないすべてのクラスにも適用されます。通常は、異なる接続コンテキスト・クラスは、異なるSQLオブジェクト・セットに対して使用することを目的としているため、-user設定は接続コンテキスト・クラスごとに指定することになります。

接続コンテキスト・クラスCtxClass1、CtxClass2およびCtxClass3を宣言し、-userを次のように設定した場合を想定します。

-user@CtxClass2=scott/password -user=bill/lion

CtxClass2のインスタンスを使用しているアプリケーション内の文が、scottスキーマと照合されます。DefaultContext、CtxClass1またはCtxClass3のインスタンスを使用している文が、billスキーマと照合されます。

また、-userオプションでオンライン・チェックを有効にした後で、特定の接続コンテキストのオンライン・チェックを無効化するには、その接続コンテキストに対して空のユーザー名で-userオプションを設定します。たとえば、次のような設定があるとします。

-user@CtxClass2=

CtxClass2のインスタンスである接続オプションを指定したSQLJ実行文に対するオンライン・セマンティクス・チェックが無効になります。

デフォルトの接続コンテキスト・クラスおよびユーザー名を指定しなかった接続コンテキスト・クラスのオンライン・セマンティクス・チェックを無効化するには、次のように指定します。

-user=

このオプションの一般的なコマンドライン構文は、次のとおりです。

-user<@conn_context_class>=username</password><@url>

次に例を示します。

-user=scott
-user=scott/password
-user=scott@jdbc:oracle:oci:@
-user=scott/password@jdbc:oracle:oci:@
-user=
-user=URL.CONNECT
-user@CtxClass=scott/password
-user@CtxClass=

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.user<@conn _context_class>=username</password><@url>

次に例を示します。

sqlj.user=scott
sqlj.user=scott/password
sqlj.user=scott@jdbc:oracle:oci:@
sqlj.user=scott/password@jdbc:oracle:oci:@
sqlj.user=
sqlj.user=URL.CONNECT
sqlj.user@CtxClass=scott/password
sqlj.user@CtxClass=

このオプションにはデフォルト値はありません。デフォルトでは、オンライン・セマンティクス・チェックはありません。

注意:
userオプションと-urlオプションとでは、ユーザー、パスワードおよびURLを指定する書式が異なることに注意してください。-urlオプションでは、ユーザー名とパスワードをURLの一部としてJDBCドライバ・タイプの直後に指定します。-userオプションでは、ユーザー名とパスワードを指定し、その後ろにURLを指定します。

オンライン・セマンティクス・チェック時のユーザー・パスワード(-password)

-passwordオプションでは、オンライン・セマンティクス・チェック用のデータベース接続で使用するユーザー・パスワードを指定します。-password値を有効にするには、-userオプションも設定する必要があります。

-userオプションの設定の一部として、パスワードも指定できます。パスワードを-userオプションで指定済の場合は、接続コンテキスト・クラスに対して-passwordオプションを使用しないでください(-userオプションの方が優先されます)。

-passwordオプションの大半の機能は、-userオプションの機能に相当します。つまり、アプリケーションでDefaultContextのデフォルト接続などのインスタンスのみを使用する場合は、すべてのSQLJ文のチェックに使用するスキーマのパスワードを次のように指定します。

-password=password

CtxClass1などの接続コンテキスト・クラスをさらに宣言して使用する場合は、これらの接続コンテキスト・クラスを使用する文をテストするために追加するスキーマを-userオプションで指定できます。同様に、これらのスキーマのパスワードを次のように-passwordオプションで指定できます。

-password@CtxClass1=password

接続コンテキスト・クラスのパスワードを-passwordまたは-userで設定しない場合は、デフォルトの接続コンテキスト・クラスのパスワード設定が使用されます。デフォルトの接続コンテキスト・クラスにパスワードを指定しない場合は、SQLJからパスワードの入力を求められます。また、ユーザー定義の接続コンテキスト・クラスにパスワードを設定していない場合も、同様にSQLJからパスワードの入力を求められます。ただし、ユーザー名にURL.CONNECTを使用した場合は例外です。この場合、ユーザー名とパスワードは-urlで指定した文字列から特定されます。-passwordオプションの設定は無視されます。

-passwordオプションの設定値を無効にし、対話型プロンプトで入力を要求するには、プロパティ・ファイルなどで空のパスワードを設定します。次のように、DefaultContextクラスまたは特定の接続コンテキスト・クラスに対して設定できます。

-password=

-password@CtxClass1=

実際に空のパスワードでログインするには、次のようにEMPTY.PASSWORDを指定します。

-password=EMPTY.PASSWORD

-password@CtxClass2=EMPTY.PASSWORD

ただし、Oracle Database 11g では空のパスワードを使用できません。

注意:

- コマンドラインで指定した-pは、-passwordと同じものとして認識されます。

- コマンドラインでパスワードを設定するときは、次のように=のかわりにスペースを使用できます。

-password password
-password@CtxClass password
-p password
-p@CtxClass password

- ISOコード生成では、トランスレータの-password設定がプロファイル・カスタマイザに転送されますが、カスタマイザのpassword設定によって無視されることもあります。

このオプションのコマンドライン構文は、次のとおりです。

-password<@conn_context_class>=user_password

次に例を示します。

-password=password
-password=
-password=EMPTY.PASSWORD
-password@CtxClass=password

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.password<@conn_context_class>=user_password

次に例を示します。

sqlj.password=tiger
sqlj.password=
sqlj.password=EMPTY.PASSWORD
sqlj.password@CtxClass=tiger

このオプションにはデフォルト値はありません。DefaultContextのパスワードが使用されるか、ユーザーの入力を要求するプロンプトが表示されます。

オンライン・セマンティクス・チェックに使用する接続URL(-url)

-urlオプションでは、オンライン・セマンティクス・チェックのためのデータベース接続の確立に使用するURLを指定します。必要に応じて、ホスト名、ポート番号およびデータベースのサービス名(またはSID)をURLに指定できます(SIDは、Oracle Database 11g では非推奨です)。

-userオプションの設定の一部として、URLを指定することも可能です。URLを-userオプションで指定済の場合は、接続コンテキスト・クラスに対して-urlオプションを使用しないでください(-userオプションの方が優先されます)。

-urlオプションの大半の機能は、-userオプションの機能に相当します。つまり、アプリケーションでDefaultContextのデフォルト接続などのインスタンスのみを使用する場合は、すべてのSQLJ文のチェックのための接続に使用するURLを、次のように指定します。

-url=jdbc:oracle:oci:@

または、URLにホスト名、ポート番号およびサービス名を含める場合は、次のように指定します。

-url=jdbc:oracle:thin:@myhost:1521/myservice

URL設定の最初にjdbc:が付かない場合、設定形式はhost :port /servicename であると見なされます。この場合、デフォルトでは、設定の最初に次の接頭辞が自動的に付けられます。

jdbc:oracle:thin:@

-url設定をlocalhost:1521/myserviceにすると、URLが自動的に次のようになります。

jdbc:oracle:thin:@localhost:1521/myservice

このデフォルトの動作を削除または変更するには、-default-url-prefixオプションを使用します。

関連項目:
「デフォルトのURL接頭辞(-default-url-prefix)」

ユーザーおよびパスワードは、-userおよび-password設定ではなく、-url設定でも指定できます。この場合は、次に示すように、-userをURL.CONNECTに設定します。

-url=jdbc:oracle:oci:scott/tiger@ -user=URL.CONNECT

たとえばCtxClass1など、追加の接続コンテキスト・クラスを宣言して使用する場合は、その接続コンテキスト・クラスを使用する文のテストのための、基本スキーマを追加指定します。次に示す例のように、これらのスキーマのURLは-urlオプションで指定できます。

-url@CtxClass1=jdbc:oracle:oci:@

-url設定と-user設定のいずれでもURLが設定されていない接続コンテキスト・クラスの場合は、デフォルトの接続コンテキスト・クラスに設定されているURLが使用されます。ただし、デフォルトのコンテキスト・クラスにURLが設定されていることを前提とします。

注意:

- URLが設定されている接続コンテキスト・クラスには、ユーザー名も設定されていることが必要です。設定されていないと、オンライン・チェックが行われません。

- コマンドラインでURLを設定するときは、次のように=のかわりにスペースを使用できます。

-url jdbc:oracle:oci:@
-url@CtxClass jdbc:oracle:oci:@

- ISOコード生成では、トランスレータの-url設定がプロファイル・カスタマイザに転送されますが、カスタマイザのurl設定によって無視されることもあります。

このオプションのコマンドライン構文は、次のとおりです。

-url<@conn_context_class>=URL

次に例を示します。

-url=jdbc:oracle:oci:@
-url=jdbc:oracle:thin:@hostname:1521/myservice
-url=jdbc:oracle:oci:scott/password@
-url=hostname:1521/myservice
-url@CtxClass=jdbc:oracle:oci:@

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.url<@conn_context_class>=URL

次に例を示します。

sqlj.url=jdbc:oracle:oci:@
sqlj.url=jdbc:oracle:thin:@hostname:1521/myservice
sqlj.url=jdbc:oracle:oci:scott/tiger@
sqlj.url=hostname:1521/myservice
sqlj.url@CtxClass=jdbc:oracle:oci:@

次に、このオプションのデフォルト値を示します。

jdbc:oracle:oci:@

注意:
-userオプションと-urlオプションとでは、ユーザー、パスワードおよびURLを指定する書式が異なることに注意してください。-urlオプションでは、ユーザー名とパスワードをURLの一部としてJDBCドライバ・タイプの直後に指定します。-userオプションでは、ユーザー名とパスワードを指定し、その後ろにURLを指定します。

デフォルトのURL接頭辞(-default-url-prefix)

デフォルトの接頭辞を変更または削除するには、-default-url-prefixオプションを使用します。URL設定の最初にjdbc:が付いていない場合、デフォルトでは、次の接頭辞が自動的に付けられます。

jdbc:oracle:thin:@

このため、-userと-urlのどちらのオプションでURLを設定する場合でも、省略表現を使用できます。データベースのホスト、ポートおよびサービス名のみ指定できます(SIDも指定できますが、非推奨です)。たとえば、次のようにURLを設定するとします。

-url=myhost:1521/myservice

-user=scott/tiger@myhost:1521/myservice

デフォルトでは、URLが次のように解釈されます。

jdbc:oracle:thin:@myhost:1521/myservice

URLの指定がjdbc:で開始される場合、デフォルトの接頭辞は使用されません。

ただし、たとえば、デフォルトのURL設定でJDBC ThinドライバのかわりにJDBC Oracle Call Interface(OCI)ドライバを使用するには、デフォルトの接頭辞を次のように設定します。

-default-url-prefix=jdbc:oracle:oci:@

接頭辞を付けないようにするには、次に示すように、-default-url-prefixオプションを空の文字列に設定します。

-default-url-prefix=

このオプションのコマンドライン構文は、次のとおりです。

-default-url-prefix=url_prefix

次にその例を示します。

-default-url-prefix=jdbc:oracle:oci:@
-default-url-prefix=

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.default-url-prefix=url_prefix

次に例を示します。

sqlj.default-url-prefix=jdbc:oracle:oci:@
sqlj.default-url-prefix=

次に、このオプションのデフォルト値を示します。

jdbc:oracle:thin:@

オンライン・セマンティクス・チェックのために登録するJDBCドライバ(-driver)

-driverオプションでは、オンライン・セマンティクス・チェックに使用するJDBC接続URLの解釈のために登録する、JDBCドライバ・クラスを指定します。このオプションを使用して、ドライバ・クラスまたはカンマで区切られたクラスのリストを指定します。デフォルトのOracleDriverでは、Oracle Database 11g でのOracle JDBC OCI、JDBC Thinおよびサーバー側JDBCドライバの使用がサポートされています。

このオプションのコマンドライン構文は、次のとおりです。

-driver=driver1<,driver2,driver3,...>

次に例を示します。

-driver=oracle.jdbc.OracleDriver
-driver=oracle.jdbc.OracleDriver,sun.jdbc.odbc.JdbcOdbcDriver

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.driver=driver1<,driver2,driver3,...>

次に例を示します。

sqlj.driver=oracle.jdbc.OracleDriver
sqlj.driver=oracle.jdbc.OracleDriver,sun.jdbc.odbc.JdbcOdbcDriver

次に、このオプションのデフォルト値を示します。

oracle.jdbc.OracleDriver

ドライバ名(sqlj.driver_name)

プロパティ・ファイルのsqlj.driver_nameオプションを使用して、ドライバ名を設定します。エンドツーエンドの診断にdriver_name属性を設定できます。この属性の値は検証されません。この値は直接サーバーに渡され、V$SESSION_CONNECT_INFOビューおよびGV$SESSION_CONNECT_INFOビューのCLIENT_DRIVER列の値として表示されます。この値の最大長は8文字です。

プロパティ・ファイルでこのプロパティを設定しない場合、このプロパティのデフォルトの値はSQLJです。次の方法でこのプロパティを設定できます。

sqlj.driver_name=MYDRIVER

注意:
この属性はプロパティ・ファイルからのみ設定でき、同等のコマンドライン・オプションはありません。

レポートと行マッピングのオプション

次に示す各オプションでは、SQLJがモニターする条件、リアルタイム・エラーとステータス・メッセージを生成するかどうか、およびトランスレータのエラー・メッセージに原因と処置の情報を含めるかどうかを指定します。

- -warn

- -status

- -explain

次のオプションを使用すると、生成済のJava.classファイルから元の.sqljソース・ファイルへの行マッピングができます。この行マッピングを行うと、ランタイム・エラーについて、元のソース・コードの該当箇所を確認できます。

- -linemap

- -jdblinemap

-jdblinemapをSun社のjdbデバッガで使用します。それ以外の場合は、-linemapを使用します。

トランスレータからの警告(-warn)

SQLJトランスレータでは、変換時の状況に応じて、様々な警告や情報メッセージを表示できます。-warnオプションは、どの警告およびメッセージを表示するか、つまりどの状況を監視して、どの状況を無視するかを指定する、一連のフラグで構成されます。このオプションに指定するフラグをすべて組み合せて、カンマ区切りの単一の文字列にする必要があります。

表8-3に、テストする状況、各状況に対するフラグ値trueおよびfalseの意味、フラグ値trueの意味、およびデフォルトの値を示します。

表8-3 SQLJの警告のテストとフラグ

テストおよびフラグ機能

TRUE/FALSE値

継承階層で宣言されたオブジェクト型のサブタイプの要件のテスト: castを有効にすると、SQL継承階層のSQLオブジェクト型を使用するには、宣言された型のサブタイプを実行時に渡す必要がある場合に、警告を受け取ります。

cast(デフォルト)

nocast

データ精度のテスト: precisionを有効にした場合、データベースの列からJavaホスト変数に値を移動した際にデータの精度が失われる可能性があると、警告を受け取ります。

precision(デフォルト)

noprecision

NULL化可能なデータの変換ロスのテスト: -nullsを有効にした場合、データベースの列からJavaホスト変数にNULL化可能の列またはNULL化可能のJava型を移動した際に、変換でデータの損失が発生する可能性があると、警告を受け取ります。

nulls(デフォルト)

nonulls

移植可能性のテスト: -portableを有効にすると、SQLJ句の移植可能性がチェックされ、移植できない句があると警告を受け取ります。(ベンダー固有の型や機能など、SQLJの拡張機能が使用されていると、移植ができません。)

portable

noportable(デフォルト)

名前付きイテレータの厳密マッチングのテスト: -strictを有効にすると、データベースから選択した列の数とデータが取り込まれている名前付きイテレータ内の列の数が一致することが、SQLJでの必須条件になります。データベース・カーソル内の列に対応する列がイテレータにないと、警告が生成されます。nostrictを設定した場合、データベース・カーソル内の列数を、イテレータ内の列数より多くすることが可能になります(ただし、イテレータ内の列数未満にはできません)。一致しない列は無視されます。

strict(デフォルト)

nostrict

変換時の情報メッセージ: -verboseを有効にすると、オンライン・チェック用に確立されたデータベース接続など、変換処理についての追加の情報メッセージが生成されます。

verbose

noverbose(デフォルト)

警告のグローバルでの有効化または無効化: allまたはnoneを指定して、すべての警告を有効または無効にします。

all

none

verbose/noverboseフラグは、他のフラグとは異なった働きをします。このフラグによって、特定のテストが有効になることはありませんが、セマンティクス・チェックについての概要メッセージの出力が有効になります。

注意:
-warn=verboseフラグと-statusフラグを混同しないでください。-statusフラグを有効にすると、変換、セマンティクス・チェック、コンパイルおよびプロファイルのカスタマイズ(使用している場合)など、SQLJ変換にかかわるすべての処理についての情報メッセージが、リアルタイムで提供されます。これに対して-warn=verboseフラグでは、変換フェーズについてのみ、追加情報が提供されます。

グローバルなall/noneフラグは、デフォルトの設定よりも優先されます。このフラグを使用するのは、すべてのフラグを有効化または無効化する場合、選択したフラグを有効化する前にすべてのフラグが無効であることを保証するために初期化する場合、または選択したフラグを無効にする前にすべてのフラグを有効化する場合です。

allを設定すると、次のように指定した場合と同じ結果になります。

cast,precision,nulls,portable,strict,verbose

noneを設定すると、次のように指定した場合と同じ結果になります。

nocast,noprecision,nonulls,noportable,nostrict,noverbose

all/noneのデフォルトはありません。個々のフラグのデフォルトのみがあります。

たとえば、次のように指定します。

- 次のシーケンスでは、nullsフラグのみが有効になります。

-warn=none,nulls

- 次のシーケンスはverbose設定が無効にされるため、同じ結果になります。

-warn=verbose,none,nulls

- 次のシーケンスでは、移植可能性フラグ以外のすべてが有効になります。

-warn=all,noportable

- 次のシーケンスはnonulls設定が無効にされるため、同じ結果になります。

-warn=nonulls,all,noportable

all/noneフラグの配置以外は、-warn設定でのフラグの指定順序は重要ではありませんが、競合する設定の場合は別です。-warn=portable,noportableなど、競合が発生する場合は、最後(右端)の設定が使用されます。

プロパティ・ファイルとコマンドラインで別々に-warnオプションを設定しても、両方の設定が受け付けられることはありません。最後の設定のみが処理されます。次の例では、-warn=portable設定は無視されます。このフラグ、およびnulls/nonulls以外のすべてのフラグは、それぞれのデフォルト設定に従って処理されます。

-warn=portable -warn=nonulls

注意:
キャスト、精度、NULL化可能性および厳密性の各テストは、オンライン・セマンティクス・チェックの一部であり、データベース接続が必要です。

このオプションのコマンドライン構文は、次のとおりです。

-warn=comma-delimited_list_of_flags

次に例を示します。

-warn=none,nulls,precision

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.warn=comma-delimited_list_of_flags

次に例を示します。

sqlj.warn=none,nulls,precision

次に、このオプションのデフォルト値を示します。

cast,precision,nulls,noportable,strict,noverbose

リアルタイムのステータス・メッセージ(-status)

-statusフラグを有効にすると、変換、セマンティクス・チェック、コンパイルおよびカスタマイズなど、すべてのSQLJ処理について追加のステータス・メッセージが表示されます。SQLJ操作の各ステージで各ファイルが処理されると、メッセージが表示されます。

注意:

- -warn=verboseフラグと-statusフラグを混同しないでください。-statusフラグでは、SQLJ変換にかかわるすべての処理についての情報メッセージが、リアルタイムで提供されます。これに対して-warn=verboseフラグでは、変換フェーズについてのみ、追加情報が提供されます。

- loadjavaユーティリティとの互換性については、-vがコマンドラインで指定されると、-statusに相当すると認識されます。

このオプションのコマンドライン構文は、次のとおりです。

-status<=true|false>

次に例を示します。

-status

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.status<=true|false>

次に例を示します。

sqlj.status

次に、このオプションのデフォルト値を示します。

false

トランスレータ・エラーの原因と処置(-explain)

-explainフラグを有効にすると、SQLJトランスレータでエラーが最初に発生したときのみ、出力されるエラー・メッセージに原因および処置の情報がある場合は出力されます。

このオプションのコマンドライン構文は、次のとおりです。

-explain<=true|false>

次に例を示します。

-explain

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.explain<=true|false>

次に例を示します。

sqlj.explain

次に、このオプションのデフォルト値を示します。

false

SQLJソース・ファイルとの行マッピング(-linemap)

-linemapフラグを有効にすると、SQLJソース・コード・ファイルの行番号が、対応する.classファイルの場所にマッピングされます。このファイルは、SQLJトランスレータで生成された.javaファイルのコンパイルで生成される.classファイルになります。このマッピングにより、Javaランタイム・エラーが発生した場合に、SQLJソース・コードの行番号と同じ行番号がJVMによって報告され、デバッグがはるかに容易になります。

通常、.classファイル内の命令は、対応する.javaファイル内のソース・コードの行にマッピングされます。ただし、生成された.javaファイル内の行番号を元の.sqljファイル内の行番号にマッピングする必要があるため、SQLJ開発者にはあまり役に立ちません。

SQLJトランスレータは、-linemapオプションを実装するように、.classファイルを修正します。この修正では、生成された.javaファイルの行番号とファイル名が、元の.sqljファイルの対応する行番号とファイル名で置き換えられます。この処理を、クラス・ファイルのインストルメントと呼びます。

SQLJでこの処理を行う際には、次の設定が考慮されます。

- .classファイルのルート・ディレクトリを決定する-dオプション設定

- 生成された.javaファイルのルート・ディレクトリを決定する-dirオプション設定

注意:

- .sqljファイルの処理でエラーのためにコンパイルが行われなかった場合は、マッピング用の.classファイルが生成されないため、行マッピングも行われません。

- SQLJからJavaコンパイラが起動された場合、コンパイル・エラーの報告には、常に、元の.sqljソース・ファイルの行番号が使用され、生成された.javaファイルは使用されません。このマッピングには、オプションの設定は必要ありません。

- .sqljファイル内の無名クラスは、インストルメントされません。

- Sun社jdbデバッガを使用する際は、-linemapオプションのかわりに、-jdblinemapオプションを使用します。

このオプションのコマンドライン構文は、次のとおりです。

-linemap<=true|false>

次に例を示します。

-linemap

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.linemap<=true|false>

次に例を示します。

sqlj.linemap

次に、このオプションのデフォルト値を示します。

false

jdbデバッガでのSQLJソース・ファイルへの行マッピング(-jdblinemap)

このオプションは-linemapオプションと同等であり、Sun Microsystemsのjdbデバッガを使用する場合は、-linemapオプションではなく、このオプションを使用する必要があります。この理由は、jdbからアクセスできるソース・ファイルが.javaファイルという拡張子付きのものに限られているためです。

-jdblinemapを設定すると、SQLJでは次の処理が行われます。

- トランスレータで生成された.javaファイルの内容を、元の.sqljファイルの内容で上書きします。

- 生成された.classファイルの中にあるファイル名のうち、.sqljファイル名でなく.javaファイル名を保持します。

このためSQLJソース・コードからjdbへのアクセスが可能になっています。

このオプションのコマンドライン構文は、次のとおりです。

-jdblinemap<=true|false>

次に例を示します。

-jdblinemap

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.jdblinemap<=true|false>

次に例を示します。

sqlj.jdblinemap

次に、このオプションのデフォルト値を示します。

false

DMSのオプション

Oracle SQLJ実装では、DMSをサポートするためのトランスレータ・フロントエンド・オプションが提供されます。

- -instrument: インストルメントを有効にし、アプリケーション(変換するコンポーネントの集合)の名前を指定します。

- -components: インストルメントするコンポーネント(パッケージおよびクラス)を指定します。

関連項目:
「Oracleパフォーマンス・モニタリングのSQLJサポート」

DMSのためのインストルメント(-instrument)

SQLJの-instrumentオプションは、インストルメントを有効にし、アプリケーション名を指定するためのオプションです。ここでアプリケーションという用語は、SQLJコマンドラインで変換のために指定されたすべてのSQLJコンポーネントとJavaコンポーネントを指します。

使用可能な-instrumentオプションの設定を次に示します。

- application_name: インストルメントを有効にして指定したアプリケーション名を使用するには、必要に応じて、接頭辞としてパッケージ名をJavaの標準ドット区切り構文で指定します。パッケージ名とアプリケーション名の間にスラッシュ(/)を挿入します。スペースは挿入しません。

- true: インストルメントを有効にしてデフォルトのアプリケーション名defaultAppを使用します。

- false(デフォルト): インストルメントを無効にします。

インストルメントが有効になっている場合、SQLJ DMSプロパティ・ファイルが作成されます。このファイルの名前および場所は、-instrumentの設定(カレント・ディレクトを基準とする)、パッケージ名、およびSQLJの-dオプションの設定に従って指定されます。アプリケーション名を指定しない場合、trueが設定されている場合と同様に、プロパティ・ファイルはsqlmonitor.propertiesという名前でカレント・ディレクトリに格納されます。

簡単な例として、-instrument=myappを設定すると、プロパティ・ファイルmyapp.propertiesがカレント・ディレクトリに作成されます。

ここで、アプリケーション名がstock、パッケージがcom.acmeの次の例を考えます。

% sqlj -instrument=com.acme/stock Stock.sqlj Trading.sqlj

この場合、プロパティ・ファイル./com/acme/stock.propertiesが作成されます。

ここでは、次の例について考えてみます。

% sqlj -instrument=com.acme/stock -d /home Stock.sqlj Trading.sqlj

この場合、-dオプションが指定されているため、ファイル/home/com/acme/stock.propertiesが作成されます。

次のようにsqlj.propertiesに-instrumentオプションを設定することもできます。

sqlj.instrument=com.acme/stock

注意:
-instrumentの設定は、-instrument=trueを設定することと同じです。

このオプションのコマンドライン構文は、次のとおりです。

-instrument<=true|false|application_name>

次に例を示します。

-instrument=com.acme/stock

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.instrument<=true|false|application_name>

次に例を示します。

sqlj.instrument=com.acme/stock

次に、このオプションのデフォルト値を示します。

false

DMSのためにインストルメントするコンポーネント(-components)

-instrumentオプションでインストルメントが有効になっている場合、-componentsオプションを使用して、DMS監視のためにインストルメントするコンポーネントを指定します。これは、変換されるコンポーネントのサブセットであり、通常、これらのほぼすべてのコンポーネントで、実行時の柔軟な監視が可能になります。実行時に、インストルメントされたコンポーネントが、SQLJ DMSプロパティ・ファイル内の指定に従って監視されます。

関連項目:
「DMS用のSQLJランタイム・コマンドおよびプロパティ・ファイル設定」

変換時にインストルメントされていないコンポーネントは、プロパティ・ファイル内の指定にかかわらず、いずれも実行時に監視できないことに注意してください。

-componentsオプションには、次のいずれかを設定できます。

- list_of_components : インストルメントするパッケージまたはクラスのカンマ区切りリスト

- all(デフォルト): 変換されるすべてのコンポーネントをインストルメントする場合

コンポーネントのリストでは、Javaの標準ドット区切り構文を使用してクラスの完全修飾名を指定できます。または、パッケージ内のすべてのクラスをインストルメントするにはパッケージ名を指定します。

たとえば、StockおよびTradingクラスをインストルメントするには、次の構文を使用します。

% sqlj ... -components=com.acme.Stock,com.acme.Trading

または、sqlj.propertiesファイルに次の指定を行うことも結果は同じです。

sqlj.components=com.acme.Stock,com.acme.Trading

このオプションのコマンドライン構文は、次のとおりです。

-components=all|list_of_components

次に例を示します。

-components=com.acme.Stock,com.acme.Trading

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.components=all|list_of_components

次に例を示します。

sqlj.components=com.acme.Stock,com.acme.Trading

次に、このオプションのデフォルト値を示します。

all

コード生成、最適化およびCHAR比較のオプション

デフォルトでは、Oracle SQLJ実装は、ISO標準コード生成のかわりにOracle固有コード生成を使用します(Oracle JDBCコードが直接生成されます)。Oracle固有コード生成の場合、プロファイルは生成されず、SQLJランタイムはコード実行時にほとんど省略されます。

プロファイルのカスタマイズはOracle固有コード生成には利用できないので、以前にOracleカスタマイザでのみ利用可能であった一般的に便利ないくつかの最適化オプションが、現在はSQLJトランスレータで直接利用できます。

WHERE句のCHAR比較で、列の空白埋めを考慮するオプションもあります。このオプションは、トランスレータ・オプション(Oracle固有コード生成の場合)としても、Oracleカスタマイザ・オプション(ISO標準コード生成の場合)としても使用できます。

ここでは、次のコード生成、最適化およびCHAR比較およびバインドのオプションについて説明します。

- -codegen

- -optcols

- -optparams

- -optparamdefaults

- -fixedchar

- -ncharconv

コードの生成(-codegen)

Oracle SQLJ実装では、Oracle固有のJDBCコードを直接生成することも、SQLJランタイムをコールし、そこからJDBCをコールするISO標準コードを生成することもできます。Oracle固有コード生成の場合、プロファイル・ファイルはなく、SQLJランタイムはプログラム実行時にほとんど省略されます。

ISO規格に従ってコードを生成する場合は、次のようにSQLJトランスレータの-codegenオプションを使用します。

-codegen=iso

デフォルトはOracle固有のSQLJコード生成です。次のようにOracle固有コード生成を明示的に指定することもできます。

-codegen=oracle

注意:
codegen=isoの場合、-user、-password、-url、-optparams、-optparamdefaultsおよび-fixedcharのトランスレータ設定は、プロファイル・カスタマイザにも転送されます。ただし、カスタマイザ・オプションを直接設定することによって、これらのカスタマイズ設定(特に-user、-passwordおよび-url)を無視できます。

このオプションのコマンドライン構文は、次のとおりです。

-codegen=iso|oracle

次に例を示します。

-codegen=iso

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.codegen=iso|oracle

次に例を示します。

sqlj.codegen=iso

次に、このオプションのデフォルト値を示します。

oracle

列の定義(-optcols)

SQLJトランスレータの-optcolsフラグを使用して、イテレータまたは結果セット列の型およびサイズを決定するようにトランスレータに指示します。このようにすると、アプリケーション実行時に列をOracle JDBCドライバに登録可能になり、ドライバの実装にもよりますが、データベースへのラウンドトリップが減ります。特に、この方法は、JDBC Thinドライバと位置イテレータには効果的です。

関連項目:
「列の定義」

注意:
このトランスレータ・オプションは、Oracleカスタマイザのoptcolsオプションと同じで、プロファイルがないデフォルトのOracle固有コード生成のために作成されたものです。しかし、ISO標準コード生成にも適用されます。この場合、トランスレータ・オプションを設定すると、同様にカスタマイザ・オプションも自動的に設定されます。

このフラグの有効化/無効化は、SQLJコマンドラインまたはプロパティ・ファイルで設定します。

このフラグをコマンドラインで有効にするには、次のようにします。

-optcols

または

-optcols=true

このフラグは、デフォルトでは無効になっていますが、明示的に無効化することも可能です。このフラグをコマンドラインで無効化するには、次のようにします。

-optcols=false

列定義には、問合せ対象の列を検証するためにデータベース接続が必要です。そのため、SQLJトランスレータの-user、-passwordおよび-urlオプションも適切に設定する必要があります。次に例を示します。

% sqlj -user=scott@jdbc:oracle:oci:@ -optcols MyApp.sqlj
Password: password

注意:

- 選択したすべての列に定義が作成されるため、必ずしも選択した列をすべて使用するわけではない場合は、SQL操作ではSELECT *構文を使用せずに、使用する列を明示的に選択することをお薦めします。必要以上に列を選択すると、実行時エラーの可能性も高くなります。このことは、カスタマイズと実行時の間にその表を変更した場合、特に列定義をカスタマイズした場合に当てはまります。変換時にはSQLJ -warn=strictフラグを設定することをお薦めします。問合せで追加の(不要な)列が選択された場合に、警告が生成されます。

- オブジェクトまたはコレクションが1つ以上含まれるイテレータや結果セットに対しては、列定義はできません。

- データベース接続用ユーザー名、パスワードおよびURLを指定せずに、-optcolsオプションを有効にすると、エラーが発生します。

- 実行時にはデータベースの接続先と同じスキーマまたはデータベースに、トランスレータから接続する必要はありません。ただし、実行時のエラーを回避するために、関連のある列と、型およびサイズが同じ列は同じ順序で並べる必要があります。

このオプションのコマンドライン構文は、次のとおりです。

-optcols<=true|false>

次に例を示します。

-optcols

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.optcols<=true|false>

次に例を示します。

sqlj.optcols

次に、このオプションのデフォルト値を示します。

false

パラメータの定義(-optparams)

パラメータ・サイズの定義を有効化するには、SQLJトランスレータの-optparamsフラグを使用します。SQLJではこのフラグを有効にすると、入力および出力パラメータが登録されて、JDBCリソース割当て量が指定したサイズに基づいて最適化されます。このサイズの優先順位は次のとおりです。

1. ソース・コードのヒント中に指定したサイズ(ある場合)

2. -optparamdefaultsオプション設定のデータ型に対して指定したデフォルトのサイズ

指定されたホスト変数用のソース・コードのヒントまたはデフォルトのデータ型サイズが設定されていない場合、リソース割当て量はJDBC次第になります。

関連項目:
「列の定義」

注意:
このトランスレータ・オプションは、Oracleカスタマイザのoptparamsオプションと同じです。このトランスレータ・オプションは、プロファイルがないデフォルトのOracle固有コード生成のために作成されたものです。しかし、ISO標準コード生成にも適用されます。この場合、トランスレータ・オプションを設定すると、同様にカスタマイザ・オプションも自動的に設定されます。

-optparamsフラグの有効化/無効化は、コマンドラインまたはSQLJプロパティ・ファイルで設定します。

このフラグをコマンドラインで有効にするには、次のようにします。

-optparams

または

-optparams=true

このフラグは、デフォルトでは無効になっていますが、明示的に無効化することも可能です。このフラグをコマンドラインで無効化するには、次のようにします。

-optparams=false

注意:
-optcolsオプションとは異なり、-optparamsオプションではサイズを自分で指定できるので、データベース接続は不要です。

コマンドライン(-optparamdefaultsオプションの設定はここでは省略します)の例を次に示します。

% sqlj -optparams -optparamdefaults=defaults_string MyApp.sqlj

このオプションのコマンドライン構文は、次のとおりです。

-optparams<=true|false>

次に例を示します。

-optparams

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.optparams<=true|false>

次に例を示します。

sqlj.optparams

次に、このオプションのデフォルト値を示します。

false

パラメータのデフォルト・サイズ(-optparamdefaults)

-optparamsオプションを有効にしてパラメータ・サイズを設定した場合は、必要に応じて-optparamdefaultsオプションを使用してデータ型のデフォルト・サイズを設定します。-optparamsを有効にしない場合、-optparamdefaultsが設定されていても無視されます。

ホスト変数に、そのサイズを指定するためのソース・コード・ヒントがある場合、このオプションで設定された対応するデータ型のデフォルト・サイズよりもヒントの方が優先されます。特定のホスト変数に対してソース・コード・ヒントも、対応するデータ型のデフォルト・サイズも指定されていない場合、その変数のリソース割当て量は、-optparamsが有効でない場合と同様に、JDBCドライバによって決定されます。

-optparamsが有効化してあるときは常に-optparamdefaultsオプションを使用するのが一般的ですが、必須ではありません。-optparamsが有効化されていても、デフォルト・サイズが設定されていない場合は、ソース・コード・ヒント(ある場合)またはJDBCドライバに基づいてリソースが割り当てられます。

関連項目:
「パラメータ・サイズの定義」

注意:
このトランスレータ・オプションは、Oracleカスタマイザのoptparamdefaultsオプションと同じです。このトランスレータ・オプションは、プロファイルがないデフォルトのOracle固有コード生成のために作成されたものです。しかし、ISO標準コード生成にも適用されます。この場合、トランスレータ・オプションを設定すると、同様にカスタマイザ・オプションも自動的に設定されます。

-optparamdefaultsフラグは、コマンドラインでもSQLJプロパティ・ファイルでも設定できます。

このフラグをコマンドラインで設定するには、次のようにします。

-optparamdefaults=datatype1(size1),datatype2(size2),...

サイズはすべてバイト単位になっています。空白文字は、含まれないようにしてください。NULLを設定するには、空のカッコを使用します。

たとえば、次のように指定すると、VARCHAR2型で30バイト、RAW型で1000バイトが設定され、またCHAR型でのNULLのサイズ設定が指定されます。CHARデータ型のどのホスト変数に対してもソース・コード・ヒントがない場合は、JDBCドライバによってリソースが割り当てられます。

-optparamdefaults=VARCHAR2(30),RAW(1000),CHAR()

-optparamdefaultsオプションでは、次のデータ型の名前が認識されます。

- CHAR

- VARCHAR、VARCHAR2(同義)

- LONG、LONGVARCHAR(同義)

- BINARY、RAW(同義)

- VARBINARY

- LONGVARBINARY、LONGRAW(同義)

-optparamdefaultsオプションでは、次のグループ名とワイルドカードも認識されます。

- CHAR_TYPEには、CHAR、VARCHAR/VARCHAR2およびLONG/LONGVARCHARがあります。

- RAW_TYPEには、BINARY/RAW、VARBINARYおよびLONGVARBINARY/LONGRAWがあります。

- パーセント記号(%)自体を指定した場合はデータ型として認識されるものがすべて表され、部分的な名前にパーセント記号を付加した場合はデータ型のサブセットが表されます。たとえば、VAR%を指定すると、「VAR」で始まるすべてのデータ型が表されます。

-optparamdefaultsの設定値は、左から右へと処理されます。グループ名またはワイルドカードを使用すると、特定のデータ型に対するグループ設定を上書きできます。

次の例のようにすると、一般的なデフォルト・サイズとして50バイト分が設定され、その設定値が500バイト分のRAW型の設定値に置き換わり、さらに、そのRAW型のグループ設定値がVARBINARY型のNULL設定に置き換わります(ソース・コード・ヒントのないホスト変数は、JDBCで処理されます)。

-optparamdefaults=%(50),RAW_TYPE(500),VARBINARY()

次にコマンドラインの例を示します。この例では、-optparamsも設定します。

% sqlj -optparams -optparamdefaults=CHAR_TYPE(50),RAW_TYPE(500),CHAR(10) MyApp.sqlj

注意:
実行時に、実際のサイズが登録されているパラメータのサイズを超えた場合は、実行時エラーが発生します。

このオプションのコマンドライン構文は、次のとおりです。

-optparamdefaults=defaults_string

次に例を示します。

-optparamdefaults=VAR%(50),LONG%(500),RAW_TYPE()

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.optparamdefaults=defaults_string

次にその例を示します。

sqlj.optparamdefaults=VAR%(50),LONG%(500),RAW_TYPE()

次に、このオプションのデフォルト値を示します。

null

空白埋めを考慮したCHAR比較(-fixedchar)

WHERE句の比較で文字列をバインドするときにCHAR型のデータベース列の空白埋めを考慮するには、このフラグをtrueに設定します。この比較方法では、たとえば、"mystring"と"mystring "は同等であるとみなされます。

この機能は、JDBCのsetFixedCHAR()メソッド(埋込みを考慮するOracleの拡張機能)を使用します。標準JDBCのsetString()メソッドは、空白埋めを考慮しません。

次に-fixedcharの使用例を示します。

% sqlj -fixedchar MyProgram.sqlj AnotherProg.java ...

注意:

- このトランスレータ・オプションは、Oracleカスタマイザのfixedcharオプションと同じです。このトランスレータ・オプションは、プロファイルがないデフォルトのOracle固有コード生成のために作成されたものです。しかし、ISO標準コード生成にも適用されます。この場合、トランスレータ・オプションを設定すると、同様にカスタマイザ・オプションも自動的に設定されます。

- CHAR列またはVARCHAR2列の場合、Oracle SQL実装ではNULL値と""値(空の文字列)は同じ意味です。ただし、""の文字列は挿入できますが、IS NULL構文を使用せずに""の文字列を正しく比較することはできません。-fixedchar機能を使用することは、この問題の解決にはなりません。

このオプションのコマンドライン構文は、次のとおりです。

-fixedchar<=true|false>

次に例を示します。

-fixedchar

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.fixedchar<=true|false>

次に例を示します。

sqlj.fixedchar

次に、このオプションのデフォルト値を示します。

false

NCHARバインド(-ncharconv)

Stringホスト変数を使用してNCHAR列にバインドする場合には、このオプションを設定します。このオプションでは、CHAR列へのすべてのバインドに対して生成コードにSetFormOfUseメソッドを使用する必要があることを指定します。次のようにこのオプションを指定してSQLJファイルを変換する必要があるとします。

% sqlj -ncharconv MyApp.sqlj AnotherApp.java ...

このオプションは、codegen=oracleおよびcodegen=isoの両方でサポートされます。

注意:

- -ncharconvオプションを指定してSQLJファイルをコンパイルすると、codegen=oracleの生成コードでsetFormOfUseメソッドが使用されます。codegen=isoの場合、このオプション情報は、バインドの実行時にSetFormOfUseを内部的に使用するOracle SQLJランタイムに渡されます。

- このトランスレータ・オプションは、Oracle Database 10g リリース2(10.2)より前のデータベース・リリースでは使用できません。

このオプションのコマンドライン構文は、次のとおりです。

-ncharconv<=true|false>

次に例を示します。

-ncharconv

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.ncharconv<=true|false>

次に例を示します。

sqlj.ncharconv

次に、このオプションのデフォルト値を示します。

false

高度なトランスレータ・オプション

ここでは、SQLJを実行する際に指定できる、高度なフラグとオプションの構文および機能について説明し、JVM、JavaコンパイラまたはSQLJプロファイル・カスタマイザにオプションを渡す際に使用する接頭辞についても説明します。これらのオプションを使用すると、Oracle SQLJ実装の特殊な機能を実行できます。プロパティ・ファイルでも指定できるオプションの構文も示します。

ここでは、次の項目について説明します。

- オプション設定を他の実行可能プログラムに渡す接頭辞

- 特殊処理のフラグ

- セマンティクス・チェックとオフライン解析のオプション

オプション設定を他の実行可能プログラムに渡す接頭辞

Javaインタプリタ、JavaコンパイラおよびSQLJプロファイル・カスタマイザに渡すオプションには、それぞれ次のフラグが付けられます。

- -J(Javaインタプリタに渡すオプションに付きます。)

- -C(Javaコンパイラに渡すオプションに付きます。)

- -P(プロファイル・カスタマイザに渡すオプションに付きます。ISOコード生成の場合にのみ使用します。)

Java Virtual Machine(JVM)に渡すオプション(-J)

SQLJを起動したJVMに渡すオプションをコマンドラインで指定する場合は、-J接頭辞を付けます。この接頭辞は、JVMオプションの直前に指定し、接頭辞とオプションの間に空白は入れません。このJavaオプションは、-J接頭辞が取り除かれた後に、sqljスクリプトによってJVMに渡されます。次に例を示します。

-J-Duser.language=ja

sqljスクリプトにより、-Duser.language=ja引数は-J接頭辞が削除された後でJVMに渡されます。Sun社のJDKでは、

-Duser.language=jaフラグを指定すると、システム・プロパティuser.languageが値ja(日本語)に設定されます。ただし、使用するJava実行可能ファイルに依存するフラグを使用すると、sqljスクリプトで解釈や動作の決定が行われない場合もあります。

プロパティ・ファイルはJVMの起動後に読み取られるため、プロパティ・ファイルからJVMにオプションを渡すことは不可能です。

注意:

- プロパティ・ファイルを使用して、SQLJトランスレータが実行されているJVMにオプションを直接渡すことはできませんが、この目的に環境変数SQLJ_OPTIONSを使用することは可能です。一方、Javaコンパイラが実行されているJVMにオプションを渡す際は、プロパティ・ファイルがあればそれを使用します。

- Javaプロパティ・ファイルには、JVMのfile.encoding設定値を使用できません。プロパティ・ファイルでは、常に8859_1エンコーディングを使用します。これは、特別なSQLJの機能ということではなく、一般的なJavaの機能です。ただし、Unicodeのエスケープ・シーケンスなら、プロパティ・ファイルで使用できます。エスケープ・シーケンスを決める際は、native2asciiユーティリティを使用することをお薦めします。

このオプションのコマンドライン構文は、次のとおりです。

-J-Java_option

次に例を示します。

-J-Duser.language=ja

Javaコンパイラに渡すオプション(-C)

sqljスクリプトから起動されたJavaコンパイラに渡すオプションには、-C接頭辞を付けます。この接頭辞は、Javaコンパイラ・オプションの直前に指定し、接頭辞とオプションの間に空白は入れません。このコンパイラ・オプションは、-C接頭辞が取り除かれた後に、sqljスクリプトによってJavaコンパイラに渡されます。次に例を示します。

-C-nowarn

sqljスクリプトにより、-nowarn引数は-C接頭辞が取り除かれた後でコンパイラに渡されます。

通常、コンパイラ・オプションは変更なしで渡されますが、値を伴うコンパイラ・オプションの設定に等号(=)を使用する場合(-bootclasspath、

-extdirs、-targetなど)は、オプションがコンパイラに渡されるときに等号が削除されます。次に示す例で確認してください。

% sqlj -C-bootclasspath=/usr/local/packages/jdk1.5.1/jre/lib/rt.jar myfile.sqlj

Javaコンパイラがそれ自体のJVMで実行されている場合は、コンパイラ経由でオプションをJVMに渡すことができます。この操作を行うには、JVMオプションに

接頭辞の-C-Jを付けます。接頭辞とオプションの間に空白は入れません。次に例を示します。

-C-J-Duser.language=de

-C接頭辞を使用するときは、次の制約を守ってください。

- Javaコンパイラで処理された.javaファイルのエンコーディングの指定には、-C-encodingを使用しないでください。かわりに、SQLJの-encodingオプションを使用します(このオプションでは、SQLJで処理された.sqljファイルのエンコーディング、およびSQLJで生成された.javaファイルのエンコーディングを指定します)。このオプションはコンパイラにも渡されます。このオプションを使用すると、.sqljファイルと.javaファイルが同じエンコーディングを受け取ります。

- .classファイル用の出力ディレクトリの指定には、-C-dを使用しないでください。かわりに、SQLJの-dオプションを使用します(このオプションでは、生成されたプロファイル・ファイル(.ser)用の出力ディレクトリを指定します)。このオプションはJavaコンパイラにも渡されます。このオプションを使用すると、.classファイルと.serファイルが同じディレクトリに置かれます。

注意:

- コンパイラ・オプションを指定していても、コンパイルを無効化する(-compile=false)と、コンパイラ・オプションは無視されます。

- コンパイラのヘルプ・オプション(-helpがコンパイラでサポートされている場合は-C-help)は、コマンドラインまたはSQLJ_OPTIONS変数でのみ指定可能で、プロパティ・ファイルでは指定できません。SQLJの-helpオプションと同様に、変換は行われません。処理するファイルを指定しても実行されません。SQLJでは、ヘルプと変換の両方でなく、どちらか一方を実行することが前提となっています。

このオプションのコマンドライン構文は、次のとおりです。

-C-Java_compiler_option

次に例を示します。

-C-nowarn

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

compile.Java_compiler_option

次に例を示します。

compile.nowarn

プロファイル・カスタマイザに渡すオプション(-P)

カスタマイズ・フェーズ(ISO標準コード生成の場合のみ)では、sqljスクリプトにより、フロントエンドのカスタマイザ・ハーネスが起動されます。このカスタマイザ・ハーネスはカスタマイズ処理を調整し、特定のカスタマイザを実行します。カスタマイズのオプションには、次のように-P接頭辞を付けます。

- -Pのみを使用すると、どのカスタマイザにも適用される汎用的なオプションが、カスタマイザ・ハーネスに渡されます。

- -P-Cを使用すると、ベンダー固有のオプションが、使用するカスタマイザに渡されます。

-P接頭辞と-P-C接頭辞は、カスタマイザ・オプションの直前に指定し、接頭辞とオプションの間に空白は入れません。カスタマイザ・オプションは、接頭辞が取り除かれた後で、sqljスクリプトによってプロファイル・カスタマイザにそのまま渡されます。

SQLJの-default-customizerオプションで定義されたデフォルトのカスタマイザをオーバーライドする場合にも、-P接頭辞を使用します。

-P-customizer=your_customizer_class

汎用的なカスタマイザ・オプションの例を示します。

-P-backup

-backupフラグは、新しいカスタマイズ結果を生成する前に既存のカスタマイズ結果をバックアップする、汎用的なカスタマイザ・オプションです。

次に示すのは、ベンダー固有のカスタマイザ・オプションの例です(ここでは、Oracle固有のカスタマイザ・オプションを使用しています)。

-P-Csummary

summaryフラグは、実行されたカスタマイズの情報を出力する、Oracleカスタマイザ・オプションです。

注意:

- -P-Cとベンダー固有のカスタマイザ・オプションの間には、ハイフンを挿入しません。その他の接頭辞、および接頭辞の組合せの場合は、接頭辞とオプションの間にハイフンを付けます。

- カスタマイザのヘルプ・オプション(-P-help)は、コマンドラインまたはSQLJ_OPTIONS変数でのみ指定可能で、プロパティ・ファイルでは指定できません。SQLJの-helpオプションと同様に、変換は行われません。処理するファイルを指定しても実行されません。SQLJでは、ヘルプと変換の両方でなく、どちらか一方を実行することが前提となっています。

- ISOコード生成では、カスタマイズ・オプションを指定していても、.sqljファイルのカスタマイズを無効にする(また、コマンドラインに.serファイルがない)と、カスタマイズ・オプションは無視されます。

- デフォルトのOracle固有コード生成では、プロファイルが生成されずカスタマイズが実行されないため、接頭辞-Pを使用できません。

このオプションのコマンドライン構文は、次のとおりです。

-P-<C>profile_customizer_option

次に例を示します。

-P-driver=oracle.jdbc.OracleDriver
-P-Csummary

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

profile.<C>profile_customizer_option

次に例を示します。

profile.driver=oracle.jdbc.OracleDriver
profile.Csummary

特殊処理のフラグ

通常、.sqljファイルはSQLJトランスレータ、Javaコンパイラおよび(ISOコード生成の場合は)SQLJプロファイル・カスタマイザで処理されます。次のフラグはこの処理に制限を加えるもので、指定したプロセスを省略するようにSQLJの起動スクリプトに指示します。

- -compile

- -profile

ISOコード生成の場合、SQLJでは-ser2classフラグを指定すると、シリアライズされたリソース(.ser)ファイルのプロファイルが、カスタマイズ後にclassファイルに変換されます。

-checksourceフラグを指定すると、特定の状況のもとでSQLJの型解決が行われます。ソース・ファイルの他、classファイルやSQLJコマンドラインから指定したファイルが検査の対象となります。

-bind-by-identifierフラグは、指定されたSQLJ文の中で複数回出現する同一のホスト変数を、単一のバインドとして処理することを指定します。

コンパイル・フラグ(-compile)

-compileフラグでは、コンパイラによる.javaファイルの処理が、有効または無効にされます。この設定は、生成された.javaファイルとコマンドラインで指定された.javaファイルの両方に適用されます。たとえば、javac以外のコンパイラを使用して、.javaファイルを後でコンパイルする場合、このフラグを使用すると便利です。このフラグのデフォルト値はtrueです。falseに設定すると、コンパイルが無効になります。

-compile=falseを指定して.sqljファイルを処理する場合は、必要に応じて、後でコンパイルおよびカスタマイズを行います。

-compile=falseを設定すると、-profile=falseも暗黙的に設定されます。つまり、-compileがfalseの場合は、コンパイルとカスタマイズの両方が省略されます。-compile=falseと-profile=trueを設定した場合、-profile設定は無視されます。

注意:
型の解決のために.javaファイルを参照する場合でも、-compileをfalseに設定する方が適切な場合があります。たとえば、.sqljファイルの変換中に行われる型解決に1つ以上の.javaファイルをコマンドラインで指定する場合、特定のコンパイラを使用してすべての.javaファイルを後でコンパイルするには、この設定を行います。
ただし、-checksourceオプションは、SQLJコマンドラインでの解決に.javaファイルを入力する必要性を排除することによって、型解決の処理を単純化できることに注意してください。

このオプションのコマンドライン構文は、次のとおりです。

-compile<=true|false>

次に例を示します。

-compile=false

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.compile<=true|false>

次に例を示します。

sqlj.compile=false

次に、このオプションのデフォルト値を示します。

true

プロファイル・カスタマイズ・フラグ(-profile)

ISOコード生成の場合、-profileフラグは、SQLJプロファイル・カスタマイザによって生成されたプロファイル・ファイル(.ser)の処理を有効または無効にします。この設定は、SQLJトランスレータによって、現行のコマンドラインで指定した.sqljファイルから生成された.serファイルにのみ適用されます。コマンドラインで指定した、前に生成された.serファイル(または.jarファイル)には適用されません。このフラグのデフォルト値はtrueです。falseに設定すると、カスタマイズが無効になります。

このオプションは、コマンドラインで指定したファイルの-compileオプションとは異なった働きをします。コマンドラインで指定された.serファイルと.jarファイルは、-profile=falseを設定してもカスタマイズされます。これに対して、-compile=falseを設定すると、コマンドラインで指定された.javaファイルはコンパイルされません。これは、.javaファイルに対しては、行マッピングなどの他の操作を実行できるためです。コマンドラインで指定された.serファイルや.jarファイルに対しては、他の操作を実行できません。

-profile=falseを指定して.sqljファイルを処理する場合は、必要に応じて、後でカスタマイズを行います。

注意:

- Oracleカスタマイザを変換処理で使用する場合は、アプリケーションの実行時にOracle SQLJランタイムおよびOracle JDBCドライバを必要としない場合は、-profile=falseを指定します。または-default-customizerオプションを使用して、デフォルト以外のカスタマイザを指定する方法もあります。カスタマイズを実行しないと、アプリケーション実行時に汎用SQLJランタイムが使用されます。

- -compile=falseを設定すると、-profile=falseも暗黙的に設定されます。つまり、-compileがfalseの場合は、コンパイルとカスタマイズの両方が省略されます。-compile=falseと-profile=trueを設定した場合、-profile設定は無視されます。

- デフォルトのOracle固有コード生成では、プロファイルが生成されずカスタマイズが実行されないため、このオプションを使用できません。

このオプションのコマンドライン構文は、次のとおりです。

-profile<=true|false>

次に例を示します。

-profile=false

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.profile<=true|false>

次に例を示します。

sqlj.profile=false

次に、このオプションのデフォルト値を示します。

true

.serファイルから.classファイルへの変換(-ser2class)

ISO標準SQLJコード生成の場合、-ser2classフラグでは、生成された.serファイルが.classファイルに変換されます。末尾に.serの付くリソース・ファイル名がサポートされないブラウザから実行されるアプレットを、SQLJを使用して作成する場合、この処理が必要です。

また、クライアント側でSQLJプログラムを変換してから、クラス・ファイルとリソース・ファイルをサーバーにロードする場合、この処理を行うとプロファイル用のスキーマ・オブジェクトの名前付けが簡略化されます。ロード済のクラス・スキーマ・オブジェクトのネーミング規則は、ロード済のリソース・スキーマ・オブジェクトよりも簡略化されています。

関連項目:
「ロードされたクラスとリソース・スキーマ・オブジェクトの名前付け」

プロファイルのカスタマイズ後に変換が行われ、独自のカスタマイズが取り込まれます。変換後のファイルのベース名は、元のファイルのベース名と同じになります。ファイル名の.serのみが.classに置き換えられます。たとえば、次の場合を考えます。

Foo_SJProfile0.ser

このファイル名は次のファイル名に変換されます。

Foo_SJProfile0.class

注意:

- 元の.serファイルは保存されません。

- プロファイルを.classファイルに変換すると、これ以上はカスタマイズできなくなります。この場合は、.classファイルを削除し、SQLJを再度実行してプロファイルを再作成する必要があります。

- 文字エンコーディングが必要な場合、-ser2classオプションでは常に文字エンコーディング8859_1が使用され、SQLJの-encoding設定は無視されます。

- デフォルトのOracle固有コード生成を使用する場合は、プロファイルが生成されないため、-ser2classオプションは適用されません。

このオプションのコマンドライン構文は、次のとおりです。

-ser2class<=true|false>

次に例を示します。

-ser2class

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.ser2class<=true|false>

次にその例を示します。

sqlj.ser2class

次に、このオプションのデフォルト値を示します。

false

型解決を目的としたソース・チェック(-checksource)

CLASSPATH内のクラス・ファイルとSQLJコマンドラインで指定されたクラス・ファイルまたはソース・ファイルのみを検証するのでは、SQLJ型解決処理には十分ではありません。SQLJでは-checksourceフラグを使用すると、次の条件に該当する場合、CLASSPATH中にあるソース・ファイルも検査の対象になります。

- 要求されたクラスのクラス・ファイルは見つからないが、ソース・ファイルが見つかった場合

- ソース・ファイルの修正日付が、対応するクラス・ファイルよりも新しい場合

注意:
この型解決が有効になるのは#sql文に指定されているJava型のみであって、Javaコード中では有効になりません。このため、必要な.sqljファイルの名前は、SQLJコマンドラインで明示的に指定する必要があります。

このオプションのコマンドライン構文は、次のとおりです。

-checksource<=true|false>

次に例を示します。

-checksource=false

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.checksource=<=true|false>

次に例を示します。

sqlj.checksource=false

次に、このオプションのデフォルト値を示します。

true

識別子によるホスト式のバインド(-bind-by-identifier)

SQLJ標準と同様に、Oracle実装のデフォルトでは、同じホスト変数が複数回出現する場合でも、1文中の各ホスト変数のバインド参照には一意の名前を作成します。SQLJ標準はJDBCに基づいており、JDBCは同じ変数を異なる位置にバインドするようにはプロビジョニングされていません。各バインド位置(?で識別)が個々の値にバインドされます。

このため、状況によっては、次の例のような場合にエラーが発生することがあります。

#sql emps = { SELECT substr(ename, 1, :bind_var), sum(sal) FROM emp
GROUP BY substr(ename, 1, :bind_var) };

2つのbind_varに対してバインド参照名が個別に作成されるため、実行時に結果がSQL例外となります。異なるバインド名が検出されると、SQLエンジンではGROUP BY句がSELECT構文のリストの一部ではないと判断します。

この問題を回避するために、Oracleでは、-bind-by-identifierフラグを使用して標準機能が拡張されています。trueに設定されている場合は、指定されたSQLJ文またはPL/SQLブロック内に同じ識別子が複数回出現しても、単一のバインドとして処理されます。4つのバインド操作(:x、:x、:y、:x)が行われるSQLJ文は、:1、:2、:3、:4ではなく、:1、:1、:2、:1としてバインドされます。

前述の例で、双方のバインド操作は、substr(ename, 1, :1)およびsubstr(ename, 1, :2)ではなく、substr(ename, 1, :1)となります。

注意:
-bind-by-identifierフラグは、ホスト変数が単純なホスト式にのみ適用します。

このオプションのコマンドライン構文は、次のとおりです。

-bind-by-identifier<=true|false>

次に例を示します。

-bind-by-identifier

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.bind-by-identifier=<=true|false>

次に例を示します。

sqlj.bind-by-identifier

次に、このオプションのデフォルト値を示します。

false

セマンティクス・チェックとオフライン解析のオプション

次の各オプションで、オンラインおよびオフラインのセマンティクス・チェックとオフライン解析を指定します。

- -offline

- -online

- -cache

- -parse

これらのオプションを説明する前に、次の2項目について説明します。

- OracleChecker(セマンティクス・チェックのデフォルトのフロントエンド・クラス)およびOracleのセマンティクス・チェッカ

- オンライン・セマンティクス・チェックとオフライン解析との比較

注意:
「オンライン・セマンティクス・チェックとユーザー名(-user)」で説明したように、オンライン・セマンティクス・チェックは、トランスレータの-userオプションを設定することによって有効になります。ただし、この設定は、オフライン解析を有効または無効にする-parseオプションを設定することによって、オーバーライドできます。「オフライン・パーサー(-parse)」を参照してください。

セマンティクス・チェッカおよびOracleCheckerフロントエンド(デフォルトのチェッカ)

Oracleでは、Oracle専用のオフライン・チェッカ、汎用のオフライン・チェッカ、Oracle専用のオンライン・チェッカ、汎用のオンライン・チェッカが提供されています。汎用チェッカは、SQL-92エントリ・レベルおよびJDBCの標準機能のみを使用することを前提としています。Oracle Databaseを使用する場合は、Oracle専用チェッカを使用することをお薦めします。

デフォルトのチェッカは、オンライン・チェックおよびオフライン・チェックともoracle.sqlj.checker.OracleCheckerで、ほとんどの環境で十分に機能します。このクラスはフロントエンドとして機能し、使用する環境やオフラインとオンラインの選択に応じて、適切なセマンティクス・チェッカを実行します。

Oracleの場合は、Oracle Database 10g 、Oracle9i およびOracle8i タイプのOracle8チェッカ(対応するJDBC実装で使用)があります。

Oracle DatabaseとJDBCドライバによるオンライン・チェック

オンライン・チェックにOracle DatabaseとOracle JDBCドライバを使用する場合、データベースとJDBCドライバの低い方のバージョンにあわせて、OracleCheckerがチェッカを選択します。表8-4に、データベースのバージョンとJDBCドライバのバージョンとの組合せと、他の有効なOracleチェッカを一覧の形式で示します。

表8-4 OracleCheckerで選択されるOracleオンライン・セマンティクス・チェッカ

データベースのリリース

JDBCのリリース

オンライン・チェッカの選択

他の有効なオンライン・チェッカ

Oracle Database 10g 、Oracle9i またはOracle8i

Oracle11g

Oracle8JdbcChecker

Oracle8To7JdbcChecker

JDBCドライバによるオフライン・チェック

オフライン・チェックにOracle JDBCドライバを使用する場合、JDBCドライバのバージョンにあわせて、OracleCheckerがチェッカを選択します。チェッカの選択については、表8-5に要約します。

表8-5 OracleCheckerで選択されるOracleオフライン・セマンティクス・チェッカ

JDBCのリリース

オフライン・チェッカの選択

他の有効なオフライン・チェッカ

Oracle11g

Oracle8OfflineChecker

なし

オンライン・セマンティクス・チェックとオフライン解析との比較

Oracle SQLJ実装は、オンライン・セマンティクス・チェックのかわりに限定的なチェックを提供する、オフライン解析と呼ばれる機能をサポートしています。オフライン解析はデータベース接続を使用しないため、データベース・スキーマに対する操作の検証は実行できませんが、SQL文とPL/SQL文すべての構文チェックを実行できます。(Oracle9iより前では、データベース接続なしで構文チェックを実行することはできません。)

オフライン解析およびオンライン・セマンティクス・チェックで提供される機能の比較を表8-6にまとめます。

表8-6 機能の比較: オフライン解析とオフライン・セマンティクス・チェック

機能

オフライン解析

オンライン・チェック

データ操作言語(DML)、SELECTおよびPL/SQL構文の検証

あり

あり

データ定義言語(DDL)構文の検証

あり

なし

DML、SELECTおよびPL/SQLセマンティクスの検証(データベース・スキーマとの比較)

なし

あり

DDLセマンティクスの検証(データベース・スキーマとの比較)

なし

なし

オンライン・チェックには、データベース・スキーマに対するSQLおよびPL/SQLの操作を検証できるという主なメリットがあります。オンライン・チェックでは、列の型がSQL操作と一致するかどうか、およびコールされたストアド・プロシージャが存在するかどうかの検証も行われます。それには、変換時にデータベース接続が必要になりますが、状況によっては、これが問題の原因となる場合があります。DDL操作の検証は行われません。

オフライン解析には、変換時にデータベースに接続せずにSQL構文をチェックできるメリットがあります。この構文チェックではDDL操作の検証も行われます。

いずれのモードでも、データベース・スキーマに対するDDLセマンティクス・チェックは行われません。

注意:

- オフライン解析とオンライン・チェックの両方が有効化されている場合、一部の種類のエラーは2回レポートされます。

- オフライン・パーサーまたはオンライン・チェッカによって検出される問題は、致命的なレベルではなく警告レベルまたは助言レベルでレポートされます。

- オフライン解析とオフライン・セマンティクス・チェックを混同しないでください。オフライン・チェックは、オンライン・チェックが有効かどうか、およびオフライン解析が有効かどうかに関係なく、常に実行される基本的なセマンティクス・チェック手順で構成されます。この処理には、SQLJ実行文で使用されているJava式の型の分析や、SELECTなどのキーワードに基づいた、埋込みSQL操作の分類などがあります。

- 弱い型指定のホスト式に対するデータの互換性はチェックされません。

- PL/SQLの無名ブロック内で使用されている式のモード互換性はチェックされません。

オフライン・セマンティクス・チェッカ(-offline)

-offlineオプションには、オフライン・チェックのための、SQLJのセマンティクス・チェック・コンポーネントを実装したJavaクラスを指定します。オフライン・チェックでは、データベース接続がありません。SQL構文およびJava型の使用方法のみがチェックされます。-offlineオプションでオフライン・チェックが有効または無効になることはありません。オンライン・チェックが有効になっていないため、またはデータベース接続を確立できないために、オンライン・チェックが実行されない場合にのみ、オフライン・チェックが実行されます。

異なる接続コンテキストごとに異なるオフライン・チェッカを指定できますが、1つのコンテキストにつき1つのチェッカに制限されています。1つの接続コンテキストに複数のオフライン・チェッカを指定しないでください。通常は、フロントエンド・クラスである、デフォルトのOracleCheckerを使用できますが、OracleCheckerで選択されない特定のチェッカを指定する場合は別です。

次の例は、特定の接続コンテキスト(CtxClass)をチェックするためにOracle8のオフライン・チェッカを選択する方法を示しています。

-offline@CtxClass=oracle.sqlj.checker.Oracle8OfflineChecker

この例では、SQLJでoracle.sqlj.checker.Oracle8OfflineCheckerが使用され、CtxClassインスタンスである接続オブジェクトを指定するSQLJ実行文について、オフライン・チェックが行われます。

接続コンテキスト・クラスCtxClassは、ソース・コード中に宣言するか、あらかじめ.classファイルにコンパイルしておく必要があります。(詳細は、「接続コンテキスト」を参照してください。)

-offlineオプションは、接続コンテキストのオフライン・チェッカごとに個別に設定します。これらの接続コンテキストの設定が相互に影響し合うことはありません。次に例を示します。

-offline@CtxClass2=oracle.sqlj.checker.Oracle8OfflineChecker
-offline@CtxClass3=sqlj.semantics.OfflineChecker

デフォルトの接続コンテキスト、およびオフライン・チェッカを指定しない他の接続コンテキストに対してオフライン・チェッカを指定するには、次のようにします。

-offline=oracle.sqlj.checker.Oracle8OfflineChecker

オフライン・チェッカが指定されていない接続コンテキストでは、デフォルトの接続コンテキストのオフライン・チェッカ設定が使用されます。ここでは、オフライン・チェッカがデフォルトのコンテキストに設定されていることを前提とします。

このオプションのコマンドライン構文は、次のとおりです。

-offline<@conn_context_class>=checker_class

次に例を示します。

-offline=oracle.sqlj.checker.Oracle8OfflineChecker
-offline@CtxClass=oracle.sqlj.checker.Oracle8OfflineChecker

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.offline<@conn_context_class>=checker_class

次に例を示します。

sqlj.offline=oracle.sqlj.checker.Oracle8OfflineChecker
sqlj.offline@CtxClass=oracle.sqlj.checker.Oracle8OfflineChecker

次に、このオプションのデフォルト値を示します。

oracle.sqlj.checker.OracleChecker

オンライン・セマンティクス・チェッカ(-online)

-onlineオプションには、SQLJのオンライン・セマンティクス・チェック・コンポーネントを実装したJavaクラスまたはクラスのリストを指定します。この処理では、データベースへの接続が行われます。オンライン・チェックは、-onlineオプションでは有効になりません。-userオプションを使用して有効にする必要があります。-password、-urlおよび-driverの各オプションも、適切に設定されていることが必要です。

注意:
SQLJの-parseオプションの設定によっては、-userオプションの効果が無視され、オンライン・セマンティクス・チェックも無効になります。

異なる接続コンテキストごとに異なるオンライン・チェッカを指定することも、1つのコンテキストに複数のチェッカを指定することも可能です(カンマ区切りで指定します)。1つのコンテキストに複数のチェッカを指定した場合、SQLJは(リストの左から右に向かって)最初に指定されているチェッカを使用します。このチェッカは、オンライン・チェック用に確立されたデータベース接続を受け入れます。分析時に接続が各オンライン・チェッカに渡され、チェッカはデータベースを認識したかどうかを確認します。

通常は、フロントエンド・クラスである、デフォルトのOracleCheckerを使用できますが、OracleCheckerで選択されない特定のチェッカを指定する場合は別です。

次の例では、DefaultContextクラスおよび設定値を指定していない接続コンテキスト・クラスをチェックするために、Oracle8のオンライン・チェッカを選択します。

-online=oracle.sqlj.checker.Oracle8JdbcChecker

ドライバのリストを指定し、アクセスしているデータベースの種類に応じて適切なクラスが選択されるようにするには、次のように指定します。

-online=oracle.sqlj.checker.Oracle8JdbcChecker,sqlj.semantics.JdbcChecker

このように指定した場合、Oracle Databaseに接続した後でoracle.sqlj.checker.Oracle8JdbcCheckerセマンティクス・チェッカが使用されます。他の種類のデータベースへの接続が行われた場合は、汎用的なsqlj.semantics.JdbcCheckerセマンティクス・チェッカが使用されます。これは、デフォルトのOracleCheckerと類似する機能です。

特定の接続コンテキスト(CtxClass)用にオンライン・チェッカを指定するには、次のようにします。

-online@CtxClass=oracle.sqlj.checker.Oracle8JdbcChecker

この例では、oracle.sqlj.checker.Oracle8JdbcCheckerが使用され、CtxClassのインスタンスである接続オブジェクトを指定するSQLJ実行文に対して、オンライン・チェックが行われます。ここでは、CtxClassに対するオンライン・チェックが有効になっていることを前提としています。

接続コンテキスト・クラスCtxClassは、ソース・コード中に宣言するか、あらかじめ.classファイルにコンパイルしておく必要があります。

-onlineオプションは、各接続コンテキストのオンライン・チェッカごとに設定します。これらの設定は互いに影響しません。

-online@CtxClass2=oracle.sqlj.checker.Oracle8JdbcChecker
-online@CtxClass3=sqlj.semantics.JdbcChecker

オンライン・チェッカを設定していない接続コンテキストは、デフォルトの接続コンテキストのオンライン・チェッカ設定を使用します。

このオプションのコマンドライン構文は、次のとおりです。

-online<@conn_context_class>=checker_class(list)

次に例を示します。

-online=oracle.sqlj.checker.Oracle8JdbcChecker
-online=oracle.sqlj.checker.Oracle8JdbcChecker,sqlj.semantics.JdbcChecker
-online@CtxClass=oracle.sqlj.checker.Oracle8JdbcChecker

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.online<@conn_context_class>=checker_class(list)

次に例を示します。

sqlj.online=oracle.sqlj.checker.Oracle8JdbcChecker
sqlj.online=oracle.sqlj.checker.Oracle8JdbcChecker,sqlj.semantics.JdbcChecker
sqlj.online@CtxClass=oracle.sqlj.checker.Oracle8JdbcChecker

次に、このオプションのデフォルト値を示します。

oracle.sqlj.checker.OracleChecker

オンライン・セマンティクス・チェッカ実行結果のキャッシング(-cache)

-cacheオプションを使用すると、オンライン・チェッカで生成された結果のキャッシングが有効になります。これによって、以後のSQLJ変換実行時に、その他のデータベース接続が確立されることはなくなります。分析結果は、カレント・ディレクトリに格納してあるSQLChecker.cacheファイル中にキャッシングされます。キャッシュには、正常に変換された(エラー・メッセージまたは警告メッセージなしで変換された)SQL文すべてが、シリアライズされて格納されますが、それには文のパラメータ、戻り型、トランスレータ設定およびモードがすべて含まれます。

キャッシュは累積し、SQLJトランスレータが起動されるたびに増大します。キャッシュを空にするには、SQLChecker.cacheファイルを削除します。

このオプションのコマンドライン構文は、次のとおりです。

-cache<=true|false>

次に例を示します。

-cache

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.cache<=true|false>

次に例を示します。

sqlj.cache

次に、このオプションのデフォルト値を示します。

false

オフライン・パーサー(-parse)

-parseオプションを使用してオフライン解析を有効化します。オフライン解析は、オンライン・セマンティクス・チェックを補完し、変換時にデータベースに接続せずにSQLおよびPL/SQLの構文チェックを実行します(スキーマに対する検証は実行しません)。オフライン解析では、オンライン・チェックでは実行されないDDL文の構文もチェックされます。

また、-parseオプションの設定は、-userオプションによって有効になるオンライン・チェックよりも優先されます。使用可能な-parse設定は、次のとおりです。

- both(デフォルト): オフライン・パーサーとオンライン・チェックを有効にします。この場合、オンライン・チェックは、-userオプションによって判断されます。

- online-only: オフライン・パーサーを無効にし、オンライン・チェックを有効にします。この場合もオンライン・チェックは、-userオプションによって判断されます。

- offline-only: オフライン・パーサーを有効にし、オンライン・チェックを無効にします。この設定によって、オンライン・チェックを有効にする-userオプションは無視されます。

- none: オフライン・パーサーとオンライン・チェックを無効にします。この設定によっても、オンライン・チェックを有効にする-userオプションは無視されます。

- parserclassname : 代替SQLパーサーを実装するJavaクラス名を指定します。このクラスはsqlj.framework.checker.SimpleCheckerインタフェースを実装する必要があります。この設定によって指定パーサーが有効になり、SQLチェックに使用されるパーサーは、このパーサーのみになります。標準のオフライン・パーサーとオンライン・チェックは、両方とも無効になります。

offline-onlyとnoneの設定は完全性のために提供されており、通常の操作モードではありません。-userオプションでオンライン・チェックを判断することをお薦めします。ユーザー独自のパーサーも一般的には指定しません。

注意:
オフライン解析とオンライン・チェックの両方を有効にするモードでは、一部の問題が重複してレポートされることがあります。

このオプションのコマンドライン構文は、次のとおりです。

-parse=both|online-only|offline-only|none|parserclassname

次に例を示します。

-parse=online-only

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.parse=both|online-only|offline-only|none|parserclassname

次に例を示します。

sqlj.parse=online-only

次に、このオプションのデフォルト値を示します。

both

トランスレータによる代替環境のサポートとオプション

デフォルトで、Oracle Database 11g SQLJ実装はSun社のJDK 1.5.xの環境で実行するように構成され、Sun社のコンパイラjavacを使用するようになっています。ただし、これらは必須条件ではありません。SQLJは、他のJVMやコンパイラで機能するように設定することも可能です。この設定を行うには、SQLJで次の情報を指定する必要があります。

- 使用するJVMの名前(-vmオプション)

- 使用するJavaコンパイラの名前(-compiler-executableオプション)

- コンパイラで必要な設定

この情報を指定する際には、一連のSQLJオプションを使用できます。また、デフォルトの設定では、SQLJでOracleプロファイル・カスタマイザが使用されますが、他のカスタマイザを指定することも可能です。

注意:
使用するオペレーティング・システムおよび環境による制限事項に注意してください。特に、完成し、展開されたSQLJコマンドラインのサイズが、許容されるコマンドラインの最大値サイズを超えないようにしてください。使用するオペレーティング・システムのドキュメントを参照してください。

ここでは、次の項目について説明します。

- Javaおよびコンパイラのオプション

- カスタマイズのオプション

Javaおよびコンパイラのオプション

次の各オプションは、JVMおよびJavaコンパイラの操作を指定するオプションです。

- -vm(JVMを指定。コマンドラインのみ。)

- -compiler-executable(Javaコンパイラを指定。)

- -compiler-encoding-flag

- -compiler-output-file

- -compiler-pipe-output-flag

標準javacをはじめとする一部のコンパイラでは、定義済のPublicクラスがあれば、それと同じ名前をJavaソース・ファイル名に付ける必要があります。このため、このファイル名がPublicクラス名と同じかどうかの検査が、SQLJトランスレータではデフォルトで実行されます。SQLJでこうした検証が実行されないように指定する場合は、-checkfilenameオプションを使用します。

JVMやコンパイラの設定によっては、SQLJでコンパイラを起動する通常の方法で、問題が発生する可能性があります。こうした問題を回避するには、-passesオプションを使用して、SQLJでの処理を2段階で実行します。-Jおよび-C接頭辞を指定すると、使用するJVMやコンパイラにオプションを直接渡すことが可能になります。

注意:
-vmオプション、-passesオプションおよび接頭辞-Jは、プロパティ・ファイルでは使用できません。これらはコマンドラインで設定する方法も、より簡単に環境変数SQLJ_OPTIONSで設定する方法もあります。

Java Virtual Machine(JVM)の名前(-vm)

SQLJで使用される特定のJVMを指定する場合は、-vmオプションを使用します。それ以外の場合は、Sun MicrosystemsのJDKの標準のjavaが使用されます。プロパティ・ファイルはJVMの起動後に読み取られるため、プロパティ・ファイルでこのオプションを設定することは不可能です。

SQLJでは、JVMの実行可能ファイル名と一緒にディレクトリ・パスを指定しないと、オペレーティング・システムのPATH変数に基づいて実行可能ファイルの検索が開始されます。

注意:
このオプションの特殊な機能として-vm=echoがサポートされています。これは-nオプションに相当するもので、sqljスクリプトは、SQLJトランスレータに渡されるコマンドライン全体を作成し、トランスレータでは実行しないでユーザーにエコーするように指示されます。

このオプションのコマンドライン構文は、次のとおりです。

-vm=JVM_path+name

次に例を示します。

-vm=/myjavadir/myjavavm

デフォルト値は次のとおりです。

java

Javaコンパイラの名前(-compiler-executable)

SQLJで特定のJavaコンパイラを使用する場合は、-compiler-executableオプションで指定します。それ以外の場合は、Sun社のJDKの標準のjavacが使用されます。

SQLJでは、コンパイラの実行可能ファイル名と一緒にディレクトリ・パスを指定しないと、オペレーティング・システムのPATH変数に基づいて実行可能ファイルの検索が開始されます。

使用するJavaコンパイラの要件は次のとおりです。

- 標準の出力デバイス(UNIXシステムのSTDOUTなど)、または-compiler-output-fileオプションで指定するファイルに、エラー情報およびステータス情報を出力できること。

- クラス・ファイルのルート・ディレクトリを決定するSQLJの-dオプションを認識できること。

- コンパイラ・エラーが発生するたびに、0(ゼロ)以外の終了コードを戻り値としてオペレーティング・システムに戻すこと。

- エラーやメッセージで示す行情報が、次のいずれかの形式であること(<>内の項目はオプションです)。

- Sun社javac形式

filename.java:line<.column><-line<.column>>

例: myfile.java:15: Illegal character: '\u01234'

- Microsoft jvc形式

filename.java(line,column)

例: myfile.java(15,7) Illegal character: '\u01234'

SQLJでは、コンパイラの行情報が、生成された.javaファイルではなくオリジナルの.sqljファイルの行番号を使用するように処理されます。

注意:
-encodingオプションがサポートされていないコンパイラの場合は、-compiler-encoding-flagを無効化してください。

このオプションのコマンドライン構文は、次のとおりです。

-compiler-executable=Java_compiler_path+name

次に例を示します。

-compiler-executable=/myjavadir/myjavac

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.compiler-executable=Java_compiler_path+name

次に例を示します。

sqlj.compiler-executable=myjavac

デフォルト値は次のとおりです。

javac

コンパイラが使用する文字エンコーディング(-compiler-encoding-flag)

-encodingオプションを使用して、SQLJで使用する文字エンコーディングを指定すると、SQLJはこの指定をJavaコンパイラに渡します。SQLJがコンパイラに文字エンコーディングの指定を渡さないようにするには、-compiler-encoding-flagをfalseに設定します。たとえば、javac以外のコンパイラを使用し、そのコンパイラが-encodingオプションをその名前ではサポートしていないとき、この設定が必要です。

このオプションのコマンドライン構文は、次のとおりです。

-compiler-encoding-flag<=true|false>

次に例を示します。

-compiler-encoding-flag=false

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.compiler-encoding-flag<=true|false>

次に例を示します。

sqlj.compiler-encoding-flag=false

デフォルト値は次のとおりです。

true

コンパイラの出力ファイル(-compiler-output-file)

Javaコンパイラがその結果をファイルに書き込むようにする場合は、-compiler-output-fileオプションを使用して、SQLJにファイル名を通知します。この操作を行わない場合、SQLJでは、コンパイラが結果を標準の出力デバイス(UNIXシステムのSTDOUTなど)に書き込むものと見なされます。絶対パスまたはカレント・ディレクトリからの相対パスは、必要に応じて指定してください。

注意:
-passesを有効にする場合は、このオプションを使用できません。この場合は、STDOUTに出力されることが必要です。

このオプションのコマンドライン構文は、次のとおりです。

-compiler-output-file=output_file_path+name

次に例を示します。

-compiler-output-file=/myjavadir/mycmploutput

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.compiler-output-file=output_file_path+name

次に例を示します。

sqlj.compiler-output-file=/myjavadir/mycmploutput

このオプションにはデフォルト値はありません。

コンパイラ・メッセージの出力パイプ(-compiler-pipe-output-flag)

デフォルトでは、Javaコンパイラはエラーおよびメッセージの出力をSTDERRに書き込みます。ただし、Javaコンパイラからのエラー・メッセージも、-compiler-output-fileオプションで指定した同じファイルにリダイレクトする必要がある場合は、このフラグをtrueに設定します。このオプションは、-compiler-output-fileと併用する場合にのみ有効です。

このフラグの設定は、コマンドラインまたはSQLJ_OPTIONS環境変数のみでなく、プロパティ・ファイルでも行えます。

このオプションのコマンドライン構文は、次のとおりです。

-compiler-pipe-outflag=<true|false>

たとえば、MyDemo.sqljというファイルのコンパイル時に、このファイルに関するJavaコンパイラ・メッセージおよびエラー・メッセージを同じファイルにリダイレクトする場合、次の構文を使用する必要があります。

sqlj -compiler-output-file=/myjavadir/mycmploutput
-compiler-pipe-output-flag=true MyDemo.sqlj

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.compiler-pipe-output-flag<=true|false>

デフォルト値は次のとおりです。

true

注意:
このフラグがfalseに設定されている場合、Javaコンパイラからのエラー・メッセージはSTDERRに送られます。

ソース・ファイル名のチェック(-checkfilename)

ソース・ファイル名は、定義済のPublicクラス名と同一にするか、Publicクラスが未定義の場合は、最初に定義されているクラス名と同一にすることをお薦めします。たとえば、MyPublicClass.sqljソース・ファイル中には、PublicクラスMyPublicClassが定義してあることが望まれます。

SQLJソース・ファイル名が、ファイル中の定義済Publicクラス名(ある場合)と同じかどうかの検証は、-checkfilenameフラグで要否を指定します。標準javacのような一部のコンパイラでは、ソース・ファイル名をPublicクラス名と同じ名前にする必要がありますが、そうでないコンパイラもあります。

コードの移植性を最大限に高めるには、このフラグを有効にしておく必要があります(デフォルトで有効になります)。

注意:
サーバー側での変換にはネーミング要件が伴わないため、-checkfilenameオプションは不要であり、トランスレータによる名前のチェックも実行されません。

このオプションのコマンドライン構文は、次のとおりです。

-checkfilename<=true|false>

次に例を示します。

-checkfilename=false

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.checkfilename<=true|false>

次に例を示します。

sqlj.checkfilename=false

デフォルト値は次のとおりです。

true

SQLJでの2段階による実行(-passes)

デフォルトでは、sqljスクリプトを実行すると、次に示す処理が展開されます。

1. sqljスクリプトによってJVMが起動され、SQLJトランスレータが実行されます。

2. トランスレータによって、セマンティクス・チェックおよび.sqljファイルの変換が行われ、変換された.javaファイルが生成されます。

3. トランスレータによってJavaコンパイラが起動され、生成済の.javaファイルがコンパイルされます。

4. トランスレータによって、コンパイラの出力が処理されます。

5. プロファイル・ファイルが生成されていなければ、トランスレータはプロファイル・カスタマイザを起動し、カスタマイズを実行します。

ただし、JVMとコンパイラの設定によっては、手順3でコンパイラが起動されないために変換が一時停止する場合もあります。

この場合は、SQLJが2段階で実行され、その間にコンパイル処理が行われるように指定します。これを行うには、2段階による実行を指定するフラグを有効にする必要があります。

-passes

-passesオプションは、コマンドラインまたは環境変数SQLJ_OPTIONSで指定します。プロパティ・ファイルでは指定できません。

注意:

- -passesを有効にする場合は、コンパイラの出力がSTDOUTに書き込まれることが必要です。そのため、-compiler-pipe-output-flagは有効のままにしておきます。デフォルトでは有効になります。また、-compiler-output-fileオプションは使用できません。使用すると、出力がSTDOUTではなくファイルに書き込まれます。

- 他のコマンドライン専用フラグ(-help、-version、-n)と同じように、-passesフラグには、=true構文を使用できません。

-passesを有効にした場合、sqljスクリプトを実行すると、次に示す処理が展開されます。

1. sqljスクリプトによってJVMが起動された後で、SQLJトランスレータでの1段階目の処理が実行されます。

2. トランスレータによって、セマンティクス・チェックおよび.sqljファイルの変換が行われ、変換された.javaファイルが生成されます。

3. JVMを終了します。

4. sqljスクリプトによって、Javaコンパイラが起動され、生成済の.javaファイルがこのコンパイラでコンパイルされます。

5. sqljスクリプトによってJVMが再び起動された後で、SQLJトランスレータでの2段階目の処理が実行されます。

6. トランスレータによって、コンパイラの出力が処理されます。

7. プロファイル・ファイルが生成されていなければ、JVMはプロファイル・カスタマイザを起動し、カスタマイズを実行します。

この手順では、JVMがJavaコンパイラを起動する際に発生する問題が回避されます。

このオプションのコマンドライン構文は、次のとおりです。

-passes

次に例を示します。

-passes

デフォルト値は次のとおりです。

off

カスタマイズのオプション

次の各オプションは、必要に応じてSQLJプロファイルのカスタマイズを指定します。

- -default-customizer

- カスタマイザに直接渡すオプション

注意:
デフォルトのOracle固有コード生成を使用する場合は、SQLJによってプロファイルが生成されないため、カスタマイズが実行されません。その場合、これらのオプションは適用されません。

デフォルト・プロファイル・カスタマイザ(-default-customizer)

SQLJで下記のデフォルト以外のプロファイル・カスタマイザを使用するには、-default-customizerを使用します。

oracle.sqlj.runtime.util.OraCustomizer

Oracle Databaseを使用しない場合は、このオプションを設定します。このオプションでは、Javaクラスの完全修飾名を引数として使用します。

注意:
このオプションをオーバーライドするには、SQLJのコマンドラインまたはプロパティ・ファイルで-P-customizerオプションを指定します。

このオプションのコマンドライン構文は、次のとおりです。

-default-customizer=customizer_classname

次に例を示します。

-default-customizer=sqlj.myutil.MyCustomizer

次に、このオプションのプロパティ・ファイルでの設定の構文を示します。

sqlj.default-customizer=customizer_classname

次に例を示します。

sqlj.default-customizer=sqlj.myutil.MyCustomizer

次に、このオプションのデフォルト値を示します。

oracle.sqlj.runtime.util.OraCustomizer

注意:
Oracle DatabaseとISOコード生成を使用する場合は、デフォルトのOraCustomizerでプロファイルのカスタマイズを行うことをお薦めします。

カスタマイザに直接渡すオプション

JVMやコンパイラと同様に、接頭辞(この場合は-P)を使用すると、オプションをプロファイル・カスタマイザ・ハーネスに直接渡すことが可能になります。

関連項目:
「プロファイル・カスタマイザに渡すオプション(-P)」

一般的なカスタマイズ・オプションとOracle固有のカスタマイザ・オプションの詳細は、「カスタマイズ・オプションとカスタマイザの選択」を参照してください。

9 トランスレータとランタイムの検証

この章では、Oracle SQLJのトランスレータおよびランタイムの内部操作と機能について説明します。

内容は次のとおりです。

- トランスレータの内部操作

- トランスレータのエラー、メッセージおよび終了コード

- SQLJランタイム

- トランスレータおよびランタイムでのグローバリゼーション・サポート

トランスレータの内部操作

ここでは、変換時にSQLJトランスレータによって実行される主な操作について説明します。

- JavaとSQLJのコード解析と構文チェック

- SQLのセマンティクス・チェックとオフライン解析

- コードの生成

- Javaコンパイル

- プロファイルのカスタマイズ(ISOコード生成の場合)

JavaとSQLJのコード解析と構文チェック

SQLJ変換の最初の段階では、SQLJパーサーとJavaのパーサーによってすべてのソース・コードが処理され、構文チェックが行われます。SQLJトランスレータは、.sqljファイルの解析時に、Java文の構文チェックのためにJavaパーサーを起動し、SQLJコンストラクト(先頭に#sqlが付くもの)の構文チェックのためにSQLJパーサーを起動します。また、SQLJパーサーは、Javaパーサーを起動して、SQLJ実行文に含まれるJavaホスト変数と式の構文をチェックします。

SQLJパーサーは、SQLJ言語の仕様に基づいてSQLJコンストラクトの文法をチェックします。ただし、埋込みSQL操作の文法はチェックしません。SQL構文は、セマンティクス・チェックまたはオフライン解析でチェックされます。

この構文チェックでは、セミコロンの抜け、中カッコの対の抜け、明らかな型の不一致(乗算する値の一方が文字列になっている)などのエラーが検索されます。このチェックで構文エラーまたは型の不一致が検出されると、変換が中止されてエラーが出力されます。

SQLのセマンティクス・チェックとオフライン解析

SQLJおよびJavaアプリケーションのソース・コードに構文の誤りがないことが確認されると、次のセマンティクス・チェックに進みます。このチェックでは、SQLJのオプション設定に基づいて、SQLセマンティクス・チェッカまたはSQLオフライン・パーサー(あるいはその両方)が起動します。

-userオプションを設定するとオンライン・チェックが有効になり、-userオプションでパスワードとURLが指定されていない場合に、-passwordおよび-urlオプションを設定するとデータベース接続が指定されます。-offlineオプションまたは-onlineオプションで、使用するチェッカを指定します。デフォルトでは(通常はこの設定で十分)、OracleCheckerと呼ばれるチェッカ・フロントエンドが指定され、オンライン・チェックが有効かどうか、および使用されるJava Database Connectivity (JDBC)に応じて、最も適切なチェッカが選択されます。

-parseはオフライン・パーサーを有効にするオプションであり、デフォルトはtrueです。オフライン・パーサーでは、変換時にデータベース接続なしでSQLおよびPL/SQL構文を検証する手段が提供されます(データベース列に対するデータ型の検証は行われません)。-parseオプションの設定によっては、-userオプションがオーバーライドされ、オンライン・チェックが無効になります。

関連項目:
「接続オプション」および「セマンティクス・チェックとオフライン解析のオプション」

注意:
ISOコード生成の場合は、SQLJトランスレータを前回実行した際に生成されたプロファイルに対しても、セマンティクス・チェックを実行できます。「プロファイルのセマンティクス・チェック用のSQLCheckerCustomizer」を参照してください。

セマンティクス・チェックでは、オンライン・チェックまたはオフライン解析のステータスに関係なく、次のタスクが常に実行されます。

1. SQLJによって、SQLJ実行文で使用されているJava式の型が解析されます。
変換されるSQLJソース・ファイルの他に、コマンドラインで指定した.javaファイル、インポート済のJavaクラスの.classファイルまたは.javaファイルのうちCLASSPATHで検出可能なファイルも解析の対象になります。解析では、SELECT文またはCAST文でのストリーム型が使用されているかどうか、使用されている場合はその使用方法がチェックされます。また、イテレータ列またはINTOリストで使用されているJava型、入力ホスト変数として使用されているJava型、出力ホスト変数として使用されているJava型もチェックされます。

また、SQLJでは、FETCH、CAST、CALL、SET TRANSACTION、VALUESおよびSETの各文が構文に基づいて処理されます。

SQLJ実行文内のJava式には、それぞれの状況と用途に適したJava型を指定する必要があります。たとえば、次のような文があるとします。

#sql [myCtx] { UPDATE ... };

myCtxは、この文に対する接続コンテキスト・インスタンスまたは実行コンテキスト・インスタンスを指定する変数です。この変数は、実際にSQLJの接続コンテキスト型または実行コンテキスト型に解決できることが必要です。

ここでは、次の例について考えてみます。

#sql { UPDATE emp SET sal = :newSal };

newSalがフィールドではなく変数の場合、newSalがあらかじめ宣言されていないときは、エラーが生成されます。また、この変数を有効なJava型に代入できない場合や、この変数のJava型をSQL文(java.util.Vectorなど)で使用できない場合も、エラーが生成されます。

注意:
Java型のセマンティクス・チェックは、SQLJ実行文内のJava式に対してのみ行われます。標準のJava文でのエラーは、Javaコンパイラでコンパイルされるまで検出されません。

2. SQLJで、埋込みSQL操作の分類が試みられます。このため、操作の種類を識別するために、操作ごとにSELECTやINSERTなどの認識可能なキーワードが必要です。たとえば、次の文ではエラーが生成されます。

#sql { foo };

3. オンライン・チェックまたはオフライン解析(あるいはその両方)が有効な場合は、SQLJによって、SQLとPL/SQLの埋込み操作の構文が分析および検証されます。

4. オンライン・チェックまたはオフライン解析(あるいはその両方)が有効な場合は、SQLJによって、SQLJ実行文で使用されているJava式の型が、データベースの列のSQL型、ストアド・プロシージャおよびストアド・ファンクションの引数と戻り値のSQL型に対してチェックされます。
このチェック中に、SQLJ実行文で使用されるSQLエンティティ(表、ビュー、ストアド・プロシージャなど)が実際にデータベースに存在するかどうかが、SQLJによって検証されます。また、データベース列からデータを選択してJava基本型のイテレータ列に入力する場合、基本型のイテレータ列ではNULLデータを処理できないため、SQLJは選択元のデータベース列でNULL値が許容されているかどうかもチェックします。ただし、ストアド・プロシージャやストアド・ファンクションの出力パラメータと戻り値に対しては、NULL値が許容されているかどうかはチェックされません。

コードの生成

ISO標準SQLJコード生成の場合、SQLJトランスレータは、1つの.sqljアプリケーション・ソース・ファイルに対して、1つの.javaファイルと、1つ以上のプロファイル(.serファイルまたは.classファイル)を生成します。.javaファイルには、変換済のアプリケーション・ソース・コード、宣言したprivateイテレータと接続コンテキスト用のクラス定義、および、ISOコードの場合は、SQLJによって生成されて内部的に使用されるプロファイルキーのクラス定義が含まれています。

注意:
デフォルトのOracle固有コード生成モードを使用している場合、プロファイルやプロファイルキー・クラスは生成されません。
ISOコード生成では、SQLJ実行文をコードで使用しない場合、プロファイルやプロファイルキー・クラスはありません。

.javaファイル内に生成されたアプリケーション・コード

デフォルトのOracle固有コード生成の場合、アプリケーション用に生成された.javaファイルには、元のSQLJ実行文のかわりにOracle JDBCドライバへの直接コールが含まれます。Oracle固有のSQLJランタイムへのコールもあります。ISO標準SQLJコード生成の場合、SQLJ実行文はSQLJランタイムへのコールに置き換えられ、このSQLJランタイムにはJDBCドライバへのコールが含まれます。

便宜上、生成された.javaファイルには、各#sql文に関するコメントも含まれ、参照用にその文全体も含まれます。生成された.javaファイルには、入力.sqljファイルと同じベース名が使用されます。通常は、.sqljファイルに定義されているPublicクラスの名前が使用され、Publicクラスが存在しない場合は最初に定義されているクラスの名前が使用されます。たとえば、Foo.sqljでFooクラスが定義されているとします。トランスレータで生成されるソース・ファイル名はFoo.javaとなります。

生成された.javaファイルの格納場所は、SQLJの-dirオプション設定の有無および設定方法によって決まります。デフォルトでは、生成された.javaファイルは、.sqlj入力ファイルと同じディレクトリに格納されます。

関連項目:
「.javaファイルの出力ディレクトリ(-dir)」

.javaファイル内に生成されるプロファイルキー・クラス(ISOコード生成の場合)

ISO標準SQLJコード生成を使用した場合、SQLJはプロファイルキー・クラスを生成します。これは、シリアライズされたプロファイルのロードおよびアクセスを実行するために、実行時に内部的に使用されます。このクラスには、変換済アプリケーション内のSQLJランタイム・コールと、シリアライズ・プロファイル内に挿入されたSQL操作間のマッピング情報が含まれています。また、シリアライズ・プロファイルにアクセスするためのメソッドも含まれています。

注意:
デフォルトのOracle固有コード生成を使用している場合、プロファイルやプロファイルキー・クラスは生成されません。

このプロファイルキー・クラスは、変換されたアプリケーション・ソース・コードが出力された.javaファイル内に定義され、次のように、.sqljソース・ファイルのベース名を使用した名前が付けられます。

Basename_SJProfileKeys

たとえば、Foo.sqljを変換すると、生成された.javaファイルには、次のプロファイルキー・クラスが定義されます。

Foo_SJProfileKeys

これは、パッケージに含まれるアプリケーションの場合も同じです。たとえば、a.bというパッケージに含まれるFoo.sqljを変換すると、次のクラスが定義されます。

a.b.Foo_SJProfileKeys

.serファイルまたは.classファイル内に生成されるプロファイル(ISOコード生成の場合)

ISO標準SQLJコード生成を使用した場合、SQLJは、入力ファイル内のSQL操作に関する情報を格納するためのプロファイルを生成します。プロファイルは、アプリケーションで使用する接続コンテキスト・クラスごとに1つ生成されます。プロファイルには、関連付けられた接続コンテキスト・クラスのインスタンスを使用して実行される操作が記述されています。つまり、実行するSQL操作、アクセスする表、コールするストアド・プロシージャとストアド・ファンクションなどが記述されています。

注意:
デフォルトのOracle固有コード生成を使用する場合、SQL操作に関する情報はOracle JDBCドライバを直接コールする生成コードに埋め込まれます。この場合、SQLJではプロファイルが生成されません。

プロファイルは、.serシリアライズ・リソース・ファイル内に生成されます。ただし、SQLJの-ser2classオプションが有効になっている場合は、変換時にプロファイルが.classファイルに自動的に変換されます。この場合、これ以降のプロファイルのカスタマイズはできなくなります。.classファイルを削除し、SQLJトランスレータを再度実行してプロファイルを再作成する必要があります。

プロファイルのベース名は、プロファイルキー・クラス名の場合と同じように生成されます。このベース名には、パッケージ名の後に.sqljファイルのベース名が続き、最後に次の文字列が付きます。

_SJProfilen

n は0(ゼロ)から始まる一意の番号で、特定の.sqlj入力ファイルに対して生成された各プロファイルに付けられます。

再び、Foo.sqljという入力ファイルを例として使用します。この入力ファイルがパッケージに含まれていない場合、生成される2つのプロファイルのベース名は、次のようになります。

Foo_SJProfile0
Foo_SJProfile1

Foo.sqljがa.bというパッケージに含まれる場合、プロファイルのベース名は、次のようになります。

a.b.Foo_SJProfile0
a.b.Foo_SJProfile1

実際には、プロファイルは、リソース・ファイル内のシリアライズされたJavaオブジェクトとして存在します。プロファイルを含むリソース・ファイルには、プロファイルのベース名(パッケージ名は除く)に従って名前が付けられ、拡張子として.serが付きます。前述の例の2つのプロファイルを含むリソース・ファイルには、それぞれ次のように名前が付けられます。

Foo_SJProfile0.ser
Foo_SJProfile1.ser

ただし、-ser2classオプションが有効になっている場合は、Foo_SJProfile0.classおよびFoo_SJProfile1.classとなります。このオプションを選択した場合は、カスタマイズ手順の後に、.classへの変換が行われます。

関連項目:
「.serファイルから.classファイルへの変換(-ser2class)」

これらのファイルは、SQLJの-dオプションで設定されているディレクトリに置かれます。生成されたすべての.serファイルおよび.classファイルの格納先は、このオプションで指定されます。

関連項目:
「.serおよび.classファイルの出力ディレクトリ(-d)」

SQLJランタイムに対して生成されたコールについて

#sql文がJDBCドライバ(Oracle固有コード生成の場合)またはSQLJランタイム(ISO標準SQLJコード生成の場合)へのコールに置き換えられている場合、これらのコールは表9-1に示す動作を行います。

表9-1 生成されたコールの動作、ISO標準とOracle固有の比較

ISO標準コード生成の場合

Oracle固有コード生成の場合

関連付けされているプロファイル・エントリ中に格納されている情報を使用して、SQLJ文オブジェクトを取得します。

Oracle JDBC文オブジェクトを取得します。

SQLJ文オブジェクトのsetXXX ()メソッドを使用して、入力パラメータを文にバインドします。

Oracle JDBC文メソッドを使用して入力をバインドして、必要な場合は、出力パラメータを登録します。

文オブジェクトのexecuteUpdate()メソッドまたはexecuteQuery()メソッドを使用して、文を実行します。

Oracle文を実行します。

可能な場合は、イテレータ・インスタンスを生成します。

可能な場合は、イテレータ・インスタンスを生成します。

SQLJ文オブジェクトのgetXXX ()メソッドを使用して、文から出力パラメータを取り出します。

JDBC取得メソッドを使用して、文から出力を取り出します。

SQLJ文オブジェクトを終了します(デフォルトで、SQLJ文キャッシュによって再使用されます)。

JDBC文オブジェクトを終了します(デフォルトで、JDBC文キャッシュによって再使用されます)。

SQLJランタイムでは、JDBC文オブジェクトに似たSQLJ文オブジェクトが使用されますが、SQLJの具体的な実装状態によっては、JDBC文クラスを直接使用できる場合とできない場合があります。SQLJ文クラスを使用すると、SQLJ固有の機能が追加されます。次に例を示します。

- 標準SQLJ文オブジェクトは、データベースから取り出したNULL値が、NULL値を使用できないintやfloatなどのJava基本型に出力されると、SQL例外を生成します。

- Oracle SQLJ文オブジェクトでは、ユーザー定義のオブジェクト型やコレクション型をOracle Databaseに渡したり、Oracle Databaseから取り出したりできます。

Javaコンパイル

コードが生成されると、SQLJではJavaコンパイラが起動され、生成済.javaファイルがコンパイルされます。これにより、アプリケーションで定義されているクラスごとに、.classファイルが生成されます(イテレータ宣言および接続コンテキスト宣言を含む)。また、ISOコード生成を使用する場合(およびアプリケーションでSQLJ実行文を使用しているとして)、生成されたプロファイルキー・クラスに対しても.classファイルが生成されます。SQLJコマンドラインで型解決などのために直接指定した.javaファイルも、この時点でコンパイルされます。

「コードの生成」で示した例では、ソース・コードにパッケージ情報が指定されている場合、次の.classファイルが適切なディレクトリに生成されます。

- Foo.class

- Foo_SJProfileKeys.class(ISOコード生成の場合のみ)

- Foo.sqljに定義した追加クラスに対する.classファイル

- Foo.sqljで宣言した各イテレータ・クラスおよび接続コンテキスト・クラス(publicおよびprivate)に対する.classファイル

.classファイルとプロファイル(ある場合は、.serまたは.classのいずれか)が、同じディレクトリに格納されるようにするために、SQLJで設定された-dオプションがJavaコンパイラに渡されます。-dオプションが設定されていない場合、.classファイルとプロファイルは、生成された.javaファイルと同じディレクトリ(-dirオプションで指定されたディレクトリ)に格納されます。

また、SQLJとJavaコンパイラで同じエンコーディングが使用されるように、SQLJはその-encodingオプションをJavaコンパイラに渡します。ただし、SQLJの-compiler-encoding-flagが無効になっている場合を除きます。-encodingオプションが設定されていない場合、SQLJとコンパイラでは、Java Virtual Machine (JVM)のfile.encodingプロパティの設定が使用されます。

デフォルトでは、標準のSun社のJava Development Kit(JDK)のjavacコンパイラが使用されますが、他のコンパイラを使用することも可能です。他のJavaコンパイラを使用するには、SQLJの-compiler-executableオプションを設定します。

注意:
SQLJの-encodingオプションを使用しているが、コンパイラに-encodingオプションがない場合は、SQLJの-compiler-encoding-flagを無効にします。無効にしないと、SQLJはコンパイラに-encodingオプションを渡そうとします。

コンパイラのオプションとコンパイラに関連するSQLJオプションに対する、SQLJのサポートに関する情報は、次の各項を参照してください。

- 「javacのオプションのサポート」

- 「.serおよび.classファイルの出力ディレクトリ(-d)」

- 「入力および出力ソース・ファイルの文字エンコーディング(-encoding)」

- 「Javaコンパイラに渡すオプション(-C)」

- 「コンパイル・フラグ(-compile)」

- 「コンパイラが使用する文字エンコーディング(-compiler-encoding-flag)」

- 「Javaコンパイラの名前(-compiler-executable)」

- 「コンパイラの出力ファイル(-compiler-output-file)」

プロファイルのカスタマイズ(ISOコード生成の場合)

ISO標準コード生成を使用している場合は、Javaコンパイルが終了すると、生成されたプロファイルのカスタマイズが行われます。プロファイルには、埋込みのSQL命令に関する情報が含まれています。カスタマイズを行うと、使用しているデータベースでのアプリケーションの処理効率が向上し、ベンダー固有の拡張機能を利用できるようになります。

注意:
デフォルトのOracle固有コード生成を使用する場合、SQLJではプロファイルが生成されず、カスタマイズも行われません。コードでは、Oracle JDBC Application Programming Interface(API)を直接コールすることによって、Oracle固有の機能をサポートします。

次のコマンドを使用して、カスタマイザで設定済のオプションを確認できます。

% sqlj -P-print *.ser

プロファイル出力オプションの詳細は、「専用カスタマイザ: プロファイル出力オプション(print)」を参照してください。

カスタマイズ時に、SQLJはカスタマイザ・ハーネスと呼ばれるフロントエンドが起動します(これはコマンドライン・ユーティリティとして機能するJavaクラスです)。このカスタマイザ・ハーネスは、特定のカスタマイザ、つまりデフォルトのOracleカスタマイザ、またはSQLJオプション設定で指定されたカスタマイザを起動します。

プロファイルのカスタマイズには、次の目的があります。

- 可能な場合は、ベンダー固有のデータベース型や機能をアプリケーションで使用できるようにします。

- データベース環境にあわせて、アプリケーションが最も効率的に機能するプロファイルを生成します。

カスタマイズを行わなかった場合、アクセスして使用できるのは標準のJDBC型のみです。

たとえば、Oracleカスタマイザを使用すると、独自に定義したSQL PERSON型をサポートするように、プロファイルを更新できます。これにより、サポートされている他のデータ型と同じようにPERSON型も使用できるようになります。

oracle.sqlの拡張型を使用する場合も、Oracleカスタマイザを使用してカスタマイズする必要があります。

注意:
プロファイルのカスタマイズについて、次の点に注意してください。

- Oracle SQLJランタイムとOracle JDBCドライバは、変換時にOracleカスタマイザを使用するたびにアプリケーションで必要となるものであり、Oracle拡張型をコード中に使用しない場合にもこのことが当てはまります。

- アプリケーションでカスタマイズ(接続のための処理)を行わない場合には、汎用SQLJランタイムが使用されます。

- .serファイル、または.serファイルを含む.jarファイルをコマンドラインで指定すると、以前に生成されたプロファイルをカスタマイズできます。ただし、これは、変換が行われるSQLJ実行とは別の実行で行う必要があります。指定できるのは、カスタマイズする.ser/.jarファイル、または変換、コンパイルおよびカスタマイズする.sqlj/.javaファイルのうち、どちらか一方のみです。.jarファイルの使用方法の詳細は、「プロファイルのJARファイルの使用」を参照してください。

プロファイルのカスタマイズの詳細は、付録A「カスタマイズおよび専用カスタマイザ」を参照してください。

プロファイルのカスタマイズに関連するSQLJオプションの詳細は、次の各項を参照してください。

- 「デフォルト・プロファイル・カスタマイザ(-default-customizer)」

- 「プロファイル・カスタマイザに渡すオプション(-P)」

- 「プロファイル・カスタマイズ・フラグ(-profile)」

- 「カスタマイズ・オプションとカスタマイザの選択」

トランスレータのエラー、メッセージおよび終了コード

ここでは、SQLJトランスレータのメッセージと終了コードの概要を示します。次の項目について説明します。

- トランスレータのエラー、警告および情報メッセージ

- トランスレータのステータス・メッセージ

- トランスレータの終了コード

トランスレータのエラー、警告および情報メッセージ

変換時に出力されるSQLJメッセージは、エラー、警告および情報の3レベルに区分されています。警告メッセージは、さらに非表示にできない警告と非表示にできる警告の2つのレベルに区分されています。次は、メッセージの4つのレベル(重要度の順)です。

1. エラー

2. 非表示にできない警告

3. 非表示にできる警告

4. 情報

非表示にできる警告と情報は、SQLJの-warnオプションを使用して制御します。

エラー・メッセージは「Error:」で開始され、次のいずれかの状態が発生した場合に表示されます。

- コンパイルを実行できない(たとえば、ファイルのベース名とは別の名前のPublicクラスがソース・ファイルに含まれている)場合。

- コードを実行すると、実行時エラーが発生する(たとえば、Oracle JDBCドライバを使用して、VARCHARをjava.util.Vectorにフェッチしようとするコードが含まれている)場合。

SQLJ変換時にエラーが発生すると、出力は生成されず、コンパイルとカスタマイズは実行されません。

非表示にできない警告メッセージは「Warning:」で開始され、次のいずれかの状態が発生した場合に表示されます。

- コードを実行したときに、実行時エラーが発生する可能性のある(たとえば、SELECT文の出力先が指定されていない)場合。

- SQLJの機能で、ソース・コードの実行時の状況が検証できない(たとえば、オンライン・チェック用に指定したデータベースに接続できない)場合。

- コーディングの誤りや見落としが原因でエラーが発生した場合。

SQLJ変換は、非表示にできない警告が発生した場合でも最後まで実行されますが、アプリケーションを実行する前に、その問題を分析して、修復の必要があるかどうかを確認してください。オンライン・チェックが指定されている場合に、オンライン・チェックを完了できなかったときは、かわりにオフライン・チェックが実行されます。

注意:
処理上の理由で、SQLJトランスレータによるSQL操作の解析には、実行時に使用されるSQLパーサーよりも精度の低い解析プログラムが使用されます。このため、変換時にエラーが検出されても、実際にはアプリケーションの実行時には問題にならない場合があります。そのようなエラーは、致命的なエラーと区別して、非表示にできない警告として出力されます。

非表示にできる警告も「Warning:」で開始され、移植性などアプリケーション固有の問題に関する情報が表示されます。たとえば、oracle.sql.NUMBERなどのOracle固有の型を使用してOracle Database 11g に対して読込みと書込みを行った場合に、警告が出力されます。

情報メッセージやステータス・メッセージはInfo:で始まりますが、エラーの状態に関する情報は出力されません。これらのエラーには、変換時に発生した事柄に関する追加情報が表示されます。

非表示にできる警告メッセージやステータス・メッセージを非表示にするには、-warnオプションの次のフラグを使用します。

- cast/nocast: nocastを設定すると、オブジェクト型インスタンスをサブタイプのインスタンスにキャストしようとするときに発生する実行時エラーに関する警告が非表示になります。

- precision/noprecision: noprecisionに設定すると、変換時にデータの精度が低下することを示す警告が非表示になります。

- nulls/nonulls: nonullsに設定すると、NULL値が許されている列や型が原因で発生する実行時エラーに関する警告が非表示になります。

- portable/noportable: noportableに設定すると、Oracle固有または非標準の機能を使用しているために、他の環境に移植できないSQLJコードに関する警告が非表示になります。

- strict/nostrict: nostrictに設定すると、名前付きイテレータの列数が、そこに取り込むために選択したデータの列数よりも少ない場合に出力される警告が非表示になります。

- verbose/noverbose: noverboseに設定すると、エラーや警告の状態ではなく情報のみを表示するステータス・メッセージが非表示になります。

関連項目:
「トランスレータからの警告(-warn)」

SQLJ変換時に警告が表示された場合は、-warn=noneオプションを設定して、トランスレータを再実行し、その警告が重要度の高いもの(非表示にできない警告)であるかどうかを確認します。

表9-2は、SQLJトランスレータで生成されるエラー・メッセージおよびステータス・メッセージの分類です。

表9-2 SQLJトランスレータのエラー・メッセージの分類

メッセージの分類

接頭辞

内容

非表示に設定する方法

エラー

Error:

コンパイル時または実行時に発生する障害の原因となる致命的なエラー(変換は異常終了します)

なし

非表示にできない警告

Warning:

変換が正常に実行されない原因、または実行時に発生する障害の原因となる状態(変換は最後まで実行されます)

なし

非表示にできる警告

Warning:

アプリケーション固有の問題(変換は最後まで実行されます)

-warnオプション・フラグ: nocast noprecision nonulls noportable nostrict

情報/ステータス・メッセージ

Info:

変換プロセスに関する情報

-warnオプション・フラグ: noverbose

トランスレータのステータス・メッセージ

エラー、警告、情報の各メッセージ以外にも、SQLJでは変換、コンパイル、カスタマイズの全段階のSQLJ操作でステータス・メッセージを生成できます。ステータス・メッセージは、各ファイルの処理時に、SQLJ操作の各段階で生成されます。

SQLJの-statusオプションを使用して、ステータス・メッセージを制御できます。

関連項目:
「リアルタイムのステータス・メッセージ(-status)」

トランスレータの終了コード

SQLJトランスレータでは、変換終了時に次の終了コードがオペレーティング・システムに戻されます。

- 0: 実行時にエラーなし

- 1: SQLJ実行時にエラー

- 2: Javaコンパイル時にエラー

- 3: プロファイルのカスタマイズ時にエラー

- 4: クラスのインストルメントのエラー(.sqljソース・ファイルから、生成される.classファイルへの行番号のマッピング(任意)時のエラー)

- 5: ser2class変換時のエラー(.serファイルから.classファイルへのプロファイル・ファイルの変換(任意)時のエラー)

注意:

- -helpオプションまたは-versionオプションが指定されている場合は、SQLJ終了コードは0(ゼロ)です。

- 処理対象のファイルを指定せずにSQLJを実行すると、SQLJによってヘルプ情報が出力され、終了コード1が戻されます。

SQLJランタイム

ここでは、Oracle SQLJランタイムについて説明します。SQLJランタイムは、Pure JavaコードのThinレイヤーで、JDBCドライバよりも上のレイヤーで実行されます。

デフォルトのOracle固有コード生成を使用する場合は、Oracle JDBCドライバとともに使用されるランタイム・サブセットによって、SQLJランタイム・レイヤーがより軽量になります。大部分のランタイム機能は、Oracle JDBCコールに直接コンパイルされます。Oracle以外のJDBCドライバは使用できません。

関連項目:
「Oracle固有コード生成(プロファイルなし)」

ISO標準コード生成を使用して、SQLJトランスレータでSQLJソース・コードを変換すると、Javaアプリケーション内の埋込みSQLコマンドはSQLJランタイムへのコールに置き換えられます。ランタイム・クラスは、それに相当するJDBCクラスのラッパーとして機能し、SQLJの特別な機能を提供します。エンド・ユーザーがアプリケーションを実行すると、SQLJランタイムが仲介役となり、プロファイルからSQL操作に関する情報を読み込んでJDBCドライバに命令を渡します。

ただし、一般的にSQLJランタイムは、あらゆるJDBCドライバおよびベンダー固有のデータベース・アクセス手段に対応しています。Oracle SQLJランタイムにはJDBCドライバが必要ですが、どの標準JDBCドライバでも使用できます。ただし、Oracle固有のデータ型や機能を使用する場合は、必ずOracle JDBCドライバを使用してください。このマニュアルでは、Oracle DatabaseとOracle JDBCドライバの1つを使用していることを前提としています。

注意:
ISO標準SQLJコード生成の場合、Oracle SQLJランタイムとOracle JDBCドライバは、変換時にOracleカスタマイザを使用するたびにアプリケーションで必要となるものであり、Oracle拡張型をコード中に使用しない場合にもこのことが当てはまります。アプリケーションでカスタマイズ(接続のための処理)を行わない場合には、汎用SQLJランタイムが使用されます。

SQLJランタイム・パッケージ

Oracle SQLJランタイムのパッケージは、インポートして直接使用できるものもあれば、間接的にしか使用できないものもあります。

注意:
これらのパッケージはランタイム・ライブラリであるruntime12、runtime12eeおよびruntimeに含まれています。

直接的に使用可能なパッケージ

アプリケーションに直接インポートして使用できるクラスを含むパッケージを次に示します。

- sqlj.runtime
このパッケージには、ExecutionContextクラス、ConnectionContextインタフェース、ConnectionContextFactoryインタフェース、ResultSetIteratorインタフェース、ScrollableResultSetIteratorインタフェースが含まれ、さらに、ストリーム(BinaryStreamやCharacterStream、および非推奨のAsciiStreamやUnicodeStream)に対するラッパー・クラスも含まれています。

このパッケージに含まれるインタフェースおよび抽象クラスは、sqlj.runtime.refパッケージやoracle.sqlj.runtimeパッケージ内のクラス、またはSQLJトランスレータによって生成されるクラスによって実装されます。

- sqlj.runtime.ref
このパッケージのクラスには、sqlj.runtimeパッケージのインタフェースおよび抽象クラスが実装されます。sqlj.runtime.ref.DefaultContextクラスを使用して、デフォルト接続を指定し、デフォルト接続コンテキスト・インスタンスを作成できます。このパッケージに含まれるその他のクラスは、コード生成時のクラス定義の際にSQLJで内部的に使用されます。たとえば、SQLJコード中でイテレータ・クラスや接続コンテキスト・クラスなどを宣言するときに使用されます。

- oracle.sqlj.runtime
このパッケージには、DefaultContextクラスのインスタンス化やデフォルト接続の確立に使用するOracleクラスが含まれています。また、Oracle SQLJで使用されるOracle固有のランタイム・クラスもこのパッケージに含まれ、Oracleの拡張型と他の型との相互変換などが可能となっています。

注意:
名前がoracleで始まるパッケージには、Oracle固有のSQLJ機能が実装されています。

間接的に使用可能なパッケージ

SQLJで内部的に使用されるクラスを含むパッケージを次に示します。

- sqlj.runtime.profile
このパッケージには、SQLJプロファイルを定義するインタフェースおよび抽象クラスが含まれています(適用対象はISO標準コード生成のみ)。たとえば、EntryInfoクラスやTypeInfoクラスなどが含まれています。プロファイル内の各エントリは、EntryInfoオブジェクトで記述されます(このオブジェクトでは、プロファイルのエントリと、アプリケーション内のSQL操作が対応付けられます)。プロファイルのエントリ内の各パラメータは、TypeInfoオブジェクトで記述されます。

このパッケージのインタフェースおよびクラスは、sqlj.runtime.profile.refパッケージ内のクラスによって実装されます。

- sqlj.runtime.profile.ref
このパッケージには、sqlj.runtime.profileパッケージのインタフェースおよび抽象クラスを実装するクラスが含まれており、これらのクラスは、プロファイル定義時にSQLJトランスレータによって内部的に使用されます(ISO標準コード生成の場合のみ)。また、デフォルトのJDBCベースのランタイムの実装にも使用されます。

- sqlj.runtime.error
このパッケージは、SQLJ内部で使用されます。このパッケージには、SQLJトランスレータによって生成される一般的な(Oracle固有ではない)エラー・メッセージのリソース・ファイルが含まれています。

- oracle.sqlj.runtime.error
このパッケージは、SQLJ内部で使用されます。このパッケージには、SQLJトランスレータによって生成されるOracle固有のエラー・メッセージのリソース・ファイルが含まれています。

ランタイム・エラーの分類

ランタイム・エラーは、次のいずれかによって生成されます。

- SQLJランタイム

- JDBCドライバ

- RDBMS

いずれの場合も、SQL例外が、java.sql.SQLExceptionクラスまたはsqlj.runtime.SQLNullExceptionなどのサブクラスのインスタンスとして生成されます。

エラーの発生元によっては、getSQLState()、getErrorCode()およびgetMessage()の各メソッドを使用して、例外から有用な情報を取得できることがあります。たとえば、SQLJエラーには、有用なSQLの状態とメッセージが含まれています。

関連項目:
「SQLの状態およびエラー・コードの取出し」

実行時にOracle JDBCドライバまたはRDBMSでエラーが発生した場合は、メッセージの接頭辞を確認して、次の各マニュアルを参照してください。

- JDBCエラーについては、『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

- RDBMSエラーについては、Oracleエラー・メッセージのドキュメント(「関連ドキュメント」を参照)を参照してください。

トランスレータおよびランタイムでのグローバリゼーション・サポート

Oracle SQLJ実装では、グローバリゼーション・サポートのためにJavaの組込み機能が使用されます。ここでは、次の内容について説明します。

- SQLJにおけるグローバリゼーション・サポートとネイティブ文字エンコーディングの基本事項。文字エンコーディングおよび言語サポートが、Oracle実装でどのように実装されているかを説明します。

- SQLJコマンドラインでOracleのグローバリゼーション・サポート構成の調整に使用できるオプション。

- 拡張Oracleグローバリゼーション・サポート。

- グローバリゼーション・サポートのためのSQLJ外部での関連操作。

注意:
ここでは、Oracleのグローバリゼーション・サポートについての知識があることを前提としています。特に、文字エンコーディングおよびロケールについての知識が必要です。詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。

ここでは、次の項目について説明します。

- 文字エンコーディングと言語サポート

- SQLJおよびJavaの文字エンコーディングと言語サポートの設定

- SQLJ拡張グローバリゼーション・サポート

- SQLJ外部でのグローバリゼーション・サポート用の操作

文字エンコーディングと言語サポート

SQLJのグローバリゼーション・サポートは、次の2つに大別できます。

- 文字エンコーディング
文字エンコーディングは、3つに分類できます。

- SQLJ変換時のソース・ファイルの読取りおよび生成のための文字エンコーディング。

- SQLJ変換時のエラーおよびステータス・メッセージ生成のための文字エンコーディング。

- アプリケーション実行時のエラーおよびステータス・メッセージ生成のための文字エンコーディング。

- 言語サポート
SQLJ変換時またはSQLJ実行時に、SQLJからエラー・メッセージおよびステータス・メッセージが出力される場合に、どの言語のメッセージ・リストを使用するのかを指定します。

実行時のグローバリゼーション・サポートの機能は、データベース・キャラクタ・セットにある文字のみをSQLJソース・コードおよびSQL文字データに使用していることを想定しており、ユーザーは特に意識する必要がありません。SQL文字データとUnicodeとのマッピングは、透過的に行われます。

多言語対応のアプリケーションでは、次のいずれかを使用することをお薦めします。

- キャラクタ・セットでUnicodeをサポートしているデータベースの使用。

- データベース・キャラクタ・セットでUnicodeがサポートされていない場合でも、Unicodeをサポートする各国語キャラクタ・セットを指定します。(『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照。)通常、この場合は、SQLJ Unicode文字型を使用します(「SQLJ拡張グローバリゼーション・サポート」を参照)。

注意:

- SQLJトランスレータでは、Unicode 2.0およびJava Unicodeのエスケープ・シーケンスが完全にサポートされています。これに対しSQLJコマンドライン・ユーティリティでは、Unicodeエスケープ・シーケンスはサポートされていません。そのため、オペレーティング・システムでサポートされているネイティブの文字しか使用できません。コマンドライン・オプションにUnicodeエスケープ・シーケンスの入力が必要な場合は、かわりにSQLJプロパティ・ファイルに入力してください。プロパティ・ファイルではUnicodeエスケープ・シーケンスがサポートされています。

- 埋込みSQL操作で使用される文字と、データベースから読み書きする文字のエンコーディングおよび変換は、JDBCで直接処理されます。SQLJは、これらの処理に介在しません。ただし、変換時にオンラインのセマンティクス・チェックが有効になっていると、データベース・キャラクタ・セットと互換性のない文字がSQLデータ操作言語(DML)操作のテキストに含まれている場合は、警告メッセージが表示されます。

- JDBCのグローバリゼーション・サポート機能の詳細は、『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

文字エンコーディングの概要

SQLJでは、ソース・ファイルの文字エンコーディング設定に従って、次の2つが決定されます。

- .sqljおよび.javaの入力ファイル内のソース・コードの記述方法。これらのファイルは、SQLJトランスレータが解読できる必要があります。

- SQLJによって生成された.java出力ファイル内のソース・コードの表記方法。

SQLJでは、デフォルトでJVM file.encodingプロパティで指定されたエンコーディングを使用します。ソース・ファイルに他のエンコーディングを使用している場合は、適切に変換を行うためにSQLJにこのエンコーディングを指定する必要があります。

それには、SQLJの-encodingオプションを使用します。この-encodingの設定は、SQLJからコンパイラに渡され、コンパイラで.javaファイルの読取りに使用されます。ただし、SQLJの-compiler-encoding-flagが無効の場合を除きます。

注意:
ソース・ファイルの文字エンコーディングを指定するときに、file.encodingシステム・プロパティを変更しないでください。プラットフォームやオペレーティング・システムの環境によっては、Java操作の他の機能に影響し、一部の文字エンコーディングしか利用できなくなる場合があります。

変換時やエンド・ユーザーによるアプリケーション実行時のSQLJメッセージ出力にも、このシステム文字エンコーディング設定が使用されます。この文字エンコーディングは、SQLJの-encodingオプションとは関係なく、file.encodingプロパティに従って設定されます。

ソース・ファイルのエンコーディングを指定する場合は、-encodingオプションを使用すると、Java環境でサポートされる任意の文字エンコーディングを指定できます。Sun MicrosystemsのJDKを使用している場合、これらはnative2asciiのドキュメントにリストされており、次のWebサイトで参照できます。

http://java.sun.com/j2se/1.3/docs/tooldocs/solaris/native2ascii.html

Sun社のJDKでは、数多くの文字エンコーディングがサポートされています。たとえば、8859_1から8859_9(ISO Latin-1からISO Latin-9)、JIS(日本語)、SJIS(Shift-JIS、日本語)、UTF8などが含まれています。

文字エンコーディングでの注意事項

次の点に注意してください。

- メッセージとソース・ファイルのいずれの場合も、使用している文字エンコーディングで表現できない文字は、Java Unicodeエスケープ・シーケンスで表現されます。その形式は、\uHHHH(Hは16進数)です。

- 変換時の.sqljソース・ファイルの読込みと処理で表示されるエラー・メッセージには、入力文字エンコーディング中の(バイト位置ではなく)文字位置により、ソースの位置が示されます。

- 文字エンコーディング設定は、SQLJ -encodingオプションまたはJava file.encodingのどちらで設定したかにはかかわらず、Javaプロパティ・ファイル(sqlj.propertiesやconnect.propertiesなど)には適用されません。プロパティ・ファイルでは、常に8859_1エンコーディングを使用します。これは、特別なSQLJの機能ということではなく、一般的なJavaの機能です。ただし、Unicodeのエスケープ・シーケンスなら、プロパティ・ファイルで使用できます。エスケープ・シーケンスを決める際は、native2asciiユーティリティを使用することをお薦めします。

関連項目:
「native2asciiによるソース・ファイルの文字エンコーディングの変換」

言語サポートの概要

SQLJのエラーおよびステータス・レポートでは、変換時または実行時に、JVMのuser.languageプロパティのJavaロケール設定を使用します。通常、ユーザーはこの設定を変更する必要はありません。

言語サポートは、キー/値ペアを使用したメッセージ・リソースを使用して実装されます。たとえば、英語の「OkKey」というキーと「Okay」という値は、ドイツ語の「OkKey」と「Gut」に相当します。使用するメッセージ・リソースは、ロケール設定の値で決定されます。

SQLJでサポートされているロケール設定は、en(英語)、de(ドイツ語)、fr(フランス語)およびja(日本語)です。

注意:
Javaのロケール設定では、言語拡張の他にも、国拡張およびバリアント拡張がサポートされています。たとえば、ErrorMessages_de_CH_var1について考えてみます。CHは、ドイツ語の国拡張であるスイスを示します。var1は追加バリアントです。ただし、現在SQLJでサポートされているのは言語拡張(この例ではde)のみで、国拡張およびバリアント拡張は無視されます。

SQLJおよびJavaの文字エンコーディングと言語サポートの設定

Oracle SQLJ実装では、次の設定を行う構文が提供されています。

- SQLJトランスレータおよびJavaコンパイラで、ソース・コードの表示に使用される文字エンコーディング
SQLJの-encodingオプションを使用します。

- SQLJのトランスレータおよびランタイムで、エラー・メッセージやステータス・メッセージの表示に使用される文字エンコーディング
SQLJの接頭辞-Jを使用して、Javaのfile.encodingプロパティを設定します。

- SQLJのトランスレータおよびランタイムで、エラー・メッセージやステータス・メッセージの表示に使用されるロケール
SQLJの接頭辞-Jを使用して、Javaのuser.languageプロパティを設定します。

ソース・コードの文字エンコーディングの設定

SQLJの-encodingオプションを使用して、トランスレータで読み込まれる.sqljファイル、トランスレータで生成される.javaファイル、コンパイラで読み込まれる.javaファイルの表現に使用されている文字エンコーディングを指定します。オプション設定は、SQLJの-compiler-encoding-flagがオフになっていなければ、SQLJによってコンパイラに渡されます。

このオプションは、コマンドラインで設定するか、または次の例のように環境変数SQLJ_OPTIONSを使用して設定します。

-encoding=SJIS

次のように、SQLJプロパティ・ファイルで設定することもできます。

sqlj.encoding=SJIS

エンコーディングのオプションが設定されていない場合、トランスレータとコンパイラでは、JVMのfile.encodingプロパティで指定されたエンコーディングが使用されます。これは、SQLJコマンドラインからも設定できます。

関連項目:
「入力および出力ソース・ファイルの文字エンコーディング(-encoding)」および「コンパイラが使用する文字エンコーディング(-compiler-encoding-flag)」

注意:
-encodingオプションを常に同じ値に設定する場合は、2番目の例のようにプロパティ・ファイルで設定します。

SQLJメッセージの文字エンコーディングとロケールの設定

変換時と実行時に生成されるSQLJのエラー・メッセージおよびステータス・メッセージの文字エンコーディングおよびロケールは、Javaのfile.encodingおよびuser.languageプロパティで指定します。通常は必要ありませんが、SQLJの-J接頭辞を使用して、これらのJVMプロパティや他のJVMプロパティをSQLJコマンドラインで設定できます。この接頭辞の付いたオプションは、JVMに渡されます。

文字エンコーディングは、次のように設定します。この例では、日本語の文字エンコーディングであるShift-JISが設定されています。

-J-Dfile.encoding=SJIS

注意:
プラットフォームやオペレーティング・システムの環境によっては、一部の文字エンコーディングしか利用できない場合があります。

ロケールは、次のように設定します。(この例では、日本語が設定されています。)

-J-Duser.language=ja

-J接頭辞は、コマンドラインまたは環境変数SQLJ_OPTIONSでのみ使用できます。プロパティ・ファイルでは使用できません(プロパティ・ファイルは、JVMの起動後に読み取られるためです)。

注意:

- file.encoding、user.languageなどのJavaプロパティを常に同じ値に設定する場合は、環境変数SQLJ_OPTIONSに-Jを設定しておきます。このように設定すると、コマンドラインで何度も同じ値を指定する必要がありません。この構文は、基本的にコマンドラインの構文と同じです。詳細は、「環境変数SQLJ_OPTIONSによるオプションの設定」を参照してください。

- SQLJの-encodingオプションが設定されていない場合は、file.encodingの設定がソース・ファイル、エラー・メッセージおよびステータス・メッセージに適用されます。

- file.encodingプロパティを変更すると、予測できないところでJava操作が影響される場合があります。新規に設定する場合は、オペレーティング・システムとの互換性に注意する必要があります。

関連項目:
「コマンドラインの構文と処理」および「Java Virtual Machine(JVM)に渡すオプション(-J)」

SQLJコマンドラインの例: 文字エンコーディングとロケールの設定

次は、JVMのfile.encodingおよびuser.languageが設定された完全なSQLJコマンドラインの例です。

% sqlj -encoding=8859_1 -J-Dfile.encoding=SJIS -J-Duser.language=ja Foo.sqlj

この例では、SQLJの-encodingオプションを使用して、SQLJ変換時のソース・コード表示に8859_1 (Latin-1)を指定しています。このエンコーディングは、.sqlj入力ファイルの読取り時と.java出力ファイルの生成時に、トランスレータによって使用されます。その後、このエンコーディング設定がJavaコンパイラに渡されて、生成された.javaファイルの読取り時に使用されます。-encodingオプションが指定されていると、このオプションはJavaコンパイラに渡されます(ただし、SQLJの-compiler-encoding-flagが無効に設定されている場合を除きます)。

Foo.sqljの変換時にSQLJトランスレータによって出力されるエラー・メッセージおよびステータス・メッセージには、文字エンコーディングとしてSJIS、ロケールとしてjaが使用されます。

SQLJ拡張グローバリゼーション・サポート

Oracle SQLJ実装には、既存の文字およびストリーム型から導出されたJava型(Unicode文字型)のサポートが含まれています。この型では、グローバリゼーション向けに期待される使用方法が伝達されます。SQLJでは、グローバリゼーション・サポートを目的とするJDBC文または結果セットのメソッドを直接使用することはできません。これらのメソッドの詳細は、『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。

データベースがネイティブにUnicodeをサポートする場合は、「グローバリゼーション・サポートのためのJava型」で説明する型は不要です。この場合、グローバリゼーション・サポートが透過的に処理されます。ネイティブにUnicodeをサポートしていないが、データベースにUnicodeをサポートする各国語キャラクタ・セットがある場合は、通常これらの型(各国語キャラクタ・セットを使用する列の型)を使用します。

グローバリゼーション・サポートのためのJava型

Oracle SQLJ実装では、グローバリゼーション・サポート用のJava型がいくつか用意されています。表9-3に、これらのグローバリゼーション・サポート型と、汎用のJDBCとSQLJの文字およびストリーム型の関係を示します。NString以外の各グローバリゼーション・サポート型は、JDBCまたはSQLJ型のサブクラスです。

表9-3 JDBC型およびSQLJ型とグローバリゼーション型

JDBC型およびSQLJ型

グローバリゼーション・サポート型

JDBC型:

oracle.sql.CHAR

oracle.sql.NCHAR

java.lang.String

oracle.sql.NString

oracle.sql.CLOB

oracle.sql.NCLOB

SQLJ型:

sqlj.runtime.CharacterStream

oracle.sqlj.runtime.NcharCharacterStream

sqlj.runtime.AsciiStream

(非推奨。CharacterStreamを使用)

oracle.sqlj.runtime.NcharAsciiStream

(非推奨。NcharCharacterStreamを使用)

sqlj.runtime.UnicodeStream

(非推奨。CharacterStreamを使用)

oracle.sqlj.runtime.NcharUnicodeStream

(非推奨。NcharCharacterStreamを使用)

アプリケーションで各国語文字列を処理する必要がある場合、各国語キャラクタ・セットの列との間の各国語文字列の受渡しには、対応する汎用型ではなく、グローバリゼーション・サポート型を使用します。

注意:

- すべてのグローバリゼーション・サポート型では、INおよびOUTパラメータの使用を自動的に登録する機能が追加されますが、JDBCまたはSQLJ型(コンストラクタなど)の使用方法は同じです。

- グローバリゼーション・サポート型の使用は、イテレータ列では不要です。基になるネットワーク・プロトコルで、基になる結果セット用に各国語文字が暗黙的にサポートされているためです。

NStringクラスの使用方法と注意事項

oracle.sql.CHARクラスおよびそのNCHARサブクラスは、データベース・キャラクタ・セットに関する明示的な知識が必要なコンストラクタのみを提供します。したがって、たいていの環境ではjava.lang.Stringのラッパーであるoracle.sql.NStringクラスの方が好ましい選択です。NStringクラスにはより簡単なコンストラクタがあり、各国語文字の使用形式が確実にJDBCドライバに登録されます。

次に主要なNStringメソッドを示します。

- NString(String): このコンストラクタでは、既存のStringインスタンスからNStringインスタンスが作成されます。

- String toString(): このメソッドでは、基になるStringインスタンスが戻されます。

- String getString(): このメソッドでも、基になるStringインスタンスが戻されます。

toString()メソッドによって、文字列連結式にNStringインスタンスを使用できます(たとえば、"a"+bの場合、bが文字列です)。CHARスーパークラスにあるgetString()メソッドは、一貫性のためにもサポートされています。さらに、Stringクラスのメンバー・メソッドは、NStringラッパー・クラスに引き継がれます。これによって、より簡潔なコードを記述できます。

SQLJアプリケーションの場合、Oracle Database 11g より前のバージョンでは、NString型のホスト変数を使用してNCHAR型の列をバインドする必要があります。たとえば、次のような表があるとします。

CREATE TABLE Tbl1 (
ColA  CHAR
NColB NCHAR
)

SQLJアプリケーションを介してこの表に行を挿入するには、次のようなコードを使用します。

...
String v_a = "\uFF5E";
NString v_nb = "\uFF5E";
#sql {INSERT INTO Tbl1 (ColA, NColB) VALUES (:v_a, :v_nb)};
...

Oracle Database 11g リリース1 (11.1)以上では、SQLJアプリケーションはString変数を使用してNCHAR列をバインドします。したがって、前述の例は次のように書き換えられます。

...
String v_a = "\uFF5E";
String v_nb = "\uFF5E";
#sql {INSERT INTO Tbl1 (ColA, NColB) VALUES (:v_a, :v_nb)};
...

ただし、Stringホスト変数を使用してNCHAR列をバインドする場合、次のように、SQLJトランスレータ・オプション-ncharconvを使用してSQLJファイルを変換する必要があります。

sqlj -ncharconv [-options] app.sqlj

前述のコマンドでは、options に他のSQLJオプションを指定できます。また、app.sqljはコードを含むSQLJファイルです。

このオプションを使用すると、文字型列(CHAR列またはNCHAR列)へのすべてのバインドに対してsetFormOfUseメソッドが生成されます。

注意:
-ncharconvオプションを指定してSQLJファイルをコンパイルすると、codegen=oracleの生成コードでsetFormOfUseメソッドが使用されます。codegen=isoの場合、このオプション情報は、バインドの実行時にSetFormOfUseを内部的に使用するOracle SQLJランタイムに渡されます。

SQLJアプリケーションでは、-ncharconvオプションを使用せずに、Stringホスト変数を使用してサーバーからデータを取得できます。これは、列型に関する情報がクライアント側でフェッチされ、JDBCによって該当する列の形式が内部的に設定されるためです。

注意:
-ncharconvオプションを使用する場合、データベース・キャラクタ・セット、各国語キャラクタ・セットおよび表内の文字型列の数によって、パフォーマンスが多少異なる場合があります。

関連項目:
「NCHARバインド(-ncharconv)」

グローバリゼーション・サポートの例

次の例では、NStringクラスの使用を説明しています。

- IN引数としてのNString
この例では、NStringインスタンスをデータベースへの入力パラメータとして使用します。

import oracle.sql.NString;
...
NString nc_name = new NString("Name with strange characters");
#sql { update PEOPLE
set city = :(new NString("\ufff2")), name = :nc_name
where num= :n };
...

- OUT引数としてのNString

この例では、NStringインスタンスをデータベースからの出力パラメータとして使用します。

import oracle.sql.NString;
...
NString nstr;
#sql { call foo(:out nstr) };
System.out.println("Result is: "+nstr);
// or, explicitly: System.out.println("Result is: "+nstr.toString());
...

- 結果セット列としてのNString
この例では、イテレータ列にNString型を使用します。このような使用方法は不要ですが、基になるネットワーク・プロトコルで各国語文字を暗黙的にサポートしているため特に問題とはなりません。またこの例では、NStringに引き継がれるStringメソッドの1つであるsubstring()の使用方法を示しています。

import oracle.sql.NString;
import oracle.sql.NCLOB;
...
#sql iterator NIter(NString title, NCLOB article);

NIter nit;
#sql nit = { SELECT article, title FROM page_table };
while (nit.next())
{
System.out.println("<TITLE>"+nit.title()+"</TITLE>");
...
nit.article().substring(0, 1000); ...
}

注意:
前述の例でNString型ではなくてNCHAR型を使用するには、次のように変更する必要があります。

- 適切なNCHARコンストラクタを使用します。次のように、NCHARコンストラクタはCHARコンストラクタを反映しています。

NCHAR(String str, oracle.sql.CharacterSet charset)

- NStringインスタンスからその基になるStringを取得するには、toString()またはgetString()のいずれかを使用できますが、NCHARインスタンスの場合、getString()メソッドを使用する必要があります。NString型を使用する場合、文字列連結のためにtoString()メソッドが自動的に使用されます。「OUT引数としてのNString」を参照してください。

SQLJ外部でのグローバリゼーション・サポート用の操作

ここでは、SQLJ外でのOracleグローバリゼーション・サポートの設定の操作方法について説明します。

アプリケーションの実行時に行う文字エンコーディングとロケールの設定

通常のJavaアプリケーションと同じように、JVMを起動してSQLJアプリケーションを実行する際に、file.encodingやuser.languageなどのJVMのプロパティを直接指定できます。これにより、アプリケーション実行時に出力されるメッセージに使用される文字エンコーディングおよびロケールが決定します。

たとえば、次のように指定します。

% java -Dfile.encoding=SJIS -Duser.language=ja Foo

この場合、文字エンコーディングにはSJISが使用され、ロケールには日本語が使用されます。

APIによるJavaプロパティの設定

JavaコードでJavaプロパティの値を確認するには、java.lang.System.getProperty()メソッドを使用し、該当のプロパティを指定します。次に例を示します。

public class Settings
{
public static void main (String[] args)
{
System.out.println("Encoding: " + System.getProperty("file.encoding")
+ ", Language: " + System.getProperty("user.language"));
}
}

このコードをコンパイルすると、スタンドアロン・ユーティリティとして実行できます。

すべてのプロパティの値を戻り値とするgetProperties()メソッドもあります。ただし、サーバー側で実行されるコード中にこのメソッドを使用すると、セキュリティの例外が生成されます。

native2asciiによるソース・ファイルの文字エンコーディングの変換

Sun社のJDKを使用している場合は、SQLJを使用せずにソース・コードの文字エンコーディングを変換できます。native2asciiというユーティリティを使用すると、ネイティブな文字エンコーディングのソースが、Unicodeエスケープ・シーケンスを使用した7ビットASCIIに変換されます。

注意:
native2asciiで生成されたソース・コードをSQLJで変換する場合は、SQLJを起動する側のJVMのfile.encodingに、7ビットASCIIのスーパーセットをサポートする文字エンコーディングを設定するようにしてください。EBCDICまたはUnicodeの場合は、この設定は必要ありません。

native2asciiを実行するには、次のように指定します。

% native2ascii <options> <inputfile> <outputfile>

入力ファイルまたは出力ファイルが指定されていない場合は、標準入力または標準出力が使用されます。このコマンドでは、次の2つのオプションを使用できます。

- -reverse(逆変換を行います。つまり、Latin-1またはUnicodeからネイティブ・コードに変換します。)

- -encoding <encoding>

次に例を示します。

% native2ascii -encoding SJIS Foo.sqlj Temp.sqlj

詳細は次のWebサイトを参照してください。

http://java.sun.com/j2se/1.3/docs/tooldocs/solaris/native2ascii.html

10 パフォーマンスとデバッグ

この章では、SQLJアプリケーションのパフォーマンスを向上させ、SQLJのソース・コードを実行時にデバッグするための機能、ユーティリティおよびヒントについて説明します。内容は次のとおりです。

- パフォーマンス強化の機能

- SQLJのデバッグ機能

- Oracle Performance MonitoringのSQLJサポート

パフォーマンス強化の機能

Oracle SQLJ実装には、データへのアクセスを効率化することによって、パフォーマンスを向上させるための機能が提供されています。具体的には、次の機能があります。

- 行プリフェッチ

- 文のキャッシング

- バッチ更新機能

- 列の定義

- パラメータ・サイズの定義

関連項目:
『Oracle Database JDBC開発者ガイドおよびリファレンス』

デフォルトのOracle固有コード生成の使用は、アプリケーションにとってメリットがあります。生成されたコードはOracle Java Database Connectivity(JDBC)ドライバへの直接コールによって最適化されるため、(JDBCへのコール前の)SQLJランタイムへの中間コールのオーバーヘッドが削減できます。

関連項目:
「Oracle固有コード生成(プロファイルなし)」

注意:
行のセットを値の配列にフェッチするバッチ・フェッチは、Oracle SQLJ実装でサポートされていません。ただし、Oracle行プリフェッチを使用すると、バッチ・フェッチのメリットをいくつか得られます。

前述したSQLJパフォーマンス強化に加えて、SQLJプログラムではSQL操作に関するオプティマイザ・ヒントを使用できます。同様に、他のOracle SQL操作に関するヒントも使用できます。

Oracle SQL実装では、「/*+」や「--+」で始まるコメント表記法でOracle SQLオプティマイザにヒントを渡すことによって、SQL文をチューニングすることができます。SQLJトランスレータは、これらのオプティマイザ・ヒントを認識してそれらをサポートし、実行時にSQL文の一部として渡します。

Oracle Database 11g のSQLの最適化のための拡張機能を使用すると、SQLJストアド・ファンクションやその他のストアド・ファンクションのコストおよび選択性の情報を定義できます。オプティマイザを使用すると、SQL実行時に、ストアド・ファンクションのコスト関数および選択関数の起動、他の実行方法の評価、ならびに最も効率的な方法の選択ができます。

関連項目:
詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

コード中にOracleパフォーマンス拡張機能を使用する場合は、次の要件が伴うので注意してください。

- Oracle JDBCドライバを使用する必要があります。

- デフォルトのOracle固有コード生成を使用するか、プロファイルを適切にカスタマイズします。
ISO標準コード生成の場合は、デフォルトのカスタマイザoracle.sqlj.runtime.util.OraCustomizerをお薦めします。

- アプリケーションの実行時にOracle SQLJランタイムを使用します。

Oracle SQLJランタイムとOracle JDBCドライバは、Oracleカスタマイザを使用してプロファイルをカスタマイズするときは常にアプリケーションで必要となるもので、Oracle拡張機能をコード中に使用しない場合にもこのことが当てはまります。

行プリフェッチ

標準のJDBCは、問合せ結果を1行ずつ受け取り、行ごとにデータベースへの別個のラウンドトリップを必要とします。行プリフェッチを使用すると、一度に複数行の結果を効率的に受け取ることができます。

ExecutionContextインスタンスのsetFetchSize()メソッドを使用して、SELECT文(特定のExecutionContextインスタンスを使用するSQLJ文用)を実行するたびにプリフェッチされる行数を設定します。

ExecutionContextインスタンスのgetFetchSize()メソッドは、現行のプリフェッチ・サイズをint値として戻します。

次の例では、デフォルトの接続コンテキスト・インスタンスのデフォルトの実行コンテキスト・インスタンスを取得し、setFetchSize()メソッドをコールして、プリフェッチ・サイズを20に設定します。

DefaultContext.getDefaultContext().getExecutionContext().setFetchSize(20);

JDBC Application Programming Interface(API)を使用して、基になるOracleConnectionオブジェクトに直接プリフェッチ・サイズを設定することも可能ですが、SQLJ内ではこれは設定できません。

特定の接続コンテキストのインスタンスを使用した問合せに対して、プリフェッチする行数を指定するには、基になるJDBC接続を使用してOracleConnectionインスタンスにキャストします。次の例は、デフォルト接続で、プリフェッチする行数を20に設定しています。

((OracleConnection)DefaultContext.getDefaultContext().getConnection()).setDefaultRowPrefetch(20);

また、SQLJ接続コンテキストで設定されたプリフェッチ・サイズが、基になるJDBC接続で設定されたプリフェッチ・サイズより優先されることに注意してください。

プリフェッチの値は、接続コンテキストごとに設定する必要があります。たとえば、宣言された接続コンテキスト・クラスのctxというインスタンスに対しては、プリフェッチする行数を次のように設定します。

ctx.getExecutionContext().setFetchSize(20);

プリフェッチできる行数に制限はありません。JDBCでのデフォルト値は10で、この値はSQLJに継承されます。この値は通常の環境では効果的ですが、受け取る行数が多い場合はこの値を大きくできます。

文のキャッシング

SQLJには文のキャッシング機能が用意されており、繰り返し使用される実行文(ループ内や、繰り返しコールされるメソッド内などの実行文)を保存することでパフォーマンスが向上します。再実行の前に文がキャッシュされると、コードの再解析(クライアントまたはサーバーで)、文オブジェクトの再作成、およびパラメータ・サイズの定義の再計算が不要になります。この機能がない場合、繰り返し使用される文を、クライアント上で(おそらくサーバー内でも)再解析する必要があります(この再解析の必要性は、文の再検出時に、その文がサーバー側のSQLキャッシュでまだ使用可能かどうかによります)。

Oracle固有コード生成の場合、SQLJの文キャッシングはOracle JDBCドライバに依存し、このドライバは、JDBCの明示的なキャッシング・メカニズムを使用します。後述のような相互依存性がありますが、この明示的なキャッシング・メカニズムは、JDBCの暗黙的なキャッシング・メカニズムとは異なります。Oracle固有のコードでは、文のキャッシングは接続メソッドを介して制御されます。

関連項目:
『Oracle Database JDBC開発者ガイドおよびリファレンス』

ISOコード生成の場合、SQLJには、SQLJランタイムの機能を介したSQLJ自体の文キャッシング・メカニズムがあります。ISOコードでは、文のキャッシングはOracleカスタマイザのstmtcacheオプションを介して制御されます。

注意:
Oracle固有コード生成の場合は、明示的なキャッシングがSQLJのAPIを介して操作できる唯一の文キャッシング・メカニズムです。このマニュアルでは、このメカニズムをSQLJ/明示的な文キャッシングと呼びます。

Oracle Database 11g では、JDBC接続が接続コンテキストによって作成される場合、デフォルトの文キャッシュ・サイズが5に設定されます。接続コンテキストが既存の使用可能なJDBC接続またはデータ・ソースを使用して作成された場合、文のキャッシュ・サイズはそのJDBC接続またはデータ・ソースのキャッシュ・サイズに設定されます。

文キャッシングのための接続コンテキスト・メソッド(Oracle固有コードの場合)

Oracle固有コード生成を使用する場合(SQLJトランスレータのデフォルトの-codegen=oracle設定を使用する場合)は、文キャッシング機能に接続コンテキスト・メソッドを使用します。文のキャッシュ・サイズに0(ゼロ)よりも大きい値を指定することによって、SQLJ/明示的な文キャッシングが有効になります。デフォルトの場合、キャッシュ・サイズが5(5文)で有効となります。

次のOracle固有(非標準)staticメソッドがsqlj.runtime.ref.DefaultContextクラスに追加されました。また、宣言した接続コンテキスト・クラスには、これらのメソッドが含まれています。

- static void setDefaultStmtCacheSize(int)
デフォルトの文キャッシュ・サイズをすべての接続コンテキストに設定します。これは、このメソッドをコールしたクラスだけでなく、これ以降に作成されるすべての接続コンテキスト・クラスのインスタンスに使用される、初期の文キャッシュ・サイズになります。このメソッド・コールは、既存の接続コンテキスト・インスタンスには影響しません。

注意:
setDefaultStmtCacheSize(int)は、SQLJ接続コンテキストを使用して作成した接続の文キャッシュ・サイズにのみ影響します。JDBC接続を使用して作成した接続の文キャッシュ・サイズには影響しません。
次の2つのコード例を考えてみます。

例1:

...
MyContext.setDefaultStmtCacheSize(10);
OracleConnection conn = DriverManager.getConnection(url, user, passwd);
myctx = new MyContext(conn);

例2:

...
MyContext.setDefaultStmtCacheSize(10);
myctx = new MyContext(url, user, passwd,true);

前述の2つの例では、2番目の例の文キャッシュ・サイズのみが10に設定されます。1番目の例では、JDBC仕様のDriverManagerインタフェースのgetConnectionメソッドを使用して接続が作成されたため、この接続に対応する文キャッシュ・サイズは影響を受けません。

- static int getDefaultStmtCacheSize()
接続コンテキストに対する現行のデフォルトの文キャッシュ・サイズを取得します。

また、次のOracle固有インスタンス・メソッドがDefaultContextクラスに追加されました。これらのメソッドは、他のどの接続コンテキスト・クラスにも含まれています。

- void setStmtCacheSize(int) throws java.sql.SQLException
特定の接続コンテキスト・インスタンスの基になる接続に文キャッシュ・サイズを設定します(デフォルトを上書きします)。

注意:
SQLJ/明示的なキャッシングがすでに無効な場合は、サイズを0(ゼロ)に設定すると無効のままになります。すでに有効な場合にサイズを0(ゼロ)に設定すると、有効のままですが機能は停止します。

- int getStmtCacheSize()
SQLJ/明示的な文キャッシングが、接続コンテキストの基になる接続に対して有効かどうかを検証します。有効な場合は、現行の文キャッシュ・サイズを戻します。また、次の整定数のいずれかを戻すこともできます。

static int STMT_CACHE_NOT_ENABLED
static int STMT_CACHE_EXCEPTION

getStmtCacheSize()コールでSQL例外が発生する可能性があります。ただし、下位互換性のため、このメソッドでは例外を直接スローすることはありません。例外が発生した場合、このメソッドは定数STMT_CACHE_EXCEPTIONを戻します。この場合は、getStmtCacheException()メソッドをコールして、例外の内容を確認できます。

SQLJ/明示的なキャッシングが無効に設定されている場合にgetStmtCacheSize()をコールすると、定数STMT_CACHE_NOT_ENABLEDが戻されます。これはキャッシュ・サイズが0(ゼロ)であることとは区別されます。0(ゼロ)のキャッシュ・サイズでSQLJ/明示的なキャッシングを有効にする(役には立ちませんが)ことは、技術的には可能です。

- java.sql.Exception getStmtCacheException()
文キャッシングの例外があるかどうかを確認します。このメソッドの使用方法は2種類あります。

- getStmtCacheSize()コールでSTMT_CACHE_EXCEPTIONが戻される場合にコールします。

- 文のキャッシングを使用するための接続コンテキスト・インスタンスを作成する場合は、必ずこのメソッドをコールします。これは、接続コンテキスト・インスタンスの作成時に、常に文キャッシュ・サイズに関して発生する自動操作のためのコールです。接続コンテキスト・インスタンスに対して文のキャッシングを行う場合は、インスタンスの作成後にgetStmtCacheException()をコールして、問題がなかったことを確認します。

文キャッシングの有効化と無効化(Oracle固有コードの場合)

Oracle固有コードでは、前に実行された文を繰り返すと、0(ゼロ)でない文キャッシュ・サイズによってSQLJ/明示的なキャッシングが有効になります。デフォルト・サイズが5のため、文のキャッシングがデフォルトで有効になっています。

SQLJ/明示的な文キャッシングは、SQLJのAPIを介して明示的に無効にすることはできませんが、文キャッシュ・サイズを0 (ゼロ)に設定することで、事実上無効(機能停止)にできます。この場合、接続コンテキストのgetStmtCacheSize()メソッドは、STMT_CACHE_NOT_ENABLEDではなく0 (ゼロ)を戻す場合があります。

SQLJ/明示的な文キャッシングまたはJDBCの暗黙的なキャッシングは、JDBC接続APIを介して明示的に無効にできます。SQLJ/明示的なキャッシングおよびJDBCの暗黙的なキャッシングでは、同じキャッシュ・サイズを使用していることが、明示的に無効にする理由の一部である場合があります。次のメソッドは、OracleConnectionクラスを介して使用できます。

- void setExplicitCachingEnabled(boolean)

- boolean getExplicitCachingEnabled()

- void setImplicitCachingEnabled(boolean)

- boolean getImplicitCachingEnabled()

SQLJ接続コンテキスト・インスタンス内からOracleConnectionインスタンスを取得すると、これらのメソッドにアクセスできます。

関連項目:
「SQLJ接続コンテキストとJDBC接続の連係動作」

注意:
SQLJでは、JDBCの暗黙的なキャッシングはデフォルトで無効です。これはsetImplicitCachingEnabled()メソッドを介して明示的に有効にしないかぎり無効のままです。

SQLJ/明示的なキャッシングとJDBCの暗黙的なキャッシング間の主な相互作用

Oracle固有コードでの文のキャッシングに関して、このマニュアルでは、JDBCの暗黙的なキャッシングではなく、SQLJ/明示的なキャッシングに説明の重点をおいています。アプリケーションでJDBCコードを使用しない場合は、SQLJ/明示的なキャッシングが唯一の適切な文のキャッシングです。ただし、SQLJとJDBCコードの両方をアプリケーションで使用する環境では、暗黙的なキャッシングも使用する可能性があります。

SQLJ/明示的なキャッシングとJDBCの暗黙的なキャッシングは、相互に関係なく有効です。さらに、ユーザーはSQLJを介して暗黙的なキャッシュにアクセスすることはできません。ただし、この2種類のキャッシング間には、同じキャッシュ・サイズを共有するという主な相互作用があります。たとえば、文のキャッシュ・サイズが5の場合は、SQLJ/明示的なキャッシングと暗黙的なキャッシングの組合せで最大5個の文をキャッシュできます。

ここで重要な点は、キャッシュ・サイズを0(ゼロ)に設定して、SQLJ/明示的な文キャッシングを無効に設定すると、暗黙的なキャッシングも無効になることです。

また、SQLJ/明示的なキャッシングが無効な場合に、キャッシュ・サイズを0(ゼロ)より大きい値に変更するとそのキャッシングが有効になりますが、これは暗黙的なキャッシングの有効化には影響を与えません。

文キャッシングに対するJDBCサポート(ISOコードの場合)

SQLJトランスレータに-codegen=isoを設定して指定されたISO標準コード生成の場合、文キャッシングは標準SQLJ機能であり、特定のJDBCドライバは不要です。ただし、sqlj.runtime.profile.ref.ClientDataSupportインタフェースを実装したドライバを使用すると、キャッシングの堅牢性が向上します。Oracle Database 11g JDBCドライバには、このインタフェースが実装され、次の機能が提供されています。

- アプリケーション全体で静的キャッシュを1つのみ使用するのではなく、データベース接続のたびに別個のキャッシュを使用できます。

- 同じ接続からの複数の接続コンテキスト・クラスのインスタンスの間でキャッシュされた文を共有できます。

キャッシュを1つ使用した場合、ClientDataSupportが実装されていない汎用JDBCドライバの場合と同様、一方の接続で文を実行したために、もう一方の接続で実行した文がフラッシュされてしまうことがあります(文のキャッシュ・サイズ、つまりキャッシングの許容される文の上限の数が超過した場合)。

文のキャッシュ・サイズに対応したOracleカスタマイザ・オプション(ISOコードの場合)

ISO標準コード生成の場合、文のキャッシングはOracleカスタマイザの使用時にアプリケーション内で有効です。デフォルトのキャッシュ・サイズは5(Oracle固有コードと同じデフォルトのサイズ)です。文のキャッシングは通常、Oracle SQLJ変換の一部として実行されます。

必要に応じて文のキャッシュ・サイズを変更したり、キャッシュ・サイズを0(ゼロ)に設定して文のキャッシングを無効にするには、Oracleカスタマイザのstmtcacheオプションを使用できます。-P-Cstmtcache=n のように設定します(n は整数)。

関連項目:
「Oracleカスタマイザ用の文のキャッシュ・サイズ・オプション(stmtcache)」

接続コンテキスト・クラスをいくつか使用するに伴ってプロファイルもいくつか使用する場合は、プロファイルごとに個別にSQLJ(事実上はカスタマイザ)を実行すると、それぞれの文のキャッシュ・サイズを個別に設定できます。

実行時、文のキャッシュ・サイズは、適切なSQLJプロファイルによって接続に対して決定されます。このSQLJプロファイルとは、この接続でインスタンス化された最初の接続コンテキスト・クラスに対応するプロファイルのことです。文のキャッシュ・サイズの設定値は、プロファイルのカスタマイズ時に設定したOracleカスタマイザのstmtcacheオプションの値に応じて決まります。接続時に最初の文が実行されたとき、その接続に使用する実行時の文のキャッシュ・サイズが設定されます。

文のキャッシングに関するその他の動作

SQLJ接続コンテキスト・オブジェクトがインスタンス化されるときに、基になるJDBC接続の文キャッシュ・サイズが接続コンテキスト・クラスのデフォルトのサイズよりも小さい場合、SQLJランタイムは、JDBCの文キャッシュ・サイズを接続コンテキストのデフォルト値まで増やそうとします。この操作は、ISOコード生成でも発生し、処理中の明示的な文キャッシングを有効にしますが、これは実際にはISOコードの例とは関連がありません。

反対に、実際のJDBC文キャッシュ・サイズが大きい場合は、SQLJランタイムはキャッシュ・サイズを変更しません。SQLJランタイムでは、SQLJ接続コンテキスト・インスタンスを作成すると、デフォルトのサイズ・セットに対する実際のJDBCキャッシュ・サイズを必ず確認します。

これらのメソッドは、同一の基になる静的フィールドを変更または報告するので、メソッドが発行されたコンテキスト・クラスにかかわらず、同じ効果があることに注意します。

次の接続コンテキスト・クラス宣言を例として挙げます。

#sql context CtxtA;
#sql context CtxtB;

この場合、次の3つのコード命令には、それ以降に新しいSQLJ接続コンテキスト・インスタンスが作成される際に、SQLJ/明示的な文キャッシングの有効化が試行されないという効果があります。

sqlj.runtime.ref.DefaultContext.setDefaultStmtCacheSize(0);

CtxtA.setDefaultStmtCacheSize(0);

CtxtB.setDefaultStmtCacheSize(0);

重要:
SQLJ接続コンテキスト・インスタンスが基になるJDBCのプールされた接続上に作成される場合は、SQLJはJDBC文キャッシュ・サイズを変更できません。Oracle固有コードの場合、発生した例外は接続コンテキストのgetStmtCacheException()メソッドを介して取得できます。この場合、必要なJDBC文キャッシュ・サイズを基になる物理接続に明示的に設定する必要があります。データ・ソースの場合、キャッシュ・サイズは、ベンダー固有のデータ・ソース属性を介して設定されます。

SQLJ/明示的なキャッシングとJDBCの暗黙的なキャッシングの機能には、異なるセマンティクスと動作があります。前述のように、SQLJ文キャッシングは、ループや同じメソッドへ繰り返して実行されるコールなど、繰り返し使用される単一の文にのみ適用されます。次に示す例で確認してください。

...
#sql { same SQL operaton }; // occurrence #1
...
Java code
...
#sql { same SQL operaton }; // occurrence #2
...
Java code
...
#sql { same SQL operaton }; // occurrence #3
...

3つのSQL操作は、空白も含めてすべて同じであると想定します。

SQLJキャッシングでは、これら3つの同じSQL操作は、それぞれ異なる文であると考えられています。それらは、キャッシュ内で3つの別々のスロットを占有します。ただし、JDBCの暗黙的なキャッシングでは、3つすべてに1つのキャッシュ・スロットを使用するので、これらを同じ文として認識します。文は、2番目と3番目の文で再利用されます。

文キャッシングの制限事項と考慮事項

文のキャッシュを使用すると、キャッシュ・サイズが1の場合でも、たいていのSQLJアプリケーションではパフォーマンスが向上します。ただしこの場合は、次の留意点があります。

- 各文が1回しか実行されない場合は、メリットがあるわけではありません。

- 複数回実行した文を使用して1回実行した文をインターリーブするのは避けてください。実行回数が1回のみである文を使用すると、文のキャッシュ中に不必要な領域がとられてしまうため、キャッシュ・サイズが上限を超える原因となります。ISOコード生成を使用している場合は、前述の方法のかわりに、実行回数が1回のみである文に対して個別の接続コンテキスト・クラスを使用して、この接続コンテキスト・クラスの文キャッシングを無効にできます。

- SQL操作が同一でも別々の文は、別々の文と同様に扱われます。処理もキャッシングも別々に実行されます。別々の文を使用するかわりに、SQL操作を1つのメソッドに記述して、このメソッドを繰り返しコールする方法もあります。

- 文のキャッシュ・サイズは、慎重に選択してください。キャッシュ・サイズが小さすぎるとキャッシュが満杯になり、文が再実行されないうちにフラッシュしてしまいます。大きすぎる場合は、データベースやプログラムのリソースが使い果たされてしまう可能性があります。

文キャッシングに関する次の一般的な注意に従ってください。

- Oracle固有コード生成の場合、別々のSQLJ接続コンテキスト・インスタンスを使用して、別の文キャッシングを動作させることは、接続コンテキストで同一の基になるJDBC接続インスタンスを共有していると、うまくいきません。これは、Oracle固有コード生成の場合、SQLJはJDBC文キャッシュを使用するためです。

- Oracleアプリケーションでは、文のキャッシュ・サイズとアプリケーション(直接またはSQLJを使用)でオープンしているJDBC文の最大個数とを合計した数を、各セッションで利用できるカーソルの最大個数よりも少ない数とする必要があります。同時にオープンすることのできる文の最大個数は、カーソルの最大個数に基づいて決まるからです。

- 文のキャッシングを使用しても、通常は操作自体の実行セマンティクスは変わりませんが、場合によっては変わることもあります。たとえば、リソース解放時に例外をスローする文がある場合にキャッシュを使用すると、接続が終了するか、または文がキャッシュからフラッシュされる(キャッシュ・サイズが上限を超えるとき)まで、例外はスローされないことを意味します。

バッチ更新機能

バッチ更新機能(Sun MicrosystemsのJDBC 2.0の仕様でバッチ更新と呼ばれる)では、UPDATE、DELETEおよびINSERT文を使用可能です。これらの文は、バッチ可能で互換性があるため、1つのバッチにまとめて、一括してデータベースに転送されて実行されるので、データベースへのラウンドトリップ回数が減ります。この機能は、JDBCおよびSQLJ仕様に含まれており、Oracle JDBCおよびSQLJ実装でサポートされています。通常、バッチ更新機能は、ループ内で繰り返し実行される操作に有効です。

SQLJのバッチ更新機能は、実行コンテキストの使用とつながりがあります。このバッチ更新機能は、実行コンテキストごとに有効化/無効化の個別指定が可能で、各実行コンテキストのインスタンスにはそのインスタンス自体のバッチが保持されます。

注意:
バッチ更新について、次の点に注意してください。

- デフォルトのOracle固有コード生成を使用するか、ISOコード生成の場合はアプリケーションをOracleカスタマイザでカスタマイズする必要があります。

- 自動コミット・モードは使用禁止にすることをお薦めします。これによって、バッチ実行時にエラーが発生した場合に、コミットする対象とロールバックする対象を制御できるようになります。

バッチ可能かつ互換性のある文

ある文を既存のバッチの文に追加できるかどうかは、次のような2つの基準によって決まります。

- バッチ可能かどうか。どんな場合にも、1つに一括できない文もあります。

- 既存のバッチの文との互換性がある文か。

SQLJの場合、次の種類の文をバッチで実行できます。

- UPDATE

- INSERT

- DELETE

ただし、UPDATE文やINSERT文にストリーム・ホスト式を1つ以上記述した場合は、バッチでは実行できません。

SQLJでは、同じ文の複数のインスタンス間でのみ互換性が確保されます。このことは、次のどちらかの場合に起こります。

- ループ内で文が繰り返し実行される場合

- メソッドで文が実行され、しかもそのメソッドが繰り返しコールされる場合

バッチ更新機能の有効化/無効化

SQLJのバッチ更新機能は、実行コンテキスト・インスタンスごとに個別に実行されます。各実行コンテキスト・インスタンスは、他の実行コンテキスト・インスタンスとは独立してバッチ更新機能を有効化することが可能で、しかも各インスタンスは、そのインスタンス自体のバッチが保持されます。

特定の実行コンテキスト・インスタンスに対してバッチ更新機能の有効化/無効化を指定するには、その実行コンテキスト・インスタンスのsetBatching()メソッドを使用します。このメソッドは、入力としてブール値をとります。

...
ExecutionContext ec = new ExecutionContext();
ec.setBatching(true);
...

または

...
ExecutionContext ec = new ExecutionContext();
ec.setBatching(false);
...

バッチ更新機能は、デフォルトでは無効になります。

注意:
既存の文のバッチは、setBatching()メソッドの処理対象にはなりません。バッチ更新の有効化/無効化には関係なく、既存のバッチについては実行や取消しが行われないようになっています。

ある実行コンテキストに対してバッチ更新機能が有効になっているかどうかを調べるには、その実行コンテキスト・インスタンスのisBatching()メソッドを使用します。

ExecutionContext ec = new ExecutionContext();
...
boolean batchingOn = ec.isBatching();

ただし、上に示した指定では、現在のバッチが未完了のままになっているかどうかは、提示されません。

明示的および暗黙的なバッチ実行

未完了のバッチ更新は、必要であれば明示的に実行できますが、状況によっては暗黙的に実行されます。

注意:
バッチ実行中に例外が発生する場合もあるので、そうした例外による影響を考慮することは重要です。「バッチ実行中のエラー状態」を参照してください。

バッチ更新機能を明示的に実行するには、実行コンテキスト・インスタンスのexecuteBatch()メソッドを使用します。このメソッドは、更新カウントのint型配列を戻り値としています。

バッチを明示的に実行する例を次に示します。

...
ExecutionContext ec = new ExecutionContext();
ec.setBatching(true);
...
double[] sals = ...;
String[] empnos = ...;
for (int i = 0; i < empnos.length; i++)
{
#sql [ec] { UPDATE emp SET sal = :(sals[i]) WHERE empno = :(empnos[i]) };
}
int[] updateCounts = ec.executeBatch();
...

注意:
executeBatch()の起動時に、実行コンテキスト・インスタンスに未完了のバッチがなければ、このメソッドの戻り値はnullになります。

未完了のバッチが存在するときは、次のような場合に暗黙的に実行されます。

- バッチ処理を行うことができない実行文が出現した場合。この場合最初に既存のバッチが実行の対象となり、次にバッチ処理の行うことができない文が実行されます。

- あるUPDATE文がバッチ可能であっても、既存のバッチとは非互換(つまり、その文のインスタンスではない)。この場合は、バッチが実行された後で、非互換の文から新規のバッチが生成されます。

- 事前定義されたバッチ数の上限(指定された文の数)に達した場合。

次に、その例を示します。まず、あるバッチを作成され、バッチ可能でない文が出現したときに暗黙的に実行されます。次に、新しいバッチが作成され、バッチ可能でも互換性のない文が出現したときに暗黙的に実行されます。

ExecutionContext ec = new ExecutionContext();
ec.setBatching(true);
...
/* Statements in the following loop will be placed in a batch */
double[] sals = ...;
String[] empnos = ...;
for (int i = 0; i < empnos.length; i++)
{
#sql [ec] { UPDATE emp SET sal = :(sals[i]) WHERE empno = :(empnos[i]) };
}

/* a SELECT is unbatchable so causes the batch to be executed */
double avg;
#sql [ec] { SELECT avg(sal) INTO :avg FROM emp };

/* Statements in the following loop will be placed in a new batch */
double[] comms = ...;
for (int i = 0; i < empnos.length; i++)
{
#sql [ec] { UPDATE emp SET comm = :(comms[i]) WHERE empno = :(empnos[i]) };
}

/* the following update is incompatible with the second batch, so causes it to be executed */
int smithdeptno = ...;
#sql [ec] { UPDATE emp SET deptno = :smithdeptno WHERE ename = 'Smith' };

暗黙的に実行されたバッチの更新カウントを取得するには、その実行コンテキスト・インスタンスのgetBatchUpdateCounts()メソッドを起動します。このメソッドの起動後、この実行コンテキスト・インスタンスで正常に実行されたバッチのうち、最後のバッチの実行更新カウントが戻り値として戻されます。SELECT文および最後のUPDATE文の後に、次のコード文が挿入される場合があります。

int[] updateCounts = ec.getBatchUpdateCounts();

注意:
実行コンテキスト・インスタンスに対して正常に実行されたバッチ更新がなければ、getBatchUpdateCounts()の戻り値はnullになります。

関連項目:
「実行コンテキストの更新カウント」

バッチの取消し

実行コンテキストの未完了のバッチを取り消すには、その実行コンテキスト・インスタンスのcancel()メソッドを使用します。たとえば、バッチ実行時に発生した例外のイベント内で、実行済であるが、コミットされていないバッチを取り消すことができます。次に例を示します。

...
ExecutionContext ec = new ExecutionContext();
ec.setBatching(true);
...
double[] sals = ...;
String[] empnos = ...;
for (int i = 0; i < empnos.length; i++)
{
#sql [ec] { UPDATE emp SET sal = :(sals[i]) WHERE empno = :(empnos[i]) };
if (!check(sals[i], empnos[i])) //assume "check" is a user-supplied function
{
ec.cancel();
throw new SQLException("Process canceled.");
}
}

try
{
int[] updateCounts = ec.executeBatch();
} catch ( SQLException exception) { ec.cancel(); }
...

あるバッチを取り消した場合、次のバッチ可能な文から新規のバッチが開始されます。

注意:

- cancel()をコールすると、現時点で実行中の文もすべて取り消されます。

- バッチを取り消しても、バッチ更新は無効になりません。

実行コンテキストの更新カウント

Oracle Database 11g SQLJ実装では、更新カウントの配列(実行コンテキスト・インスタンスのexecuteBatch()またはgetBatchUpdateCounts()メソッドの戻り値)には、バッチの文で更新された行数カウントは含まれていません。この戻り値で示されるのは、各文の更新が成功したかどうかです。このため、バッチ処理が無効である場合、実行コンテキスト・インスタンスのgetUpdateCount()メソッドの戻り値である単一の更新カウントと前に示したカウントは機能が異なるものです。いくつかの文を1つに一括してバッチ実行すると、getUpdateCount()からの戻り値である単一の更新カウントの内容も変更されます。

バッチ可能な環境では、実行コンテキスト・インスタンスのgetUpdateCount()メソッドの戻り値は、各文が出現するたびに修正されます。この戻り値は、ExecutionContextクラスのstatic int定数の値(次のうちの1つ)で更新されます。

- NEW_BATCH_COUNT: 最後に出現した文に対して新しいバッチが生成されたことを示します。

- ADD_BATCH_COUNT: 最後に出現した文が既存のバッチに追加されたことを示します。

- EXEC_BATCH_COUNT: 最後の文が出現した後で、未完了のバッチが明示的または暗黙的に実行されたことを示します。

上に示した定数を参照するには、次の修飾名を使用します。

ExecutionContext.NEW_BATCH_COUNT
ExecutionContext.ADD_BATCH_COUNT
ExecutionContext.EXEC_BATCH_COUNT

バッチが明示的または暗黙的に実行された後にexecuteBatch()やgetBatchUpdateCounts()から戻された配列には、文の実行の正常・異常終了のみが示されます。各バッチの文には、それぞれ配列要素があります。JDBC 2.0仕様に従って、配列要素の値が-2であれば、対応する文の実行は正常終了したが、更新行数は不明であるという意味になります。

バッチの実行後に配列の値すべてに目を通しても、大して意味がありません。この戻り値としての配列に対するチェックとしては、実行前にバッチ形態にまとめられた文の数を確認することのみが挙げられ、具体的には実行の正常終了後(基本的には、例外を発生しないバッチ実行後)に配列の要素数をチェックします。

複数の文が一括されてそのバッチが実行される段階では、更新カウントの配列は未更新になっています。

バッチ制限の設定

事前定義された数の文がバッチされてから次の文が追加されるまでの間に、各更新バッチが実行されるように指定できます。次のように、実行コンテキスト・インスタンスのsetBatchLimit()メソッドを使用し、0(ゼロ)でない正の整数を入力します。

...
ExecutionContext ec = new ExecutionContext();
ec.setBatching(true);
ec.setBatchLimit(10);
...
double[] sals = ...;
String[] empnos = ...;
for (int i = 0; i < 20; i++)
{
#sql [ec] { UPDATE emp1 SET sal = :(sals[i]) WHERE empno = :(empnos[i]) };
}

このループの実行回数は20回ですが、文のバッチとバッチの実行は11回目のループ中、つまり11個目の文がバッチに追加される前に完了します。ループの中では、バッチはループの2回目には処理されないので注意してください。アプリケーションがループを抜けた後は、別の文を実行するか、バッチを明示的に実行するまでは最後の10個の文はこの未実行のバッチの中に残ります。

ExecutionContextクラスのstatic int定数(次の2つのどちらか)は、setBatchLimit()への入力として使用できます。

- AUTO_BATCH: SQLJランタイムによるバッチ制限の判断を可能にします。

- UNLIMITED_BATCH(デフォルト): バッチ制限がないことを示します。

次に例を示します。

...
ExecutionContext ec = new ExecutionContext();
ec.setBatching(true);
ec.setBatchLimit(ExecutionContext.AUTO_BATCH);
...

または

ec.setBatchLimit(ExecutionContext.UNLIMITED_BATCH);
...

現在のバッチ制限をチェックするには、実行コンテキスト・インスタンスのgetBatchLimit()メソッドを使用します。

非互換の文に対するバッチ処理

既存のバッチ形態の文とは互換性がない文をバッチ処理する際に、このバッチを暗黙的に実行しない場合は、別個の実行コンテキスト・インスタンスを使用してください。次に例を示します。

...
ExecutionContext ec1 = new ExecutionContext();
ec1.setBatching(true);
ExecutionContext ec2 = new ExecutionContext();
ec2.setBatching(true);
...
double[] sals = ...;
String[] empnos = ...;
for (int i = 0; i < empnos.length; i++)
{
#sql [ec1] { UPDATE emp1 SET sal = :(sals[i]) WHERE empno = :(empnos[i]) };
#sql [ec2] { UPDATE emp2 SET sal = :(sals[i]) WHERE empno = :(empnos[i]) };
}
int[] updateCounts1 = ec1.executeBatch();
int[] updateCounts2 = ec2.executeBatch();
...

注意:
この例では、2つのUPDATE文が互いに依存しないことを前提としています。相互に依存しあう文を別々の実行コンテキストでバッチ処理するのは避けてください。これらの文が実行される順序を必ずしも保証できないためです。

かわりの方法としては、単一の実行コンテキストと別個のループを使用し、EMP1の更新をすべて一括して実行した後で、EMP2の更新を実行する方法があります。具体的には、次のようにします。

...
ExecutionContext ec = new ExecutionContext();
ec.setBatching(true);
...
double[] sals = ...;
String[] empnos = ...;
for (int i = 0; i < empnos.length; i++)
{
#sql [ec] { UPDATE emp1 SET sal = :(sals[i]) WHERE empno = :(empnos[i]) };
}
for (int i = 0; i < empnos.length; i++)
{
#sql [ec] { UPDATE emp2 SET sal = :(sals[i]) WHERE empno = :(empnos[i]) };
}
ec.executeBatch();
...

この例の最初のバッチは暗黙的に実行されているのに対し、2番目のバッチは明示的に実行されます。

暗黙的な実行コンテキストを使用したバッチ更新機能

ここまでのすべてのバッチ更新の例では、明示的な実行コンテキスト・インスタンスを指定してきました。あらゆる実行コンテキスト・インスタンスが暗黙的な実行コンテキスト・インスタントを持てば必要ありません。たとえば、デフォルト接続の暗黙的な実行コンテキスト・インスタンスを参照するには、次のようにします。

DefaultContext.getDefaultContext().getExecutionContext().setBatching(true);
...
double[] sals = ...;
String[] empnos = ...;
for (int i = 0; i < empnos.length; i++)
{
#sql { UPDATE emp SET sal = :(sals[i]) WHERE empno = :(empnos[i]) };
}
// implicitly execute the batch and commit
#sql { COMMIT };

または、次のようにこのバッチを明示的に実行することも可能です。

DefaultContext.getDefaultContext().getExecutionContext().executeBatch();

バッチ更新機能に関する一般的な注意

バッチ更新機能処理を使用する場合、特に、実行コンテキスト・インスタンスがバッチの文とバッチ形態でない文とを混合する場合は、次の点に注意してください。

- バッチ形態でない文はバッチの文に依存するので、まずバッチの文を実行し、その後でバッチ形態でない文を実行する必要があります。

- JDBC COMMIT操作やROLLBACK操作、つまり、JDBC Connectionインスタンスを自動コミットするか、またはcommit()メソッドまたはrollback()メソッドを明示的に使用する場合は、バッチ中の未完了の文は実行されません。
ただし、SQLJ COMMITまたはROLLBACK文を次のように使用すると、バッチ内の未完了文が実行されます。

#sql { COMMIT };

または

#sql { ROLLBACK };

この理由からも、変更内容のコミットやロールバックには、常に#sql構文を使用することをお薦めします。この構文を使用すると、SQLJリソースとJDBCリソースの両方をクリーンアップできます。

- バッチ処理できない文または互換性のない文が現れた結果としてバッチが暗黙的に実行される場合、そのバッチが実行されるのは、バッチ処理できない文または互換性のない文が実行される前で、文の入力パラメータが評価されて目的の文に渡された後です。

- バッチ可能な実行コンテキスト・インスタンスのうち特定のインスタンスのみの使用を中止する際は、リソースを解放するために、未完了のバッチを暗黙的に実行するか、取り消すことをお薦めします。

バッチ実行中のエラー状態

ある文が原因でバッチ実行中に例外が発生した場合、次の点に注意してください。

- 例外発生の原因となった文より後のバッチの文は、実行されません。

- 例外発生前にすでに実行されたバッチの文は、ロールバックされません。

- 例外が発生したバッチが、別の(バッチ処理できないか非互換の)文が現れた結果として、暗黙的に実行された場合、その文は実行されません。

注意:
バッチ更新の使用時には自動コミット・モードを無効にしてください。これによって、バッチ実行時にエラーが発生した場合、コミットおよびロールバックを制御できます。

JDBC 2.0以上でのバッチ実行中に例外が発生した場合、通常、それは標準java.sql.BatchUpdateExceptionクラスのインスタンス、java.sql.SQLExceptionクラスのサブクラスです。BatchUpdateExceptionクラスにはgetUpdateCounts()メソッドがあり、このメソッドは、例外発生前に正常に実行されたバッチ処理文に関して、ExecutionContextクラスのexecuteBatch()またはgetBatchUpdateCounts()メソッドから戻される内容と同等の更新カウントの配列を戻します。

再帰的コールインとバッチ更新機能

SQLJストアド・プロシージャでは、あるプロシージャから別のプロシージャをコールすると、2つのプロシージャが同時に1つの実行コンテキスト・インスタンスを使用することになります。バッチ更新フラグ(実行コンテキスト・インスタンスのsetBatching()メソッドを使用して設定)は、その他の実行コンテキストの属性と同じ動作をします。フラグを設定したストアド・プロシージャには関係なく、このフラグ設定値は、どちらかのストアド・プロシージャ内にある次の実行文に反映されます。

このため、再帰的コールインのたびにサーバーではバッチ更新機能が自動的に無効化されます。再帰的に起動されるプロシージャでは、未完了のバッチは実行されますが、バッチ処理は行われなくなります。こうした動作を回避するには、バッチ可能なストアド・プロシージャで明示的な実行コンテキスト・インスタンスを使用します。

関連項目:
「サーバーでの再帰的SQLJコール」

列の定義

Oracle SQLJ実装では、列の型およびサイズの定義にOracle JDBCのサポートが反映されています。ドライバの実装は、Oracle JDBCドライバごとに若干異なりますが、列の型およびサイズを登録すると、問合せごとのデータベースとのやり取りが軽減されます。このことは特に、Oracle JDBC Thinドライバと位置イテレータの使用に当てはまります。

列の定義に関するOracle実装

Oracle SQLJ実装では列の定義を有効にすると、次に示したような、列型とサイズを登録するための手順が自動的に開始されます。

- デフォルトのOracle固有コード生成を使用したカスタマイズ時または変換時に、SQLJは、特定のデータベース・スキーマに接続して、取得する列の型およびサイズを確認します。ISO標準SQLJコード生成の場合、列のデフォルトはSQLJプロファイルの一部になります。この処理が行われるのは、ソース・コードの変換をカスタマイズするための手順の際または既存プロファイルを個別にカスタマイズする際です。

- アプリケーション稼働時、SQLJランタイムでは列情報を利用し、JDBCドライバで列型とサイズを登録します。この際にOracle JDBC文のクラスのdefineColumnType()メソッドへのコールが使用されます。

列の定義に使用するカスタマイザおよびトランスレータのオプション

列の定義を有効化するには、SQLJのオプションを次のように設定します。

- optcolsフラグを有効にします。Oracle固有コード生成の場合は、SQLJトランスレータの-optcolsオプションを使用します。ISO標準コード生成の場合は、トランスレータのオプションまたはOracleカスタマイザのオプションを使用します(SQLJコマンドラインで-P-Coptcolsと入力します)。

- データベース接続用のユーザー、パスワードおよびURLを設定します。Oracle固有コード生成の場合、この設定はSQLJトランスレータの-user、-passwordおよび-urlの各オプションを介して行います。ISO標準コード生成の場合、この設定は、トランスレータのオプションを介して、またはカスタマイザのオプションを個別に使用して行われます(SQLJコマンドラインで-P-user、-P-passwordおよび-P-urlを入力します)。デフォルトのOracleDriverクラスを使用する場合は、さらに、JDBCドライバ・クラスも設定します(SQLJコマンドラインで-P-driverと入力します)。

関連項目:
「列の定義(-optcols)」および「接続オプション」

カスタマイザのオプションの詳細は、「カスタマイザ固有のオプションの概要」のoptcolsの項、および「カスタマイザ・ハーネスのオプションの概要」のuser、password、urlおよびdriverの項を参照してください。

パラメータ・サイズの定義

Oracle JDBCおよびSQLJ実装では、JDBCリソース割当て量を最適化できます。このためには、次のいずれかに使用するパラメータ・サイズ(Javaホスト変数のサイズ)を定義します。

- ストアド・プロシージャまたはファンクション・コールの入出力パラメータ

- ストアド・ファンクション・コールからの戻り値

- SET文の入出力パラメータ

- PL/SQLブロックの入出力パラメータ

パラメータ・サイズの定義に関するOracle実装

Oracleでは、オプション設定値とソース・コードのコメントに埋込みのヒントとの組合せによって、パラメータ・サイズが実装されます。ISO標準SQLJコード生成の場合、Oracleカスタマイザのオプションが使用できます。デフォルトのOracle固有コード生成の場合、同等のSQLJトランスレータのオプションが使用できます。

次のように、オプションおよびヒントを使用します。

- SQLJトランスレータまたはOracleカスタマイザのパラメータ定義フラグを使用して、パラメータ・サイズの定義を有効にします。

- SQLJトランスレータまたはOracleカスタマイザのパラメータ・デフォルト・サイズ・オプションを使用して、特定のデータ型のデフォルト・サイズを指定します。

- ソース・コードのコメントにヒントを次の書式で埋め込んで、特定のデータ型のデフォルト・サイズを指定変更します。

指定したホスト変数に対するパラメータ・サイズの定義を使用可能にすると、ソース・コード・ヒントがあればそれに従ってリソースが割り当てられます。ソース・コード・ヒントがない場合、対応するデータ型のデフォルト・サイズが指定されていれば、そのデフォルト・サイズが使用されます。ソース・コード・ヒントも該当のデフォルト・サイズも指定されてない場合、JDBC実装に基づいて最大のリソース量が割り当てられます。

アプリケーション実行時に、Oracle JDBC文のクラスで使用できるdefineParameterType()メソッドとregisterOutParameter()メソッドをコールすることによって、パラメータ・サイズが登録されます。

注意:
パラメータ定義フラグを有効にしなかった場合は、パラメータ・サイズのデフォルトとソース・コード・ヒントが無視され、JDBC実装に基づいて最大またはデフォルトのリソースが割り当てられます。

パラメータ・サイズの定義に使用するカスタマイザとトランスレータのオプション

パラメータ・サイズの定義には、次のSQLJのオプションを使用します。

- パラメータ・サイズの定義を有効化するには、optparamsフラグを使用します。Oracle固有コード生成の場合は、SQLJトランスレータの-optparamsオプションを使用します。ISO標準コード生成の場合は、トランスレータのオプションまたはOracleカスタマイザのオプションを使用します(SQLJコマンドラインで-P-Coptparamsと入力します)。

- 特定のデータ型にデフォルトのサイズを設定するには、optparamdefaultsを使用します。Oracle固有コード生成の場合は、SQLJトランスレータの-optparamdefaults=xxxxオプションを使用します。ISO標準コード生成の場合は、トランスレータのオプションまたはOracleカスタマイザのオプションを使用します。SQLJコマンドラインで-P-Coptparamdefaults=xxxxと入力します。

関連項目:

- 「パラメータの定義(-optparams)」

- 「パラメータのデフォルト・サイズ(-optparamdefaults)」

- 「カスタマイザ固有のオプションの概要」

パラメータ・サイズの定義に使用するソース・コード・ヒント

パラメータ・サイズ定義のためのヒントは、次の形式でSQLJ文のソース・コードに埋め込みます(必要であれば、コメント内に空白文字を追加してもかまいません)。

/*(size)*/

サイズはバイト単位になっています。optparamsオプションを無効にすると、ヒントが無視されます。

デフォルトのパラメータ・サイズは、新規のサイズを指定せずに(JDBC実装でのサイズの自動割当てにより)指定変更するには、次のようにします。

/*()*/

次にその例を示します。

byte[] hash;
String name=Tyrone;
String street=2020 Meryl Street;
String city=Wichita;
String state=Kansas;
String zipcode=77777;
#sql hash = { /* (5) */ VALUES (ADDR_HASH(:name /* (20) */, :street /* () */,
:city, :state, :INOUT zipcode /* (10) */ )) };

結果式のヒント(前述の例では結果式hash)は、SQLJ文の大カッコの内側に記述します。入出力ホスト変数のヒントは、前述の例に示したように、このホスト変数のすぐ後ろに記述する必要があります。

この例では、パラメータ・サイズが次のように設定されます。

- hash: 5バイト

- name: 20バイト

- street: デフォルトを設定なしで指定変更します(JDBCによる自動割当て)

- city: なし(該当のデータ型のデフォルトが指定されていればそれが使用されます)

- state: なし(該当のデータ型のデフォルトが指定されていればそれが使用されます)

- zipcode: 10バイト

注意:
いずれかのパラメータ・サイズが変更された場合(実行時に実際のサイズが登録済のサイズを超えた場合など)、SQLの例外がスローされます。

SQLJのデバッグ機能

ここでは、Oracle SQLJ実装のデバッグ機能をまとめます。次の項目について説明します。

- デバッグ用のSQLJ -linemapフラグ

- サーバー側のdebugオプション

- AuditorInstaller専用カスタマイザの概要

- Oracle10g JDeveloperでの開発とデバッグの概要

デバッグ用のSQLJ -linemapフラグ

-linemapフラグを有効にすると、SQLJソース・コード・ファイルの行番号が、対応する.classファイルの場所にマッピングされます。このファイルは、SQLJトランスレータで生成された.javaファイルのコンパイルで生成される.classファイルになります。この結果、Javaランタイム・エラーが発生した場合、Java Virtual Machine(JVM)で報告された行番号がSQLJソース・コードでの行番号となり、デバッグがはるかに容易になります。

Sun社jdbデバッガを使用する際は、-linemapオプションのかわりに、-jdblinemapオプションを使用します。これらのオプションの機能は同等ですが、-jdblinemapではいくつか特別な処理を実行する点が異なります。この特別な処理とは、jdbではファイル拡張子が.javaであるJavaソース・ファイルのみがサポートされるために必要となる処理です。

関連項目:
「SQLJソース・ファイルとの行マッピング(-linemap)」および「jdbデバッガでのSQLJソース・ファイルへの行マッピング(-jdblinemap)」

注意:
サーバー側で変換すると、その変換で生成されたクラス・スキーマ・オブジェクトが、SQLJソース・コードにマッピングしてある行番号を自動的に参照します。クライアント側での変換時に-linemapオプションを有効化すると、サーバー側と同様の自動参照が行われます。

サーバー側のdebugオプション

SQLJソースをサーバーにロードし、サーバー側の埋込みトランスレータを使用して変換する場合、サーバー側debugオプションを指定すると、.sqljまたは.javaソース・ファイルをサーバー側でコンパイルしたときに、サーバー側コンパイラからデバッグ情報が出力されます。これは、クライアント上で標準のjavacコンパイラを実行するときに、-gオプションを使用するのに相当します。このオプションは、SQLJコードのデバッグでは特に役立ちませんが、Javaコードのデバッグでは通常は役立ちます。

このオプションと、サーバー側オプションの設定方法の詳細は、「サーバー側の埋込みトランスレータでサポートされるオプション」を参照してください。

Oracle JVMでのデバッグ方法の概要は、『Oracle Database Java開発者ガイド』を参照してください。

AuditorInstaller専用カスタマイザの概要

ISOコード生成の場合、SQLJでは、AuditorInstallerという特別なカスタマイザが提供されます。このカスタマイザは、SQLJコマンドラインで指定したプロファイルに、オーディタと呼ばれるデバッグ文のセットを挿入します。これらのプロファイルは、前回のカスタマイズによって生成済であることが必要です。アプリケーションを実行すると、SQLJランタイムでデバッグ文が実行され、メソッド・コールと戻り値のトレース情報が表示されます。

デバッグ文を挿入するには、カスタマイズの一般オプションの場合と同じように、先頭に-P-を付けて、カスタマイザ・ハーネスのdebugオプションを使用します。

関連項目:
「デバッグ用のAuditorInstallerカスタマイザ」

Oracle10g JDeveloperでの開発とデバッグの概要

Oracle SQLJ製品は、Oracle10g JDeveloperビジュアル・プログラミング・ツールに完全に統合されています。

JDeveloperには、SQLJをサポートする統合デバッガも用意されています。アプリケーションの実行時に、標準のJava文と同じようにSQLJ文を1行ずつデバッグできます。報告される行番号は、生成されたJavaコードの行番号ではなく、SQLJソース・コードの行番号に対応しています。

Oracle Performance MonitoringのSQLJサポート

ここでは、Oracle Dynamic Monitoring Service(DMS)に対するOracle SQLJ実装のサポートについて説明します。

- SQLJ DMSサポートの概要

- DMS用のSQLJコマンドライン・オプションの概要

- DMS用のSQLJランタイム・コマンドおよびプロパティ・ファイル設定

- SQLJ DMSセンサーとメトリック

- SQLJ DMSの例

注意:
『Oracle Application Serverパフォーマンス・ガイド』

SQLJ DMSサポートの概要

DMSを使用すると、ユーザーは、SQLJプログラムのパフォーマンス統計を測定できます。DMSのSQLJサポートは、実行時間などの各SQL文の全体的なパフォーマンスに焦点を当てていますが、DMSのOracle JDBCサポートのように、メソッドレベルまたはクラスレベルのパフォーマンス情報を提供することもできます。クライアント側の観点(各#sql文の全体的なパフォーマンスなど)か、またはサーバー側の観点(各SQL操作のサーバー側トレースなど)か、あるいはその両方を選択できます。

プログラムのインストルメントは、DMS設定を可能にするために必要であり、SQLJオプションを介して変換時に指定されます。インストルメントとは、具体的にはパフォーマンスを測定するためにDMSコールをシステムまたはアプリケーション・コードに挿入するプロセスです。

実行時に、変換時にインストルメントされたすべてのコンポーネントを、SQLJ DMSプロパティ・ファイル内の指示に従って監視できます。実行時、統計がDMS APIを介してDMSに送信されます。これには、環境でDMSシステムが実行されている必要があります。統計には、DMSツールを介してアクセスできます。

統計は、SQL文のパフォーマンスを追跡および理解するために役立ちます。また、統計は次の階層に従って(上から下に)レポートされます。

1. アプリケーション: このコンテキストでは、アプリケーションは、変換のためにSQLJコマンドラインで指定されたSQLJコンポーネントとJavaコンポーネントの構成と定義されます。ただし、SQLJコンポーネントのみがインストルメント可能です。

2. モジュール: モジュールはJavaパッケージに対応します。

3. アクション: アクションは、SQLJプログラムに定義されたJavaクラスにマップします。

4. 文: 文は、SQLJプログラム内のSQL文です。

次のDMS統計は、クライアント側の監視のために測定されます。

- 各#sql文の経過時間(解析および実行を含む)

- 各next()コールの実行時間であるGet-next時間

- 各getXXX ()コールを介したデータベース列の抽出時間であるGet-XXX時間

これらの統計では、変換時と実行時の両方でDMSライブラリがCLASSPATH内に存在する必要があります。したがって、サーバーでは、DMSライブラリを使用できないため、これらの統計はサポートされません。サーバー側のSQLJコードは、クライアント側のコードと同じ方法では監視できません。

次の統計は、SQLJクライアント・プログラムのサーバー側のSQL監視のために測定されます。

- 解析時間

- 実行時間

- フェッチ時間

これらの統計は、SQLトレース機能を介して、Oracle Database 11g のトレース・ファイルから取得できます。これはDMSとは関係ありませんが、SQLJ DMSプロパティ・ファイルsqlmonitor.servertracingの設定を介して使用可能にできます。

関連項目:
「DMS用のSQLJランタイム・コマンドおよびプロパティ・ファイル設定」

クライアント側のSQLJプログラムには、DMS統計とサーバー側トレースの両方を使用できます。たとえば、DMSから1つの問合せで構成される#sql文に必要な合計時間を取得でき、次にサーバー側トレースから、サーバー内でのSQL問合せの実行にかかった実際の時間を取得できます。

注意:

- 現在、DMSサポートにはOracle固有コード生成が必要です。これは、デフォルトで有効になっています。

- Oracle Database 11g では、インストルメント済のコードにJava Development Kit(JDK)1.5が必要です。

- SQLJ宣言と文のみがインストルメントされます。

- DMSライブラリは、Oracle Database 11gのORACLE_HOME/oc4j/libにあるファイルdms.jar内に存在します。

DMS用のSQLJコマンドライン・オプションの概要

Oracle SQLJ実装では、DMSをサポートするための次のトランスレータ・フロントエンド・オプションが提供されます。

- -instrument: インストルメントを有効にし、アプリケーション(変換するコンポーネントの集合)の名前を指定します。

関連項目:
「DMSのためのインストルメント(-instrument)」

- -components: インストルメントするコンポーネント(パッケージおよびクラス)を指定します。

関連項目:
「DMSのためにインストルメントするコンポーネント(-components)」

通常、-instrument設定で目的のアプリケーション名を指定し、必要に応じてパッケージも指定して、インストルメントを有効にします。または、trueを指定して、デフォルトのアプリケーションdefaultAppを使用します。DMSのインストルメントで、アプリケーションという用語は、SQLJコマンドラインで変換のために指定されたすべてのSQLJコンポーネントとJavaコンポーネントを指します。

インストルメントが有効な場合、SQLJ DMSプロパティ・ファイルは、-instrumentの設定(カレント・ディレクトリを基準とする)およびSQLJ -dオプションのすべての設定に従って作成されます。trueを設定すると、カレント・ディレクトリ内のプロパティ・ファイルの名前がsqlmonitor.propertiesになります。

注意:
-instrumentを設定することは、-instrument=trueを設定することと同じです。-instrument=false(デフォルト)を設定すると、インストルメントは無効になります。

簡単な例として、-instrument=myappを設定すると、プロパティ・ファイルmyapp.propertiesが作成されます。ここで、アプリケーション名がstock、パッケージ名がcom.acmeの次の例を考えます。

% sqlj -instrument=com.acme/stock -d /home Stock.sqlj Trading.sqlj

-dオプションが指定されているため、/home/com/acme/stock.propertiesファイルが作成されます。

-instrumentオプションでインストルメントを有効にしている場合は、-componentsオプションを使用して、DMS監視のためにインストルメントする変換済コンポーネントのサブセットを指定します。通常は、実行時の監視に柔軟性を持たせるために、ほとんど、またはすべてのコンポーネントを指定します。(各パッケージ内のすべてのクラスをインストルメントするために)パッケージのカンマ区切りリストを指定するか、特定のクラスを指定するか、またはデフォルトのall設定を使用して変換するすべてのコンポーネントをインストルメントします。

たとえば、クラスStockおよびTradingをインストルメントするには、次の構文を使用します。

% sqlj ... -components=com.acme.Stock,com.acme.Trading

実行時に、インストルメントされたコンポーネントが、SQLJ DMSプロパティ・ファイル内の指定に従って監視されます。変換時にインストルメントされていないコンポーネントは、プロパティ・ファイル内の指定にかかわらず、いずれも実行時に監視できません。

DMS用のSQLJランタイム・コマンドおよびプロパティ・ファイル設定

SQLJトランスレータで監視機能のためにファイルをインストルメントするかどうかはSQLJの-instrumentオプションで指定しますが、実行時に何をどのように監視するかを実際に決定するのはSQLJ DMSプロパティ・ファイルです。

このプロパティ・ファイルは変換時にSQLJによって作成され、必要に応じて変更できます。SQLJを再実行する場合、SQLJによってプロパティ・ファイルが上書きされることに注意してください。ファイルに行ったすべての変更は失われます。

SQLJプロパティ・ファイルでは、次の設定を行います。

- sqlmonitor.components: インストルメントされたコンポーネント(パッケージまたはクラス)のカンマ区切りリストです。これは、SQLJの-componentsオプションの設定を反映して、トランスレータによって自動的に設定されます。

- sqlmonitor.monitorcomp: 監視するコンポーネント(パッケージまたはクラス)のカンマ区切りリストであり、sqlmonitor.components設定内のコンポーネントのサブセットを示します。sqlmonitor.monitorcompは、sqlmonitor.components設定を反映して変換時に初期設定されますが、必要に応じて調整できます。allを設定すると、sqlmonitor.components設定にリストされたすべてのコンポーネントが監視されます。

- sqlmonitor.dms: このブール・フラグにデフォルト値のtrueを設定して、収集した統計をDMSに送信することを指定します。これには、DMSツールを使用可能なOracle Application Server 10g インスタンスが実行されている必要があります。統計は、Webブラウザで表示するか、またはファイルに書き込むことができます。

注意:
現在、sqlmonitor.dms=falseの設定はサポートされていません。

- sqlmonitor.sysurl: サーバー側トレースに対して、データベースURLを指定します。

- sqlmonitor.sysuser: サーバー側トレースに対して、データベース・ユーザーを指定します。このユーザーには、sysdba権限が必要です。

- sqlmonitor.syspassword: サーバー側トレースに対して、sysuserのパスワードを指定します。

注意:
sysurl、sysuserおよびsyspasswordのデフォルト値は、SQLJコマンドラインまたはSQLJプロパティ・ファイルのいずれかを介してSQLJに指定されたuser、passwordおよびurlの値に従います。

- sqlmonitor.servertracing: サーバー側トレースを有効にして、SQL操作に関する統計などのサーバー内のパフォーマンス統計を収集するかどうかを指定します。trueまたはfalse(デフォルト)の設定がサポートされています。

- sqlmonitor.dumpfile: DMSに統計を送信する場合、このオプションを使用して、DMSツールで統計を書き込むファイルを指定できます。デフォルトはapplication_name.mtrです。application_nameは、-instrumentオプションの設定に従うか、またはデフォルトのdefaultAppになります。

SQLJ DMSセンサーとメトリック

センサーは、インストルメントされたSQLJプログラムの実行中にDMSでパフォーマンス・メトリックを計算するために使用され、DMSに送信されます。センサーは階層で編成され、各センサーにはパス名が付きます。一般的なセンサーの形式を次に示します。

/SQLJ/application_name/sensor_name
/SQLJ/application_name/module/sensor_name
/SQLJ/application_name/module/class/sensor_name
/SQLJ/application_name/module/class/linenum/sensor_name

センサーはoracle.dms.instrument.Sensorクラスのインスタンスで、このクラスには、パフォーマンス統計を計算および編成するためのメソッドが含まれます。たとえば、追加のメトリックを導出し、いずれかのメトリックの値を取得するようにセンサーに指示するメソッドが存在します。

インストルメントしたアプリケーションの終了の前に、oracle.sqlj.runtime.sqlmonitor.SQLMonitorクラスのclose()メソッドへのコールが必要なことに注意してください。次に例を示します(接続コンテキストを終了するためのOracleクラスのclose()メソッドも使用されています)。

try
{
Oracle.close();
oracle.sqlj.runtime.sqlmonitor.SQLMonitor.close();
}
catch( Throwable e ) { ... }

次の用語に注意してください。

- application_name はアプリケーションの名前であり、SQLJ -instrumentオプションの設定に従うか、またはデフォルトのdefaultAppになります。

- センサーがパッケージに関連付けられている場合、module はパッケージ名になります。パッケージ名を省略した場合、設定*TopLevel*が使用されます。

- センサーがクラスに関連付けられている場合、class はクラス名になります。

- センサーがSQL文に関連付けられている場合、linenum はインストルメントしているSQLJプログラム内のSQL文の行番号を示します。複数のSQL文が同じ行に存在する場合、開始列の位置を使用して文が区別されます。たとえば、linenum の値が8.13の場合、8は行番号、13は列番号を示します。

次のセンサーと関連付けられたメトリックは通常、特定の用途に使用されます。

- センサー名: ContextType

/SQLJ/application_name/module/class/linenum/ContextType

メトリック:

- value: 接続コンテキスト型を示す文字列

- センサー名: SQLString

/SQLJ/application_name/module/class/linenum/SQLString

メトリック:

- value: SQL文で構成される文字列
これはJDBCに渡される完全な文字列であり、元の#sql文から行われたすべての変換を含みます。

- センサー名: Execute

/SQLJ/application_name/module/class/linenum/Execute

メトリック:

- time: この文に対するJDBC execute()メソッドのすべての実行の合計時間(ミリ秒)
たとえば、文が5回実行された場合、timeは5回の実行に対してexecute()メソッドの実行にかかった合計時間になります。

- completed: 完了した実行の数(5など)

- minTime: 任意の1回の実行の最小時間

- maxTime: 任意の1回の実行の最大時間

- avg: timeをcompletedで割った平均実行時間

- active: プログラムの実行の終わりに文を実行しているスレッドの数(通常は0)

- maxActive: プログラムの実行中に文を実行したスレッドの最大数

JDBC文の実行時間を測定するために、クロックが文の実行直前に開始され、結果セットが取得されるか、文が実行を終了するか、または例外が捕捉されたときに停止します。

- センサー名: ServerExecute

/SQLJ/application_name/module/class/linenum/ServerExecute

メトリック:

- value: このSQL文のすべての実行に対するサーバーでの合計実行時間(ミリ秒)

- count: 完了した実行の数

- minValue: 任意の1回の実行の最小時間

- maxValue: 任意の1回の実行の最大時間

- センサー名: ServerFetch

/SQLJ/application_name/module/class/linenum/ServerFetch

メトリック:

- value: このSQL文のすべての実行に対するサーバーでの合計フェッチ時間(ミリ秒)

- count: 完了した実行の数

- minValue: 任意の1回の実行の最小時間

- maxValue: 任意の1回の実行の最大時間

- センサー名: ServerParse

/SQLJ/application_name/module/class/linenum/ServerParse

メトリック:

- value: このSQL文のすべての実行に対するサーバーでのSQL文の合計解析時間(ミリ秒)

- count: 完了した実行の数

- minValue: 任意の1回の実行の最小時間

- maxValue: 任意の1回の実行の最大時間

- センサー名: Next

/SQLJ/application_name/module/class/linenum/Next

メトリック:

- time: このSQL文のすべての実行に対する結果セット・イテレータのnext()メソッドの合計実行時間(ミリ秒)

- completed: 完了した実行の数(5など)

- minTime: 任意の1回の実行の最小時間

- maxTime: 任意の1回の実行の最大時間

- avg: timeをcountで割った平均実行時間

- active: プログラムの実行の終わりに文を実行しているスレッドの数(通常は0)

- maxActive: プログラムの実行中に文を実行したスレッドの最大数

SQLJ DMSの例

SQLJプログラムExprDemo.sqljをインストルメントするコマンドラインの例(全体を1行に入力)を次に示します。

% sqlj -dir=. -instrument=a.b.c/app -components=all
-user=scott -url=jdbc:oracle:oci:@ ExprDemo.sqlj
Password: password

注意:
dms.jarがCLASSPATH内に存在することを確認してください。

このコマンドを実行すると、次のファイルが生成されます。

- ./a/b/c/ExprDemo.java(-dirオプションの設定およびExprDemo.sqljでのパッケージa.b.cの宣言の結果)

- ./a/b/c/app.properties(-instrumentオプションの設定の結果)

SQLJ DMSプロパティ・ファイルの例

app.propertiesの内容の例を次に示します。この例では、SQLJによって作成された後にファイルを編集して、いくつかの設定をデフォルト以外に変更しているとします。

sqlmonitor.components=all
sqlmonitor.monitorcomp=all
sqlmonitor.dms=true
sqlmonitor.servertracing=true
sqlmonitor.sysurl=jdbc:oracle:oci:@
sqlmonitor.sysuser=scott
sqlmonitor.syspassword=tiger
sqlmonitor.dumpfile=a/b/c/app.mtr

注意:
SQLJトランスレータを再実行した場合、app.propertiesが上書きされ、加えたすべての変更が失われます。

統計の例

sqlmonitor.dms=trueを設定すると、監視する統計がDMSに送信されます。sqlmonitor.dumpfile値が設定されている場合、プログラムのコンパイルおよび実行時に、DMSツールによって統計が./a/b/c/app.mtrファイルに書き込まれます。

特定のコード例に対する統計を検査するExprDemo.sqljの部分を次に示します。

#sql
{
DECLARE
n NUMBER;
s NUMBER;
BEGIN
n := 0;
s := 0;
WHILE n < 100 LOOP
n := n + 1;
s := s + :IN (indx++);
END LOOP;
:OUT total := s;
END;
};

前述のコード例に関連し、実行時間およびサーバー実行時間を表示するapp.mtr内の統計の部分を次に示します。

SQLString.value:      DECLARE         n NUMBER;        s NUMBER;
BEGIN         n :=  0;         s := 0;       WHILE n < 100 LOOP
n := n + 1;
s := s +  :1 ;
END LOOP;          :2  := s;       END; statement SQL string
ServerExecute.maxValue:       20.0 server_execute_time
ServerExecute.minValue:       20.0 server_execute_time
ServerExecute.count:  0 ops
ServerExecute.value:  20.0 server execute time
ServerFetch.maxValue: 0.0 server_fetch_time
ServerFetch.minValue: 0.0 server_fetch_time
ServerFetch.count:    0 ops
ServerFetch.value:    0.0 server fetch time
ServerParse.maxValue: 0.0 server_parse_time
ServerParse.minValue: 0.0 server_parse_time
ServerParse.count:    0 ops
ServerParse.value:    0.0 server parse time
193.5
ContextType.value:    class sqlj.runtime.ref.DefaultContext
statement connection context
Execute.maxActive:    1 threads
Execute.active:       0 threads
Execute.avg:  37.0 msecs
Execute.maxTime:      37 msecs
Execute.minTime:      37 msecs
Execute.completed:    1 ops
Execute.time: 37 msecs

これらの統計は、JDBCクライアントでの(1回の実行の)合計実行時間が37ミリ秒であり、サーバーでの実行時間が20ミリ秒であることを示します。

イテレータの統計の例

ExprDemo.sqljでは、次のようにイテレータ型Iterの定義および実行も行われます。

#sql public static iterator Iter(String ename);

....

Iter iter;
#sql iter = { select ename from emp};
while (iter.next())
{
System.out.println(iter.ename());
}

DMSでは、イテレータに対するnext()操作の実行時間が収集されます。イテレータ型Iterに対するDMSの結果の例を次に示します。

Iter
Next.time:    5 msecs

この結果は、Iterインスタンス内を反復中にnext()操作にかかった合計時間が5ミリ秒であったことを示しています。

接続コンテキストの統計の例

ExprDemo.sqlj内の#sql文では、デフォルトの接続コンテキストが使用されます。プログラム全体で使用されるDefaultContextインスタンスに対して、DMSは次の統計を戻します。

class_sqlj.runtime.ref.DefaultContext
StmtCacheSize.value:  5 statement cache size
StmtsExecuted.count:  7 ops
StmtsCacheExecuted.count:     7 ops

この結果は、コンテキストに5つの文の文キャッシュ・サイズが含まれることを示しています。合わせて、7つのSQL文が実行されています。

11 サーバー側SQLJ

SQLJアプリケーションは、Oracle Database 11g サーバー側に格納でき、直接実行できます。SQLJアプリケーションを実行する場合、クライアント側で変換とコンパイルを行った後で、生成されたクラスとリソースをサーバー側にロードする方法と、SQLJのソース・コードをサーバー側にロードした後で、サーバーの埋込みトランスレータで変換とコンパイルを行う方法があります。

この章では、マルチスレッドや再帰的なSQLJコールなどの注意事項を含め、サーバー側でのSQLJの機能と使用方法について説明します。

内容は次のとおりです。

- サーバー側SQLJの概要

- サーバーで使用するSQLJコードの作成

- クライアント側でのSQLJソースの変換とコンポーネントのロード

- SQLJソースのロードとサーバーでの変換

- Javaスキーマ・オブジェクトの削除

- サーバー側のその他の考慮事項

サーバー側SQLJの概要

SQLJコードは、Javaコードと同様に、Oracle Database 11g のストアド・プロシージャ、ストアド・ファンクションまたはトリガーでも実行できます。データ・アクセスは、SQLJランタイムのサーバー側実装とサーバー側のOracle Java Database Connectivity(JDBC)内部ドライバを介して行います。また、Oracle Database 11g の埋込みSQLJトランスレータでは、SQLJソース・ファイルをサーバーで直接変換することも可能です。

SQLJをサーバーで実行するときは、サーバー側コーディングの問題、コードの変換先およびサーバーへのロード方法について考慮する必要があります。生成された出力の名前が、サーバーで決定される方法についても注意する必要があります。クライアント側でコードを変換およびコンパイルして、クラス・ファイルとリソース・ファイルをサーバーにロードすることも、.sqljソース・ファイルをサーバーにロードして、埋込みSQLJトランスレータで自動的に変換することも可能です。

この埋込みトランスレータのユーザー・インタフェースは、クライアント側のトランスレータとは異なります。サポートされているオプションはデータベース表を使用して指定することが可能で、エラーはデータベース表に出力されます。トランスレータからの出力ファイルを開発者が意識する必要はありません。

注意:

- Oracle Database 11g では、サーバーはJava Development Kit(JDK)1.5 Java2 Platform, Standard Edition (J2SE)環境を使用します。サーバー側のSQLJ環境は、SQLJ固有の接続Beanのサポートと「サーバーで使用するSQLJコードの作成」に記述されている関連する例外を除いて、runtime12eeライブラリを使用しているクライアント側の環境とほぼ等しいといえます。

- このマニュアルでは、システム設定にかかわる作業を、SQLJ開発者の仕事としては位置付けていません。そのため、Oracle Database 11g Java Virtual Machine(JVM)の設定はここでは説明していません。Java関連の設定パラメータの詳細は、『Oracle Database Java開発者ガイド』を参照してください。マルチスレッド・サーバー、ディスパッチャまたはリスナーの構成に関する情報が必要な場合は、『Oracle Database Net Services管理者ガイド』を参照してください。

Oracle DatabaseのJ2EEの非サポートに関する注意事項

Oracle9i Application Server Containers for J2EE(OC4J)(新しく軽量で、使いやすく高速な、認定済のJava2 Platform, Enterprise Edition(J2EE)コンテナ)の導入によって、J2EEおよびCommon Object Request Broker Architecture(CORBA)のスタックがデータベースでサポートされなくなります。ただし、Oracle JVMはまだ存在し、データベースでのJ2SEの機能、Javaストアド・プロシージャ、JDBCおよびSQLJを提供するために機能拡張が継続して行われます。

つまり、次のテクノロジは、データベースでサポートされません。

- Enterprise Beans(EJB)コンテナ、JavaServer Pages(JSP)コンテナおよびOracle9i Servlet Engine(OSE)で構成されるJ2EEスタック

- Visibroker for Javaをベースにした、埋込みCORBAフレームワーク

サーブレット、JSPページ、EJBおよびCORBAのオブジェクトをOracle Databaseにデプロイすることはできません。Oracle9i リリース1(9.0.1)は、J2EEとCORBAスタックをサポートする最後のデータベース・リリースです。データベースで実行していたJ2EEアプリケーションは、OC4Jに移行することをお薦めします。

サーバーで使用するSQLJコードの作成

ほとんどの場合、ターゲットのOracle Database 11g インスタンスで使用するSQLJコードの記述方法は、クライアント側で使用するSQLJコードの記述方法と同じです。記述方法に若干の相違はありますが、これはOracle JDBCの特性や一般的なJava特性によるもので、SQLJに固有のものではありません。ただし、次のような考慮事項があります。

- サーバー自体への暗黙的な接続が行われます。

- 自動コミット機能など、コーディング上の注意点があります。

- サーバー側のデフォルトの出力デバイスは、現行のトレース・ファイルになります。

- サーバー側とクライアント側とでは、名前解決の機能が異なります。

- SQLとJavaとでは、名前の解釈および処理の方法が異なります。

- サーバーには、JSP、EJBまたはCORBAの機能はありません。JSPコンテナがないため、サーバー側のコードではSQLJ JSP接続Beanを使用できません。

注意:
あるサーバーからサーバー側Thinドライバを介して別のサーバーに接続するためのSQLJコードを記述する場合は、クライアント側JDBC Thinドライバを使用したアプリケーション用のコードを記述する場合と同じようにします。この項で取り上げた留意点が当てはまる場面は、ほとんどありません。

ここでは、次の項目について説明します。

- サーバー側でのデータベース接続

- サーバー側でのコーディングの注意事項

- サーバーのデフォルトの出力デバイス

- サーバー側での名前解決

- SQL名とJava名

サーバー側でのデータベース接続

サーバー自体でSQLJコードを実行する場合、サーバー接続の概念は異なってきます。この場合、明示的なデータベース接続はありません。デフォルトでは、サーバー側で実行されるJavaプログラムに対して、データベースへの暗黙的なチャネルが使用されます。この接続はSQLJプログラムに対して自動的に初期化されるため、自分で初期化する必要はありません。ドライバの登録や指定、接続インスタンスの作成、デフォルトの接続コンテキストの指定、#sql文の接続オブジェクトの指定、または接続の終了を行う必要はありません。

注意:
サーバー側で、次に示したようにデフォルトの接続コンテキストをNULLに設定すると、デフォルトの接続コンテキスト(サーバーへの暗黙的な接続)が再設定されます。

DefaultContext.setDefaultContext(null);

サーバー側でのコーディングの注意事項

ターゲットのサーバーでサーバー側内部ドライバを使用してコードを実行する際には、コーディング上考慮する必要がある問題が多少伴います。留意点を次に挙げます。

- 内部ドライバで発行された結果セットは複数のコールにわたって存続するため、ファイナライザはカーソルを解放しません。このため、カーソルが不足しないように、すべてのイテレータを閉じることが特に重要です。ただし、実際に複数のコールにわたって使用される場合など、イテレータを開いたままにしておく特別の理由がある場合は別です。

- 内部ドライバでは自動コミット機能がサポートされないため、サーバー側では自動コミット設定が無視されます。データ更新を実行または取り消すには、明示的なCOMMIT文またはROLLBACK文を使用します。

#sql { COMMIT };
...
#sql { ROLLBACK };

注意:
Java Transaction Service(JTS)のトランザクションなどの、XAトランザクションを使用する場合は、SQLJやJDBCのCOMMIT/ROLLBACK文またはメソッドを使用できません。

- ISO標準コード生成の場合、JDBCコードと連係するSQLJコードを使用して、デフォルトでない接続コンテキスト・インスタンスを使用する場合は、そこにキャッシュされている文をクリーンアップするために最後に接続コンテキスト・インスタンスを終了する必要があります(同じ接続コンテキスト・インスタンスをセッション継続中に使用する場合は除く)。次に例を示します。

DefaultContext ctx = new DefaultContext(conn); // conn is JDBC connection
#sql [ctx] { SQL operation };
...
ctx.close(sqlj.runtime.ConnectionContext.KEEP_CONNECTION);
...

接続コンテキスト・インスタンスを終了しない場合、文ハンドルがセッション中に不足する可能性があります。また、基になるJDBC接続オブジェクトを終了しただけでは、文ハンドルは再利用されません。これは、アプリケーションをクライアントで実行するときの動作とは異なります。

デフォルトのOracle固有コード生成の場合、文は基になるJDBC文キャッシュにキャッシュされ、自動的に再生できます。

- Oracle固有コード生成をサーバーで実行するコードに使用する場合は、明示的なExecutionContextインスタンスを使用します。これによって、アプリケーションは、ISO標準SQLJコード生成で変換されたアプリケーションと完全に連係できるようになります。
1つの接続に1つのスレッドを使用する(つまり、1つのOracleセッションに1つのスレッドを使用する)場合、次の例のように、静的インスタンスを1つ使用すれば十分です。

public static ExecutionContext ec = new ExecutionContext();
...
#sql [ec] { SQL operation };    // use ec for all operations

1つの接続に複数のスレッドを使用する場合、実行メソッドを起動するたびに別のコンテキスト・インスタンスを使用する必要があります。

関連項目:
『Oracle Database JDBC開発者ガイドおよびリファレンス』

サーバーのデフォルトの出力デバイス

Oracle Java Virtual Machine(JVM)では、現行のトレース・ファイルがデフォルトの出力デバイスになります。サーバーで実行中のプログラムの標準出力(System.out.println()コールからの出力など)のすべてをユーザー画面に表示する場合は、次に示すように、DBMS_JAVAパッケージのSET_OUTPUT()プロシージャを実行します。バッファ・サイズはバイト単位(この場合は10,000バイト)で入力します。

sqlplus> execute dbms_java.set_output(10000);

バッファ・サイズを超過した出力は、失われます。

サーバー側で実行するコードをユーザー画面に明示的に出力されるようにする場合は、Java System.out.println()メソッドを使用するかわりに、PL/SQL DBMS_OUTPUT.PUT_LINE()プロシージャを使用します。PUT_LINE()プロシージャをオーバーロードする際には、VARCHAR2、NUMBERまたはDATEのいずれかを入力とし、出力対象を指定できます。

関連項目:
『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』

サーバー側での名前解決

サーバー側でのクラスのロードと名前変換は、クライアント側での場合とは異なるパラダイムに従って行われます。これは、サーバー側とクライアント側の環境自体が異なるためです。

Oracle JVMでのJava名の解決には次が必要です。

- クラス・リゾルバ仕様。クラス・スキーマ・オブジェクト(機能的には、クライアント側のCLASSPATHに相当)の解決の際に検索を行うスキーマのリストです。

- リゾルバ。サーバー内で相互参照するクラス・スキーマ・オブジェクト間のマッピングを維持します。

クラス・スキーマ・オブジェクトが解決されるまで、クラスのJavaオブジェクトのインスタンス化やクラスのメソッドの実行はできません。Java名へのクラス・スキーマ・オブジェクトの外部参照のすべてがバインドされると、そのクラス・スキーマ・オブジェクトの解決が可能になります。通常、Javaプログラムのすべてのクラスは、そのコンパイルまたはロードが終わるまで解決されません。これは、通常、再帰的に互いを参照できる複数のソース・ファイルでJavaプログラムが記述されているためです。

サーバーのJavaプログラムのすべてのクラス・スキーマ・オブジェクトが解決され、解決後にいずれも変更されていない場合、プログラムは事前リンクされて実行可能な状態になります。

注意:
loadjavaユーティリティによってクラスへの参照は解決されますが、リソースへの参照は解決されません。クライアント側での変換が必要なISO標準コードの場合は、リソースをサーバーのリソース・スキーマ・オブジェクトにロードする方法に注意してください。クライアント側変換用のSQLJ -ser2classフラグを有効化すると、SQLJプロファイルはクラス・ファイル中にロードされますが、リソース・ファイルは生成されません。この逆に-ser2classを有効化しなかった場合は、プロファイルが.serリソース・ファイル中にロードされます。

関連項目:
『Oracle Database Java開発者ガイド』

SQL名とJava名

ソース名、クラス名、リソースのスキーマ・オブジェクト名などのSQL名は、Java名の場合とは異なり、グローバルではありません。Java言語仕様(JLS)では、パッケージ名にインターネットのネーミング規則を適用して、グローバルに一意なJavaプログラム名を作成するように規定されています。対照的に、SQLの完全修飾名は、現行のスキーマおよびデータベースに関連してのみ解釈されます。たとえば、1つのデータベースにSCOTT.FIZZという名前のプログラムがあるとき、同じプログラムが他のデータベースでもSCOTT.FIZZと示されるとは限りません。実際、あるデータベースのSCOTT.FIZZから、他のデータベースのSCOTT.FIZZをコールすることも可能です。

このような内在する違いから、SQL名はJava名とは異なる方法で解釈および処理する必要があります。SQL名は相対名であり、プログラムが実行されるスキーマに従って解釈されます。これは、プログラムがそのスキーマに格納されたローカル・データをバインドする方法の要となります。Java名はグローバル名であり、その名前で指定するクラスは、任意の実行サイトにロードできます。ただし、これらのクラスはプログラムのコンパイルに使用されたクラスであることを前提とします。

クライアント側でのSQLJソースの変換とコンポーネントのロード

Oracle Database 11g で使用するSQLJコードをデプロイする方法の1つは、クライアント・コンピュータ上でSQLJトランスレータを実行し、変換、コンパイルおよびプロファイルのカスタマイズ(必要な場合)を行うことです。次に、通常はJavaアーカイブ(JAR)・ファイルを使用して、生成されたクラス・ファイルとリソース・ファイル(ある場合)をサーバーにロードします。サーバー側のトランスレータがサポートするのはOracle固有コード生成のみであるため、実際には、これがサーバー側でISO標準コードを使用する唯一の方法です。

クライアント・コンピュータ上でソースを開発する場合で、SQLJトランスレータを使用できるときは、この方法をお薦めします。サーバー側でオプション設定やエラー処理を行うと手間がかかるため、クライアント・マシン上でトランスレータを実行した方が効果的です。

ISO標準コードの場合、アプリケーションをサーバーにロードするときは、変換時にSQLJ -ser2classオプションを使用することをお薦めします。このオプションを使用すると、SQLJプロファイルが.serシリアライズ・リソース・ファイルから.classファイルに変換され、名前付けが簡略化されます。ただし、.classファイルに変換されたプロファイルはそれ以上カスタマイズできないため、注意が必要です。さらにカスタマイズするには、トランスレータを再実行して、プロファイルを再生成する必要があります。

関連項目:
「.serファイルから.classファイルへの変換(-ser2class)」

.classファイルや.serリソース・ファイルを直接またはJARファイルを使用してOracle Database 11g にロードすると、作成されるライブラリ・ユニットは、Javaクラス・スキーマ・オブジェクトおよびJavaリソース・スキーマ・オブジェクトとみなされます。SQLJプロファイル(ある場合)は、リソース・スキーマ・オブジェクト(.serファイルをロードしたときと同様にロードした場合)またはクラス・スキーマ・オブジェクト(変換時に-ser2classを有効化した場合や、.classファイルとしてロードした場合)の中にロードされます。

ここでは、次の項目について説明します。

- クラスおよびリソースのサーバーへのロード

- ロードされたクラスとリソース・スキーマ・オブジェクトの名前付け

- クラス・ファイルとリソース・ファイルをロードした後のアプリケーションの公開

- サーバー側でのクライアント・アプリケーションの実行の概要

クラスおよびリソースのサーバーへのロード

クライアント上でトランスレータを実行した後、Oracle loadjavaクライアント側ユーティリティを使用して、クラス・ファイルとリソース・ファイルをサーバーのスキーマ・オブジェクトにロードします。loadjavaコマンドラインでクラス・ファイルとリソース・ファイル(ある場合)を個別に指定するか、両ファイルをJARファイルにまとめてからコマンドラインでJARファイルを指定します。JARファイルまたはコマンドラインで指定された.classまたは.serファイル用に、個別のスキーマ・オブジェクトが作成されます。

次のように実行する例について考えてみます。

1. ISO標準コード生成を使用して、MyIterへのイテレータ宣言があるFoo.sqljを変換しコンパイルします。

2. Foo.sqljを変換するときに、-ser2class オプションを有効化します。

3. 結果ファイル(Foo.class、MyIter.class、Foo_SJProfileKeys.classおよびFoo_SJProfile0.class)をFoo.jarにアーカイブします。

コマンドラインでloadjavaを実行します(必要なオプションも指定します)。次にデフォルトのJDBC Oracle Call Interface(OCI)ドライバを使用した例を示します。

% loadjava -user scott Foo.jar
Password: password

または、次のように元のファイルを使用することも可能です。

% loadjava -user scott Foo.class MyIter.class Foo_SJProfileKeys.class Foo_SJProfile0.class
Password: password

または

% loadjava -user scott Foo*.class MyIter.class
Password: password

ロードにJDBC Thinドライバを使用する場合は、次の例のように指定して、-thinオプションと適切なURLを指定します。

% loadjava -thin -user scott@localhost:1521/myservice Foo.jar
Password: password

関連項目:
「コードの生成」および「Javaコンパイル」

注意:

- プロファイルの変換および生成時に-codegen=iso設定を使用し、そのプロファイルを.serファイルとしてサーバーにロードすると、クライアント側でカスタマイズされていなかったプロファイルが最初にカスタマイズされます。プロファイルがすでにカスタマイズされている場合は、そのままロードされます。

- スキーマのUSER_OBJECTSビューにアクセスすると、クラスとリソースが適切にロードされたかどうかを確認できます。

SQLJおよびJavaアプリケーションのサーバーへのロードには、loadjavaユーティリティの使用をお薦めします。ただし、次のようにSQL CREATE JAVAコマンドを使用する方法もあります。

CREATE OR REPLACE <AND RESOLVE> JAVA CLASS <NAMED name>;

CREATE OR REPLACE JAVA RESOURCE <NAMED name>;

関連項目:
『Oracle Database SQL言語リファレンス』および『Oracle Database Java開発者ガイド』

ロードされたクラスとリソース・スキーマ・オブジェクトの名前付け

ここでは、クラスやプロファイルをサーバー側にロードしたときの、この両方のスキーマ・オブジェクトの名前付けについて説明します。ただし、プロファイルが作成されるのは、ISO標準コード生成の場合のみです。

ISO標準コード生成では、アプリケーションをクライアント側で変換したときにSQLJ -ser2classオプションが有効であった場合、プロファイルは.classファイルに変換されているため、サーバーのクラス・スキーマ・オブジェクトにロードされます。-ser2classが有効になっていなかった場合、プロファイルは.serシリアライズ・リソースとして生成されるため、サーバーのリソース・スキーマ・オブジェクトにロードされます。

この後の説明では、サーバーで実行されるすべてのアプリケーションについて、デフォルトの接続コンテキスト・クラスを使用することを前提とします。このため、プロファイルは1つのみになります。

フル・ネームとショート・ネーム

サーバー側のスキーマ・オブジェクト名には、フル・ネームとショート・ネームという2つの形式があります。フル・ネームは完全修飾名であり、可能な場合は常にスキーマ・オブジェクト名として使用されます。フル・ネームが32文字以上の場合、またはフル・ネームに無効な文字やデータベース・キャラクタ・セットに変換できない文字が含まれている場合は、Oracle Database 11gでフル・ネームがショート・ネームに変換されて、スキーマ・オブジェクト名として使用されます(フル・ネームおよびショート・ネームの両方の名前、およびその変換方法は記録されています)。フル・ネームが31文字以内で、無効な文字や変換できない文字が含まれていない場合は、フル・ネームがスキーマ・オブジェクト名として使用されます。

DBMS_JAVAプロシージャでショート・ネームからフル・ネームを取得するときやその逆を実行するときの考慮事項など、スキーマ・オブジェクト名および他のファイルのネーミング規則に関する考慮事項については、『Oracle Database Java開発者ガイド』を参照してください。

ロードされたクラスのフル・ネーム

ISO標準コード生成を使用し、-ser2classフラグが有効な場合、ロードされるクラスにはプロファイル・ファイルが含まれます。.classファイルをサーバーにロードすると作成されるクラス・スキーマ・オブジェクトのフル・ネームは、元のソース・コード中のパッケージおよびクラス名によって決定されます。コマンドラインまたはJARファイルで指定するPATHは、スキーマ・オブジェクトの名前付けには影響しません。たとえば、Foo.classが、ソース・コードでx.yパッケージにあると指定されたFooクラスで構成される場合、作成されるクラス・スキーマ・オブジェクトのフル・ネームは次のようになります。

x/y/Foo

拡張子.classが削除されていることに注意してください。

Foo.sqljでイテレータMyIterが宣言されている場合、そのクラス・スキーマ・オブジェクトのフル・ネームは、次のようになります(ネストされたクラスでない場合は、それ自体のスキーマ・オブジェクトはありません)。

x/y/MyIter

さらに、ISO標準コード生成を使用している場合のフル・ネームは、次のようになります。

- Foo.sqljの変換時にSQLJで生成される関連プロファイルキーのクラス・ファイルは、Foo_SJProfileKeys.classです。したがって、そのクラス・スキーマ・オブジェクトのフル・ネームは、次のようになります。

x/y/Foo_SJProfileKeys

- アプリケーションの変換時に-ser2classオプションが有効であった場合、プロファイルはFoo_SJProfile0.classファイルに生成されています。したがって、クラス・スキーマ・オブジェクトのフル・ネームは、次のようになります。

x/y/Foo_SJProfile0

ロードされたリソースのフル・ネーム

ここで説明する内容が適用されるのは、ISO標準コード生成を使用していて、アプリケーションの変換時に-ser2classオプションが無効であった場合、またはアプリケーションで他のJavaシリアライズ・リソース(.ser)ファイルを使用する場合のみです。

リソース・スキーマ・オブジェクトとクラス・スキーマ・オブジェクトでは、名前付けの方法が異なります。リソース・スキーマ・オブジェクトの名前は、リソースの内容には依存しません。そのフル・ネームには、JARファイルやloadjavaコマンドラインに示される名前と同様に、PATHも含まれます。また、.ser拡張子は削除されません。

リソース名は、実行時にリソースの場所を示すために使用されます。リソース名には必ず正しいPATHを指定することが重要です。サーバーでは、Javaがクライアント上でリソースを検索するときに使用する相対パスおよびファイル名が、リソースの正しいフル・ネームになります。

SQLJプロファイルの場合は、トランスレータの-dオプションに(パッケージ名に従って)指定したディレクトリの下のサブディレクトリが、フル・ネームになります。-dオプション(生成される.classおよび.serファイルの最上位の出力ディレクトリを指定するために使用)に/mydirを設定した場合に、アプリケーションがabc.defパッケージに含まれているときは、変換で生成される.classおよび.serファイルは/mydir/abc/defディレクトリに配置されます。

関連項目:
「.serおよび.classファイルの出力ディレクトリ(-d)」

実行時には、/mydirをCLASSPATHで指定することになります。Javaではこのディレクトリの下にあるabc/defディレクトリでアプリケーション・コンポーネントが検索されます。このため、このアプリケーションをサーバーにロードするときは、コマンドラインでファイル検索箇所として指定したパスがパッケージ名をも示すように、loadjavaまたはjarを-dディレクトリから実行する必要があります。次に例を示します(%はシステム・プロンプトです)。

% cd /mydir
% loadjava <...options...> abc/def/*.class abc/def/*.ser

または、次のようにJARファイルを使用することも可能です。

% cd /mydir
% jar -cvf myjar.jar abc/def/*.class abc/def/*.ser
% loadjava <...options...> myjar.jar

アプリケーションがAppで、プロファイルがApp_SJProfile0.serの場合、前述の例のいずれでも、作成されるリソース・スキーマ・オブジェクトのフル・ネームが次のように正しく設定されます。

abc/def/App_SJProfile0.ser

.serが保持されていることに注意してください。

-dには、そのディレクトリ階層に他の内容が含まれないディレクトリを設定することをお薦めします。このように設定すると、JARユーティリティを次のように実行して、アプリケーション・コンポーネントを再帰的に取得できます。

% cd /mydir
% jar -cvf myjar.jar *
% loadjava <...options...> myjar.jar

クラス・ファイルとリソース・ファイルをロードした後のアプリケーションの公開

サーバー側でJavaコードを使用する場合と同様に、サーバー側でSQLJコードを使用する場合にも、事前に最上位メソッドを公開する必要があります。公開する場合は、コール記述子の記述、データ型のマッピング、パラメータ・モードの設定を行います。

関連項目:
『Oracle Database Java開発者ガイド』

サーバー側でのクライアント・アプリケーションの実行の概要

ここでは、サーバーでクライアント・アプリケーションを実行する手順について要約します。例では、NamedIterDemoと呼ばれるデモ・アプリケーションを使用します。

1. アプリケーション・コンポーネントとしてJARファイルを作成します。NamedIterDemoのコンポーネントとしては、SalesRec.classの他、アプリケーション・クラスやプロファイル(ある場合)などが挙げられます。
JARファイルniter-server.jarを作成するには、次のようにします。

% jar cvf niter-server.jar Named*.class Named*.ser SalesRec.class connect.properties

.serファイルは、ISO標準コード生成の場合にのみ使用します。

2. JARファイルをサーバーにロードします。
loadjavaは次のように指定します。この例に示したように指定した場合、loadjavaでのファイルのロードにはOCIドライバが使用されます。-resolveオプションにより、クラス・ファイルが解決されます。

% loadjava -oci -resolve -force -user scott niter-server.jar
Password: password

3. アプリケーション用に、SQLラッパーをサーバーに作成します。
たとえば、次のSQL*Plusスクリプトを実行します。

set echo on
set serveroutput on
set termout on
set flush on

execute dbms_java.set_output(10000);

create or replace procedure SQLJ_NAMED_ITER_DEMO as language java
name 'NamedIterDemo.main (java.lang.String[])';
/

DBMS_JAVA.SET_OUTPUT()ルーチンでは、デフォルトの出力が、トレース・ファイルではなくユーザー画面へ戻されます。入力パラメータには、バイト単位でバッファ・サイズを指定します。

4. ラッパーを実行します。
次に例を示します。

sqlplus> call SQLJ_NAMED_ITER_DEMO();

SQLJソースのロードとサーバーでの変換

サーバーで使用するSQLJコードを作成する場合には、ソース・コードをサーバーにロードして、サーバーで直接変換する方法もあります。この方法では、Oracle JVMの埋込みSQLJトランスレータを使用します。ここでも、クライアント・コンピュータ上でソースが作成されたことを前提とします。

注意:
サーバー側SQLJトランスレータでは、ISO標準生成コードはサポートされません。そのようなコードをサーバーで使用する場合、クライアントで変換して、個々のクラス・ファイルおよびリソースをサーバーにロードする必要があります。

サーバーへのSQLJソースのロードは、原則的にはサーバーへのJavaソースのロードと同じであり、loadjava -resolveオプションなどのコンパイル・オプションが設定されている場合は、変換が暗黙的に実行されます。.sqljソース・ファイルをOracle Database 11gに直接またはJARファイルを使用してロードすると、結果として生成されたライブラリ・ユニットにはソース・コードが格納されており、このライブラリ・ユニットはJavaソース・スキーマ・オブジェクトと呼ばれます。ソース・ファイルごとに個別のスキーマ・オブジェクトが作成されます。

変換とコンパイルが行われると、生成されたクラスに対する結果のライブラリ・ユニットは、Javaクラス・スキーマ・オブジェクトと呼ばれます。これは、クライアント側で作成された.classファイルからサーバーに直接にロードした場合と同じ名前です。クラスごとに個別のスキーマ・オブジェクトが作成されます。リソース・スキーマ・オブジェクトは、サーバーにロードしてあるプロパティ・ファイルに使用されます。

ここでは、次の項目について説明します。

- SQLJソース・コードのサーバーへのロード

- サーバー側の埋込みトランスレータでサポートされるオプション

- ロードされたソース、生成されたクラスおよびリソース・スキーマ・オブジェクトの名前付け

- サーバー側埋込みトランスレータからのエラー出力

- ソース・ファイルをロードした後の、アプリケーションの公開

関連項目:
『Oracle Database SQL言語リファレンス』および『Oracle Database Java開発者ガイド』

SQLJソース・コードのサーバーへのロード

ソースをサーバーにロードするには、(.classファイルではなく).sqljファイルに対して、Oracle loadjavaクライアント側ユーティリティを実行します。loadjava -resolveオプションを有効にして.sqljファイルをロードすると、ロード時にサーバー側の埋込みトランスレータが実行され、アプリケーションの変換およびコンパイルが行われます。それ以外の場合は、変換が行われずにソースがソース・スキーマ・オブジェクトにロードされます。ただしこの場合は、ソース中に定義されているクラスを最初に使用しようとしたときに、ソースは暗黙的に変換およびコンパイルされます。クライアント側SQLJにはこの暗黙的変換に相当するものがありません。

たとえば、loadjavaは、システム・プロンプトから次のように実行します。

% loadjava -user scott -resolve Foo.sqlj
Password: password

または、ロードにJDBC Thinドライバを使用することも可能です。

% loadjava -thin -user scott@localhost:1521/myservice -resolve Foo.sqlj
Password: password

いずれの方法でも、ソース・スキーマ・オブジェクトに加えて、適切なクラス・スキーマ・オブジェクトが作成されます。

ただし、loadjavaを実行する際は、事前にSQLJオプションを正しく設定する必要があります。エンコーディングの設定は、サーバー側SQLJ encodingオプションではなく、次のようにloadjavaのコマンドラインで指定できることに注意してください。

% loadjava -user scott -resolve -encoding SJIS Foo.sqlj
Password: password

実際のユーティリティを実行するloadjavaスクリプトの格納場所は、ORACLE_HOME ディレクトリのbinサブディレクトリです。このディレクトリは、Oracleをインストールすると自動的に作成されます。

注意:

- JARファイルの処理では、loadjavaによって最初に.sqljファイル、.javaファイルおよび.classファイルが処理されます。次に、セカンド・パスが作成され、他のすべてがJavaリソース・ファイルとして処理されます。

- .sqljファイルは、同じ.sqljファイルの処理で生成された.classファイルとともにロードすることはできません。このようにロードすると、サーバーで生成中のクラスやプロファイルと同じクラスに対してサーバーがロードを試みることになるため、競合が発生します。

- 複数の.sqljファイルをJARファイルに入れて、JARファイルをloadjavaに指定できます。

- スキーマのUSER_OBJECTSビューにアクセスすると、クラスが適切にロードされていることを確認できます。

SQLJおよびJavaアプリケーションのサーバーへのロードには、loadjavaユーティリティの使用をお薦めします。ただし、次のようにSQL CREATE JAVAコマンドを使用する方法もあります。

CREATE OR REPLACE <AND COMPILE> JAVA SOURCE <NAMED srcname> <AS loadname>;

.sqljファイルにAND COMPILEを指定すると、その時点でのソースが変換およびコンパイルされ、ソース・スキーマ・オブジェクトの他に、必要に応じてクラス・スキーマ・オブジェクトが作成されます。それ以外の場合は、変換やコンパイルが行われません。この場合、ソース・スキーマ・オブジェクトのみが作成されます。ただし、後者の場合は、ソース内のクラスを最初に使用しようとしたときに、ソースが暗黙的に変換およびコンパイルされます。

注意:
初めてソース・ファイルをロードすると、定義済クラスの確認など、ソース・コードのチェックが行われます。このときにエラーが検出されると、ロードが失敗します。

サーバー側の埋込みトランスレータでサポートされるオプション

サーバー側SQLJのトランスレータでは、次のオプションを使用できます。

- encoding

- online

- debug

ここでは、サーバー側SQLJでの固定した設定を説明してから、これらのオプションについて説明します。loadjavaユーティリティとその-resolveオプションについても説明します。

サーバー側SQLJトランスレータでの固定の設定

クライアント側のSQLJトランスレータのオプションによってサポートされる次の設定は、サーバー側トランスレータでは固定です。

- サーバーでは、オンライン・セマンティクス・チェックとオフライン解析の両方がデフォルトで有効であり、これはクライアントでのデフォルトの-parse=both設定に相当します。この設定をオーバーライドして、オンライン・セマンティクス・チェックをonlineオプションで無効にすることはできますが、オフライン解析を無効にすることはできません。

関連項目:
「オンライン・セマンティクス・チェックとオフライン解析との比較」

- サーバー側では、Oracle固有コード生成が使用されます。これは、クライアント側のデフォルトの-codegen=oracle設定に相当します。この設定は固定です。

関連項目:
「Oracle固有コード生成(プロファイルなし)」

- サーバー側での変換時に生成されたクラス・スキーマ・オブジェクトは、SQLJソース・コードをマッピング先とする行番号を自動的に参照します。クライアント側での変換時に-linemapオプションを有効化すると、サーバー側と同様の自動参照が行われます。

関連項目:
「SQLJソース・ファイルとの行マッピング(-linemap)」

encodingオプション

このオプションには、サーバー側にロードするときのソース・コードの解釈に使用するエンコーディングを指定します。encodingオプションは、ソースのロード時にコンパイルの有無にかかわらず、使用されます。また、loadjavaを使用してSQLJアプリケーションをサーバー側にロードする別の方法としては、loadjavaコマンドラインでエンコーディングを指定する方法もあります。loadjavaコマンドラインで設定された文字エンコーディングは、このencodingオプションに優先します。

注意:
このオプションまたはloadjavaで文字エンコーディングが指定されていない場合は、loadjavaを実行したクライアントのfile.encodingで指定された文字エンコーディングが使用されます。

関連項目:
「入力および出力ソース・ファイルの文字エンコーディング(-encoding)」

onlineオプション

onlineオプションにtrue(デフォルト値)を設定すると、オンライン・セマンティクス・チェックが有効になります。セマンティクス・チェックは、ソースがロードされたスキーマに対して行われます。クライアント側でのオンライン・チェックでは、基本スキーマの指定は不要です。onlineオプションをfalseに設定すると、オフラインでチェックが行われます。

いずれの場合も、デフォルトのチェッカはoracle.sqlj.checker.OracleCheckerです。このチェッカにより、使用するJDBCドライバのバージョンとOracleのバージョンに応じてチェッカが選択されます。

関連項目:
「セマンティクス・チェッカおよびOracleCheckerフロントエンド(デフォルトのチェッカ)」

onlineオプションは、ソースの変換およびコンパイル時に使用されます。loadjava -resolveオプションを有効にしてこれをロードすると、即座に実行されます。それ以外の場合は、ソースで定義されたクラスを最初に使用しようとしたときに実行されます(変換およびコンパイルは暗黙的に行われます)。

注意:
サーバー側とクライアント側とでは、onlineオプションの使用方法が異なります。サーバー側でonlineオプション使用した場合、デフォルトのチェッカでのオンライン・チェックを有効にするフラグとしてのみ機能します。一方、クライアント側では、使用するチェッカを-onlineオプションで指定できますが、別途-userオプションでオンライン・チェックを有効にする必要があります。

debugオプション

このオプションにtrueを設定すると、.sqljまたは.javaソース・ファイルがサーバーでコンパイルされるときに、サーバー側のJavaコンパイラがデバッグ情報を出力します。これは、クライアント上で標準のjavacコンパイラを実行するときに、-gオプションを使用するのに相当します。

loadjava -resolveオプションを使用した場合、ロード中にソースがコンパイルされます。.sqljファイルの場合は、SQLJ変換の直後に実行されます。-resolveオプションを使用しない場合は、ソースで定義されたクラスを最初に使用しようとしたときに暗黙的な変換およびコンパイルが実行されます。

サーバーでのSQLJオプションの設定

サーバーでSQLJトランスレータを実行するときは、コマンドラインもプロパティ・ファイルも存在しません。トランスレータやコンパイラのオプションについての情報は、JAVA$OPTIONSという表の各スキーマに保持されます。この表のオプションを操作するには、DBMS_JAVAパッケージの次のファンクションおよびプロシージャを使用します。

- DBMS_JAVA.GET_COMPILER_OPTION()

- DBMS_JAVA.SET_COMPILER_OPTION()

- DBMS_JAVA.RESET_COMPILER_OPTION()

個々のパッケージやソースに対して個別のオプションを指定するには、set_compiler_option()を使用します。次を入力パラメータとして指定し、各パラメータは一重引用符で囲みます。

- パッケージ名(ドット区切りの名前)またはソース名
ショート・ネームではなくフル・ネームで指定します。パッケージ名を指定した場合、そのパッケージとサブパッケージのすべてのソースに、そのオプション設定が適用されます。ただし、特定のサブパッケージやソースに対して設定をオーバーライドした場合を除きます。

- オプション名

- オプション設定

SQL*Plusを使用して、DBMS_JAVAルーチンを実行します。

sqlplus> execute dbms_java.set_compiler_option('x.y', 'online', 'true');
sqlplus> execute dbms_java.set_compiler_option('x.y.Create', 'online', 'false');

これら2つのコマンドで、x.yパッケージ内のすべてのソースに対するオンライン・チェックが有効になります。次に、Createソースのオンライン・チェックを無効し、Createソースに対してチェックが行われないようにします。

同様に、次のように指定して、x.yパッケージのエンコーディングをSJISに設定します。

sqlplus> execute dbms_java.set_compiler_option('x.y', 'encoding', 'SJIS');

サーバー側オプションについての注意事項

次の点に注意してください。

- スキーマ・オブジェクト名ではスラッシュ構文(パッケージ名としてabc/defなど)を使用しますが、パッケージ名やソース名のset_compiler_option()パラメータはドット区切りの名前(パッケージ名としてabc.defなど)を使用します。

- パッケージ名を指定するときは、サブパッケージにもオプションが適用されることに注意してください。a.b.MyPackageの設定では、次の形式の名前の付いたソース・スキーマ・オブジェクトすべてに対して、オプションが設定されます。

a/b/MyPackage/subpackage/...

- パッケージ名として''(スペースを挿入せずに一重引用符2つ)を指定した場合、ルートおよびすべてのサブパッケージに対してオプションが適用されます。結果的に、スキーマ内のすべてのパッケージにオプションが適用されることになります。

ロードされたソース、生成されたクラスおよびリソース・スキーマ・オブジェクトの名前付け

-resolveオプションを有効にしてloadjavaを.sqljファイルに使用するときなど、サーバー側のSQLトランスレータを使用する場合、基本的には、クライアント側で生成される内容と同じものが生成されます。出力には、ソース中に定義した各クラスのコンパイル済クラスおよび各イテレータや接続コンテキスト・クラスのコンパイル済クラスが含まれます。

このため、loadjavaで.sqljファイルをサーバーにロードして、変換およびコンパイルを行うと、次に示した各スキーマ・オブジェクトが作成されます

- 元のソース・コード用のソース・スキーマ・オブジェクト

- ソースで定義したすべてのクラス用のクラス・スキーマ・オブジェクト

- ソースで定義した各イテレータまたは接続コンテキスト・クラス用のクラス・スキーマ・オブジェクト
ただし、ユーザー定義型に型マップを指定するためでない場合は、サーバーで実行するコードに接続コンテキスト・クラスを宣言する必要はありません。

これらのスキーマ・オブジェクトのフル・ネームは、後述の方法で決定されます。作成されるスキーマ・オブジェクトとその名前を出力するには、loadjava -verboseオプションを指定します。

ソースのフル・ネーム

ソース・ファイルをサーバーにロードすると、変換やコンパイルが行われるかどうかにかかわらず、ソース・スキーマ・オブジェクトが作成されます。このスキーマ・オブジェクトのフル・ネームは、ソース・コード中のパッケージ名とクラス名によって決定されます。コマンドラインでloadjavaに対して指定するPATHは、スキーマ・オブジェクトの名前付けには影響しません。

たとえば、Foo.sqljがx.yパッケージ内のFooクラスを定義し、他のクラスを定義または宣言しない場合、作成されるソース・スキーマ・オブジェクトのフル・ネームは次のようになります。

x/y/Foo

拡張子.sqljが削除されていることに注意してください。

クラスを追加定義したり、イテレータ・クラスや接続コンテキスト・クラスを宣言した場合、ソース・スキーマ・オブジェクトの名前は、最初に出現したPublicクラス定義またはクラス宣言に従って付けられ、Publicクラスがないときは、最初のクラス定義に従って付けられます。サーバー側では、1つのソースの中に複数のPublicクラスを定義することも可能です。

前の例と同じx.yパッケージ中のFoo.sqljに、まずPublicクラスBarを、次にクラスFooを定義したとします。このBarの定義の前にpublicイテレータ・クラスまたは接続コンテキスト・クラスを宣言しなかった場合には、作成されるソース・スキーマ・オブジェクトのフル・ネームは次のようになります。

x/y/Bar

ただし、BarクラスとFooクラスの定義の前に、publicイテレータ・クラスMyIterが宣言されている場合、作成されるソース・スキーマ・オブジェクトのフル・ネームは次のようになります。

x/y/MyIter

生成されたクラスのフル・ネーム

クラス・スキーマ・オブジェクトは、ソース中に定義されているクラス、宣言済イテレータおよびプロファイルキー・クラスのそれぞれに対して生成されます。クラス・スキーマ・オブジェクトは、ソース・コードのクラス名およびパッケージ名に基づいて名前付けされます。

ここでも、前述の「ソースのフル・ネーム」の例を使用します。ソース・コード中にx.yパッケージを指定し、最初にPublicクラスBar、次にクラスFooを定義した後で、publicイテレータ・クラスMyIterを宣言したとします。定義および宣言されたクラスのクラス・スキーマ・オブジェクトには、次のようにフル・ネームが付けられます。

x/y/Bar
x/y/Foo
x/y/MyIter

.classが付けられていないことに注意してください。

注意:
ソース名は、最初に定義されているPublicクラスの名前と同じにするか、Publicクラスが未定義の場合は、最初に定義されているクラスの名前と同じにすることをお薦めします。このようにすると、クライアント側とサーバー側で違う動作をすることを回避できます。

元のソース・ファイルの名前や、ソースのサーバーへのロード時に指定するPATHは、生成されるクラスの名前付けには影響しません。コードで内部クラスや無名クラスを定義する場合、これらのクラスは標準のjavacコンパイラのネーミング規則に従って名前付けされます。

サーバー側埋込みトランスレータからのエラー出力

サーバー側のSQLJエラー処理は、サーバー側での一般的なJavaエラー処理と同様に行われます。SQLJエラーは、ユーザー・スキーマのUSER_ERRORS表に出力されます。この表のTEXT列からSELECTを行うと、特定のエラー・メッセージを取得できます。

ただし、SQLJソースのロードにloadjavaを使用する場合は、loadjavaによってサーバー側トランスレータからのエラー・メッセージのキャプチャおよび書込みが行われます。

情報メッセージや非表示にできる警告は、サーバー側トランスレータで出力しないようにできます。これは、クライアント側トランスレータで-warn=noportable,noverbose(デフォルト)が設定された場合と同じです。

関連項目:
「トランスレータからの警告(-warn)」

ソース・ファイルをロードした後の、アプリケーションの公開

サーバー側でJavaコードを使用する場合と同様に、サーバー側でSQLJコードを使用する場合にも、事前に最上位メソッドを公開する必要があります。公開する場合は、コール記述子の記述、データ型のマッピング、パラメータ・モードの設定を行います。詳細は、『Oracle Database Java開発者ガイド』を参照してください。

Javaスキーマ・オブジェクトの削除

loadjavaユーティリティを補足するために、Javaソース、クラスおよびリソース・スキーマ・オブジェクトを削除するdropjavaユーティリティが提供されています。loadjavaを使用してサーバーにロードしたスキーマ・オブジェクトを削除する場合は、必ずdropjavaを使用することをお薦めします。

dropjavaユーティリティでは、コマンドラインのファイル名とJARファイルの内容がスキーマ・オブジェクト名に変換され、スキーマ・オブジェクトが削除されます。.sqlj、.java、.class、.serおよび.jarの各ファイルは、任意の順序でコマンドラインに指定できます。

Javaスキーマ・オブジェクトは、必ず最初にロードしたときと同じ方法で削除することをお薦めします。.sqljソース・ファイルをロードしてからサーバー側で変換した場合は、同じソース・ファイルに対してdropjavaを実行します。クライアント側で変換を行ってからクラスとリソースを直接ロードした場合は、同じクラスとリソースに対してdropjavaを実行します。

たとえば、Foo.sqljに対してloadjavaを実行した場合は、次のように同じファイル名を指定してdropjavaを実行します。

% dropjava -user scott/password Foo.sqlj

プログラムをクライアント側で変換してから、生成されたコンポーネントを含むJARファイルでロードした場合は、同じJARファイル名を使用してプログラムを削除します。

% dropjava -user scott/password Foo.jar

プログラムをクライアント側で変換してから、生成されたコンポーネントをloadjavaコマンドラインでロードした場合は、次のようにdropjavaコマンドラインで削除します(-codegen=oracleで、イテレータ・クラスがないことを想定しています)。

% dropjava -user scott/password Foo*.class

関連項目:
『Oracle Database Java開発者ガイド』

サーバー側のその他の考慮事項

ここでは、サーバーでのJavaマルチスレッドと再帰的SQLJコールについて説明します。次の項目について説明します。

- サーバーでのJavaマルチスレッド

- サーバーでの再帰的SQLJコール

- サーバーでのコードの実行状況の確認

サーバーでのJavaマルチスレッド

Javaマルチスレッドを使用するプログラムは、変更を加えなくてもOracle Database 11g で実行できます。ただし、クライアント側プログラムがマルチスレッドの使用によりスループットが向上するのに対して、サーバー側でJavaマルチスレッド・コードが実行される場合はそのようなメリットがありません。マルチスレッド・アプリケーションをサーバーに移植する場合は、次に示すOracle JVMとクライアント側JVMとのマルチスレッド機能の相違を考慮してください。

- サーバー内のスレッドは、同時処理ではなく順次処理されます。

- サーバーでは、1つのコール内のスレッドは、そのコールの終わりに消滅します。

- サーバー内のスレッドは、プリエンプティブにスケジュールされません。1つのスレッドが無限ループに入った場合、他のスレッドは実行できません。

Oracle Database 11g のJavaマルチスレッドを、一般的なOracleサーバーのマルチスレッドと混同しないでください。後者の場合はOracleの同時セッションであり、Javaマルチスレッドではありません。サーバーでは、多くのユーザーが自身のセッションで同時に実行することにより、拡張性とスループットが得られます。スループットを最大にするためのJavaの実行スケジューリング(1セッション内のコールごとなど)は、JavaではなくOracle Database 11g で行われます。

関連項目:
「SQLJでのマルチスレッド」

サーバーでの再帰的SQLJコール

SQLJでは通常、複数のSQLJ文で同じ実行コンテキスト・インスタンスを同時に使用することはできません。つまり、すでに使用されている実行コンテキスト・インスタンスの使用を試みた文は、前の文が完了するまでブロックされます。

ただし、この機能は、クライアント上よりも、サーバー上であまり望ましくありません。その理由は、異なるストアド・プロシージャまたはストアド・ファンクションは、通常であればすべてデフォルトの実行コンテキスト・インスタンスを使用しますが、再帰的な状況においては、誤ってこの同じ実行コンテキスト・インスタンスを同時に使用しようとする可能性があるためです。たとえば、あるストアド・プロシージャがSQLJ文を使用して、SQLJ文を使用する別のストアド・プロシージャをコールする可能性があります。これらのストアド・プロシージャを最初に作成する時点では、このような状況がいつ発生するかを把握できないため、特定の実行コンテキスト・インスタンスをSQLJ文のいずれかに対して指定することは疑問です。

この状況に対処するため、SQLJでは、再帰的コールによってこのような状況が生じた場合に、複数のSQLJ文が同じ実行コンテキスト・インスタンスを同時に使用できるようになっています。

ここでは、再帰的な状況の例を考えて、実行コンテキスト・インスタンスのステータス情報がどのようになるかを説明します。すべての文で、デフォルトの接続コンテキスト・インスタンスとそのデフォルトの実行コンテキスト・インスタンスが使用されると想定します。ストアド・プロシージャproc1が持つSQLJ文が、同じくSQLJ文を持つストアド・プロシージャproc2をコールする場合、proc2内の各文は、proc1のプロシージャ・コールが使用しているときに同じ実行コンテキスト・インスタンスを使用します。

proc2の各SQLJ文によって、その文のステータス情報が実行コンテキスト・インスタンスに書き込まれるため、必要な場合は、各文の完了後にその情報を取得することができます。proc2をコールするproc1の文からステータス情報が実行コンテキスト・インスタンスに書き込まれるのは、proc2の実行が終了し、プログラム・フローがproc1に戻り、proc2をコールしたproc1内の操作が完了した後です。

再帰的な状況でも実行コンテキストのステータス情報が正しく処理されるように、実行コンテキスト・メソッドは、SQL操作が完了した後にステータス情報を更新するように定義されています。

注意:

- サーバー側で実行されるコードの中に、実行コンテキスト・ステータスや制御メソッドを使用する計画を立てるたびに、必要に応じて別個の実行コンテキスト・インスタンスを使用することをお薦めします。

- 前述の例で別個の実行コンテキスト・インスタンスを使用せず、しかも制御パラメータを変更するためにproc2から実行コンテキスト・インスタンスへのメソッドをコールした場合、それ以降にproc1で実行される操作に影響します。

- バッチ更新は、再帰的コールでは使用できません。デフォルトでは、バッチ処理(有効化してある場合)を実行できるのは、最上位プロシージャのみに限定されています。こうした制限を免れるには、実行コンテキスト・インスタンスを明示的に使用する必要があります。

関連項目:
「実行コンテキストのメソッド」

サーバーでのコードの実行状況の確認

作成したコードが実際にサーバー側で実行可能かどうかを確認する場合、java.lang.Systemクラスのstatic getProperty()メソッドを使用してoracle.server.versionのJavaプロパティを取得する方法が便利です。このプロパティにバージョン番号が指定されている場合、コードはサーバーで実行されます。このバージョン番号がNULLの場合、Oracleサーバーではコードが実行されません。次にその例を示します。

...
if (System.getProperty("oracle.server.version") != null
{
// (running in server)
}
...

注意:
サーバー側でgetProperties()メソッドは使用しないでください。セキュリティ例外の原因となります。

A カスタマイズおよび専用カスタマイザ

プロファイルとプロファイルのカスタマイズについては、「SQLJプロファイル」を参照してください。この付録では、技術的な詳細を示し、カスタマイザ・オプション、デフォルトのOracleカスタマイザ以外のカスタマイザの使用方法についても説明します。

また、Oracleの専用カスタマイザについても、特にプロファイルのセマンティクス・チェック用のSQLCheckerCustomizer、およびデバッグに使用するオーディタのインストール用のAuditorInstallerを中心に説明します。

内容は次のとおりです。

- プロファイルについて

- プロファイルのカスタマイズについて

- カスタマイズ・オプションとカスタマイザの選択

- プロファイルのJARファイル

- プロファイルのセマンティクス・チェック用のSQLCheckerCustomizer

- デバッグ用のAuditorInstallerカスタマイザ

注意:
この付録の説明は、デフォルトのOracle固有のコード生成(-codegen=oracle)を使用する場合は適用されません。

プロファイルについて

SQLJプロファイルには、埋込みSQL操作に関する情報が含まれています。プロファイルは、アプリケーションで使用される接続コンテキスト・クラスごとに、個別に作成されます。プロファイルは、SQLJトランスレータのコード生成フェーズで作成され、カスタマイズ・フェーズでカスタマイズされます。カスタマイズすると、アプリケーションでベンダー固有のデータベース機能を使用できるようになります。このようなベンダー固有の操作を別々のプロファイルにまとめると、それ以外の生成コードを汎用として使用できます。

各プロファイルには、関連する接続コンテキスト・クラスを使用するSQLJ文に対する一連のエントリが含まれています。各エントリは、アプリケーション内の1つのSQL操作に対応しています。

プロファイルは、アプリケーションとパッケージ化されるリソース・ファイルに、シリアライズされたオブジェクトとして保存されます。このため、プロファイルをいつでもロード、読取りおよび変更(追加または再カスタマイズ)できます。プロファイルのカスタマイズ時に、情報は追加されますが、削除されることはありません。プロファイルを複数回カスタマイズしても、以前のカスタマイズ内容が失われることはなく、アプリケーションは複数の環境で実行可能なままです。これをバイナリ移植性と呼びます。

プロファイルにバイナリ移植性を持たせるために、Oracle SQLJはSQLJの業界標準に従って実装されています。

コード生成時のプロファイルの生成

トランスレータは、コード生成時に次のようにプロファイルを生成します。

1. sqlj.runtime.profile.Profileクラスのインスタンスとして、プロファイル・オブジェクトを生成します。

2. 生成されたプロファイル・オブジェクトに、埋込みSQL操作(関連する接続コンテキスト・クラスを使用するSQLJ文)に関する情報を挿入します。

3. プロファイル・オブジェクトをシリアライズして、Javaリソース・ファイルに保存します。このファイルはプロファイル・ファイルと呼ばれ、ファイル名拡張子として.serが付加されます。

注意:
Oracle SQLJ実装には、トランスレータに自動的にこれらの.serファイルを.classファイルに変換させるオプションがあります。.serファイルをサポートしていないブラウザがあるため、変換されたアプリケーションをサーバーにロードするときに、_serファイルのロードに手間が必要なためです。ただし、いったん自動変換したプロファイルは、カスタマイズの対象にならなくなります。詳細は、「.serファイルから.classファイルへの変換(-ser2class)」を参照してください。

「コードの生成」で説明したように、アプリケーションFooのプロファイル・ファイル名は、次のようになります。

Foo_SJProfilen.ser

SQLJでは、Foo_SJProfile0.ser、Foo_SJProfile1.serなどのファイルが、コード中に使用した接続コンテキスト・クラスの数に応じて生成されます。-ser2classオプションが設定されている場合は、Foo_SJProfile0.class、Foo_SJProfile1.classなどのファイルが生成されます。

各プロファイルには、SQLJの実行時にコールされるgetConnectedProfile()メソッドが含まれています。このメソッドは、JDBCのConnectionオブジェクトと同等のものを戻しますが、これには追加の機能が付いています。詳細は、「カスタマイズされたプロファイルの実行時の機能」を参照してください。

注意:
プロファイル・オブジェクトとは、シリアライズされる前の元の状態のプロファイルを示します。プロファイル・ファイルとは、シリアライズされた状態(.serファイル)を示します。

プロファイル・エントリの例

ここでは、SQLJ実行文と、生成されるプロファイル・エントリの例を示します。ここに示すプロファイル・エントリは、わかりやすいように関係のない部分は省略して、テキストで表記してあります。

プロファイル・エントリでは、ホスト変数がJDBC構文(疑問符)に置き換えられることに注意してください。

SQLJ実行文

次のような宣言があるとします。

#sql iterator Iter (double sal, String ename);

また、次のような実行文があるとします。

String empname = 'Smith';
Iter it;
...
#sql it = { SELECT ename, sal FROM emp WHERE ename = :empname };

対応するSQLJプロファイル・エントリ

=================================================================
...
#sql { SELECT ename, sal FROM emp WHERE ename = ? };
...
PREPARED_STATEMENT executed through EXECUTE_QUERY
role is QUERY
descriptor is null
contains one parameter
1. mode: IN, java type: java.lang.String (java.lang.String),
sql type: VARCHAR, name: ename, ...
result set type is NAMED_RESULT
result set name is Iter
contains 2 result columns
1. mode: OUT, java type: double (double),
sql type: DOUBLE, name: sal, ...
2. mode: OUT, java type: java.lang.String (java.lang.String),
sql type: VARCHAR, name: ename, ...
=================================================================

注意:
ここに示すプロファイル・エントリは、便宜上テキストで表記してありますが、実際のプロファイルはテキスト形式ではありません。ただし、SQLJ -P-printオプションを使用するとテキストとして出力することができます(「カスタマイザ・ハーネスのオプションの概要」を参照)。

プロファイルのカスタマイズについて

ISO SQLJコードを使用している場合、SQLJソース・ファイルに対してsqljスクリプトを実行すると、自動的にカスタマイズが行われます。その際、コード生成段階に作成された各プロファイルが、使用する特定のデータベース用にカスタマイズされます。デフォルトのoracle.sqlj.runtime.OraCustomizerというOracleカスタマイザを使用すると、Oracle11g固有の型拡張およびパフォーマンス強化機能を使用するように、プロファイルが最適化されます。

sqljスクリプトを実行して、既存のプロファイルをカスタマイズすることも可能です。SQLJコマンドラインで、個々の.serファイル、.serファイルを含むJARファイル、またはその両方を指定できます。

注意:

- デフォルトのOracleカスタマイザをトランスレータ実行時に使用する場合は、その実行時にOracle SQLJランタイムおよびOracle JDBCドライバがアプリケーションで必要になります。これらは、Oracleの拡張型をコード中に使用しない場合にも必要です。

- アプリケーションでカスタマイズ(接続のための処理)を行わない場合には、汎用SQLJランタイムが使用されます。

- SQLJで一度に実行できるのは、.sqljファイルや.javaファイルに対する処理(変換、コンパイルおよびカスタマイズの場合)、または.serファイルや.jarファイルに対する処理(カスタマイズのみの場合)のいずれか一方です。

カスタマイザ・ハーネスおよびカスタマイザの概要

Oracleカスタマイザを使用する場合も、その他のカスタマイザを使用する場合も、SQLJでのカスタマイズには、カスタマイザ・ハーネスと呼ばれるフロントエンドのカスタマイズ・ユーティリティが使用されます。

SQLJの実行時に指定できるカスタマイズ・オプションとしては、カスタマイザ・ハーネス用(あらゆるカスタマイザに適用できる一般的なカスタマイザ設定)およびカスタマイザ用(カスタマイザ固有の設定)があります。これらのオプションは、コマンドラインまたはプロパティ・ファイルで指定します。詳細は、「カスタマイズ・オプションとカスタマイザの選択」を参照してください。

カスタマイザは、プロパティを公開するために、標準のJavaBeans APIに適合するJavaBeansコンポーネントであることが必要です。また、customize()メソッドを指定しているsqlj.runtime.profile.util.ProfileCustomizerインタフェースを実装する必要があります。カスタマイザ・ハーネスは、カスタマイズするプロファイルごとに、カスタマイザ・オブジェクトのcustomize()メソッドをコールします。

Oracleカスタマイザは前述の要件を満たしています。このカスタマイザはoracle.sqlj.runtime.OraCustomizerクラスに定義されています。

カスタマイズ処理の手順

変換時のカスタマイズ処理は、次のように行われます。これは、SQLJの全体的な実行におけるカスタマイズ・フェーズの場合も、既存のプロファイルのみをカスタマイズする場合も同じです。

1. SQLJは、カスタマイザ・ハーネスを起動して、指定されているカスタマイズの一般オプションをそのカスタマイザ・ハーネスに渡します。

2. カスタマイザ・ハーネスは、使用するカスタマイザを起動して、指定されているカスタマイザ固有のオプションをそのカスタマイザに渡します。

3. カスタマイズのみを行うために、コマンドラインでJARファイルを指定してSQLJを実行した場合、カスタマイザ・ハーネスは、これらのJARファイル内のプロファイル・ファイルを検出して抽出します。

4. カスタマイザ・ハーネスは、各プロファイル・ファイルをプロファイル・オブジェクトにシリアライズ解除します(対象は、SQLJの全体的な実行で自動的に生成される.serファイル、カスタマイズのみを行うためにコマンドラインで指定した.serファイル、またはカスタマイズのみを行うために、コマンドラインで指定したJARから抽出された.serファイルです)。

5. データベース接続が必要なカスタマイザを使用している場合、カスタマイザ・ハーネスが接続を確立します。

6. カスタマイザ・ハーネスは、プロファイルごとに手順2でインスタンス化されたカスタマイザ・オブジェクトのcustomize()メソッドをコールします(カスタマイザをSQLJで使用するには、customize()メソッドが必要です)。

7. 通常、customize()メソッドは、各プロファイルの内容をカスタマイズして、そのカスタマイズ内容を同じプロファイルに登録します。ただし、これはカスタマイザで処理する内容に依存します。カスタマイザによっては、特別な処理を行うために、このようなカスタマイズと登録を必要としない場合があります。

8. カスタマイザ・ハーネスは、各プロファイルを再度シリアライズして.serファイルを生成します。

9. カスタマイズのみを行うために、コマンドラインでJARファイルを指定してSQLJを実行した場合、カスタマイザ・ハーネスは、カスタマイズされた各.serファイルで、カスタマイズ前の元の.serファイルを上書きし、JARの内容を再度生成します。

注意:

- プロファイルのカスタマイズ時にエラーが発生した場合、元の.serファイルは上書きされません。

- JARファイル内のプロファイルのカスタマイズ時にエラーが発生した場合、元のJARファイルは上書きされません。

- SQLJでは、一度に複数のカスタマイザを実行することは不可能です。1つのプロファイルに対して複数回カスタマイズを行うには、SQLJを複数回実行する必要があります。追加でカスタマイズを行う場合は、SQLJのコマンドラインでプロファイル名を直接入力します。

プロファイルのカスタマイズと登録

カスタマイザ・ハーネスは、customize()メソッドをコールして、プロファイルをカスタマイズします。その場合、このメソッドにプロファイル・オブジェクト、SQLJ接続コンテキスト・オブジェクト(接続が必要なカスタマイザを使用している場合)およびエラー・ログ・オブジェクト(カスタマイズ時に出力されたエラー・メッセージのログに使用)を渡します。

1回のSQLJの実行では、すべてのカスタマイズに同じエラー・ログ・オブジェクトが透過的に使用されます。カスタマイザ・ハーネスは、エラー・ログ・オブジェクトに書き込まれたメッセージを読み込み、標準出力(通常はディスプレイ)にリアルタイムで出力します。

各プロファイルには複数のエントリが含まれており、それぞれSQL操作に対応しています。(これらはアプリケーション内のSQL操作であり、そのプロファイルに対応付けられている接続コンテキスト・クラスのインスタンスが使用されます。)

customize()は、これらのエントリに対して特別な処理を行います。各エントリの構文の妥当性チェックのような簡単な処理の場合もあれば、元のエントリに特定のデータベースの機能を使用するための変更を加えて、新しいエントリを生成するような複雑な処理の場合もあります。

注意:

- customize()でプロファイル・エントリを処理しても、元のエントリが変更されることはありません。

- 特定の環境で使用できるようにプロファイルをカスタマイズしても、アプリケーションを他の環境で実行できなくなることはありません。プロファイルは、複数の環境で使用できるように、複数回カスタマイズすることが可能であり、これらのカスタマイズ間で互いに干渉することはありません。

カスタマイズ時のエラー・メッセージとステータス・メッセージ

カスタマイザ・ハーネスでのエラー・メッセージとステータス・メッセージは、SQLJトランスレータと同じ出力デバイスに出力されます。ただし、カスタマイズに関する警告メッセージは、非表示にはできません。

カスタマイザ・ハーネスによって生成されるエラー・メッセージは、次の4つのカテゴリに分類できます。

- 認識できないオプションまたは不正なオプション

- 接続のインスタンス化エラー

- プロファイルのインスタンス化エラー

- カスタマイザのインスタンス化エラー

カスタマイズ時に、カスタマイザ・ハーネスからステータス・メッセージが報告されます。これらのメッセージを参照して、プロファイルが正しくカスタマイズされたかどうかを確認できます。次の3つのカテゴリに分類できます。

- プロファイルの変更状態

- JARファイルの変更状態

- 作成されたバックアップ・ファイル名(カスタマイザ・ハーネスのbackupオプションが設定されている場合)

この他にも、特定のカスタマイザのcustomize()のメソッドによって、カスタマイザ固有のエラーや警告が出力される場合があります。

カスタマイズ時には、プロファイル・カスタマイザがメッセージがエラー・ログに書き込み、カスタマイザ・ハーネスがログの内容をリアルタイムに読み取って、これらのメッセージと、ハーネスからの他の出力とあわせてSQLJの出力デバイスに出力します。ユーザーがエラー・ログの内容に直接アクセスする必要はありません。

カスタマイズされたプロファイルの実行時の機能

カスタマイズされたプロファイルは、それが対応付けられている接続コンテキスト・クラスの静的なメンバーです。アプリケーション内のSQLJ文ごとに、SQLJランタイムは、その文に関連付けられている接続コンテキスト・クラスとインスタンスを確認し、その接続コンテキスト・クラスのカスタマイズされたプロファイルと、特定の接続コンテキスト・インスタンスの基になるJDBC接続を使用して、接続プロファイルを作成します。この接続プロファイルをSQLJランタイムで使用すると、SQLJアプリケーションの実行時にベンダー固有の機能を利用できるようになります。

カスタマイズ・オプションとカスタマイザの選択

ここでは、プロファイルのカスタマイズ時のオプションについて説明します。これらのオプションは、次の3つのカテゴリに分類できます。

- カスタマイザ・ハーネスに対して指定するオプション。使用するカスタマイザに関係なく適用されます。
このオプションの例としては、一般オプション、接続オプション、専用カスタマイザを起動するオプションなどがあります。

- カスタマイザ固有のオプション。これらのオプションはカスタマイザ・ハーネスを介して、使用するカスタマイザに対して指定します。

- SQLJオプション。これらのオプションは、カスタマイズを行うかどうか、どのカスタマイザを使用するかなど、カスタマイズの基本事項を指定します。

どのカテゴリのオプションも、すべてSQLJコマンドラインまたはプロパティ・ファイルを使用して指定します。

ここでは、次の内容を取り上げます。

- カスタマイザ・ハーネスのオプションの概要

- カスタマイザ・ハーネスの一般オプション

- カスタマイザ・ハーネスの接続用オプション

- 専用のカスタマイザの起動に使用するカスタマイザ・ハーネスのオプション

- カスタマイザ固有のオプションの概要

- Oracleカスタマイザのオプション

- プロファイルのカスタマイズ用のSQLJトランスレータのオプション

デフォルトのOracleカスタマイザ以外のカスタマイザを選択するには、カスタマイザ・ハーネスのcustomizerオプション(「カスタマイザ・ハーネスのオプションの概要」を参照)またはSQLJの-default-customizerオプション(「プロファイルのカスタマイズ用のSQLJトランスレータのオプション」を参照)を使用します。

カスタマイザ・ハーネスのオプションの概要

Oracle SQLJ実装のカスタマイザ・ハーネスには、特定のカスタマイザ以外にも使用できるオプションがいくつか用意されています。このハーネスの各オプションは、カスタマイズ処理をフロントエンドで調整する際に使用されます。

カスタマイザ・ハーネスのオプションの構文

SQLJコマンドラインでカスタマイザ・ハーネス・オプションを設定する場合は、次の構文を使用します。

-P-option=value

または、SQLJプロパティ・ファイルで、次の構文を使用します。

profile.option=value

ブール値のオプション(フラグ)を有効にするには、次のように指定します。

-P-option

または

-P-option=true

ブール値のオプションは、デフォルトでは無効になっています。明示的に無効にするには、次のように指定します。

-P-option=false

このオプションの構文の詳細は、「プロファイル・カスタマイザに渡すオプション(-P)」および「プロパティ・ファイルの構文」を参照してください。

カスタマイザ・ハーネスでサポートされているオプション

カスタマイザ・ハーネスには、次の一般オプションを使用できます。

- backup: カスタマイズ前にプロファイルのバックアップ・コピーを作成するためのオプション

- context: リストされた接続コンテキスト・クラスに対応付けられているプロファイルのみをカスタマイズするためのオプション

- customizer: 使用するカスタマイザを指定するためのオプション

- digests: JARマニフェスト・ファイルのダイジェスト値を指定するためのオプション(JARファイルのカスタマイズを指定した場合のみ)

- help: カスタマイザ・オプションを表示するためのオプション(SQLJコマンドラインを使用した場合のみ)

- verbose: カスタマイズ時にステータス・メッセージを表示するためのオプション

カスタマイザ・ハーネスでは、次のカスタマイザ・データベース接続用オプションを使用できます。現在、Oracleカスタマイザでは、列定義(パフォーマンスの最適化)用のoptcolsオプションを有効化した場合にこれらのオプションが使用されます。また、SQLCheckerCustomizerと呼ばれる、プロファイルに対してセマンティクス・チェックを実行する特別なカスタマイザを使用した場合にも、これらのオプションが使用されます。

- user: このカスタマイズで使用する接続用ユーザー名を指定するためのオプション

- password: このカスタマイズで使用する接続用パスワードを指定するためのオプション

- url: このカスタマイズで使用する接続用URLを指定するためのオプション

- driver: このカスタマイズで使用する接続用JDBCドライバを指定するためのオプション

Oracleカスタマイザoptcolsフラグの詳細は、「Oracleカスタマイザの列定義オプション(optcols)」を参照してください。SQLCheckerCustomizerの詳細は、「プロファイルのセマンティクス・チェック用のSQLCheckerCustomizer」を参照してください。

次のコマンドは、カスタマイザ・ハーネス・オプションとして機能しますが、Oracle SQLJ実装で提供される特別なカスタマイザを介して実装されます。

- debug: デバッグ情報を指定したプロファイルに挿入し、実行時に出力するためのオプション。これはOracle SQLJのAuditorInstallerを起動する簡単な方法です。「デバッグ用のAuditorInstallerカスタマイザ」を参照してください。

- print: プロファイルの内容をテキスト・フォーマットで出力するためのオプション

- verify: 前のSQLJトランスレータ実行時に生成されているプロファイルに対してセマンティクス・チェック(変換時にソース・コードに行われるセマンティクス・チェックに相当)を行うためのオプション。これはOracle SQLJのSQLCheckerCustomizerを起動する簡単な方法です。「プロファイルのセマンティクス・チェック用のSQLCheckerCustomizer」を参照してください。

カスタマイザ・ハーネスの一般オプション

この項では、カスタマイザ・ハーネスでサポートされている一般オプションについて説明します。

プロファイル・バックアップ・オプション(backup)

backupフラグを使用すると、元のファイルに上書きする前に、各.jarファイルとスタンドアロンの.serファイルのバックアップ・コピーをハーネスで保存できます。(.jar内の.serファイル用のバックアップを別に作成する必要はありません。)

バックアップ・ファイル名には、拡張子として.baknが付加されます。nは、似た名前のファイルが存在する場合に、必要に応じて使用される数字です。バックアップ・ファイルが作成されるたびに、情報メッセージが出力されます。

スタンドアロンの.serファイルのカスタマイズ時にエラーが発生した場合は、元の.serファイルは上書きされず、バックアップも作成されません。同様に、JARファイル内の.serファイルのカスタマイズ時にエラーが発生した場合も、元のJARファイルは上書きされず、バックアップも作成されません。

このオプションのコマンドライン構文は、次のとおりです。

-P-backup<=true|false>

次にコマンドラインの例を示します。

-P-backup

プロパティ・ファイルの構文は、次のとおりです。

profile.backup<=true|false>

デフォルト値は、次のとおりです。

false

カスタマイズ接続コンテキスト・オプション(context)

contextオプションを使用すると、指定された接続コンテキスト・クラスに対応するプロファイルのみに、カスタマイズの対象を限定できます。クラスの完全修飾名を指定し、複数のクラスを指定する場合は各クラスをカンマで区切ります。次に例を示します。

-P-context=sqlj.runtime.ref.DefaultContext,foo.bar.MyCtxtClass

カンマの前後には、スペースは不要です。

このオプションが指定されていない場合は、対応付けられている接続コンテキスト・クラスに関係なく、すべてのプロファイルがカスタマイズされます。

コマンドライン構文は、次のとおりです。

-P-context=ctx_class1<,ctx_class2,...>

次にコマンドラインの例を示します。

-P-context=foo.bar.MyCtxtClass

プロパティ・ファイルの構文は、次のとおりです。

profile.context=ctx_class1<,ctx_class2,...>

次にプロパティ・ファイルの例を示します。

profile.context=foo.bar.MyCtxtClass

カスタマイザ・オプション(customizer)

customizerオプションを使用すると、使用するカスタマイザを指定できます。次に示すように、クラスの完全修飾名を指定します。

-P-customizer=oracle.sqlj.runtime.util.OraCustomizer

このオプションが設定されていない場合は、SQLJの-default-customizerオプションで指定されているカスタマイザが使用されます。このオプションでの設定を行わない場合、デフォルトの設定は次のようになります。

oracle.sqlj.runtime.util.OraCustomizer

コマンドライン構文は、次のとおりです。

-P-customizer=customizer_class

次にコマンドラインの例を示します。

-P-customizer=a.b.c.MyCustomizer

プロパティ・ファイルの構文は、次のとおりです。

profile.customizer=customizer_class

次にプロパティ・ファイルの例を示します。

profile.customizer=a.b.c.MyCustomizer

デフォルト値は、次のとおりです。

None

カスタマイズ用JARファイルのダイジェスト・オプション(digests)

JARファイルの生成時に、JARユーティリティでは、指定した1つ以上のアルゴリズムに基づいて、エントリごとに1つ以上のダイジェストを含めることが可能であり、後でJARファイル・エントリの整合性を検証することができます。ダイジェストは、概念的にはチェックサムと似ています。

JARファイルの更新時に、JARファイルに含まれているプロファイルをカスタマイズし、JARユーティリティを使用して新しいダイジェストを追加(または、既存のダイジェストを更新)する場合は、digestsオプションを使用して、1つ以上のアルゴリズムをカンマで区切って指定します。JARユーティリティは、これらのアルゴリズムを使用して、各エントリのダイジェストを生成します。JARユーティリティは、JARマニフェスト・ファイル内の各JARファイル・エントリに対して、アルゴリズムごとに1つのダイジェストを生成します。次のように、アルゴリズムを指定します。

-P-digests=SHA,MD5

カンマの前後には、スペースは不要です。

この例では、JARマニフェスト・ファイル内の各エントリについて、SHAおよびMD5の2つのダイジェストが生成されます。

注意:
JARマニフェスト・ファイルの詳細は、Sun社のサイトを参照してください。

コマンドライン構文は、次のとおりです。

-P-digests=algo1<,algo2,...>

次にコマンドラインの例を示します。

-P-digests=SHA,MD5

プロパティ・ファイルの構文は、次のとおりです。

profile.digests=algo1<,algo2,...>

次にプロパティ・ファイルの例を示します。

profile.digests=SHA,MD5

デフォルト値は、次のとおりです。

SHA,MD5

カスタマイズ用ヘルプ・オプション(help)

helpオプションを使用すると、カスタマイザ・ハーネスと、デフォルトのカスタマイザまたは指定されているカスタマイザのオプションを表示できます。ハーネスおよびOracleカスタマイザに関しては、各オプションの簡単な説明と現行の設定も表示されます。

ハーネスとデフォルトのカスタマイザ(Oracleカスタマイザ、またはSQLJの-default-customizerオプションで指定されているカスタマイザ)のオプションを表示するには、次のように指定します。

-P-help

次のように、helpオプションにcustomizerオプションを指定すると、特定のカスタマイザのオプションを表示できます。

-P-help -P-customizer=sqlj.runtime.profile.util.AuditorInstaller

注意:

- -P-helpオプションは、SQLJコマンドラインでのみ指定できます。SQLJプロパティ・ファイルでは使用できません。

- -P-helpフラグが有効になっている場合は、カスタマイズするプロファイルをコマンドラインで指定しても、カスタマイズは行われません。

コマンドライン構文は、次のとおりです。

-P-help <-P-customizer=customizer_class>

次にコマンドラインの例を示します。

-P-help

プロパティ・ファイルの構文は、次のとおりです。

NA

次にプロパティ・ファイルの例を示します。

NA

デフォルト値は、次のとおりです。

None

カスタマイズ用の詳細オプション(verbose)

verboseフラグを使用すると、カスタマイズ時にハーネスからステータス・メッセージを表示できます。これらのメッセージは、SQLJの他のメッセージと同じように、標準出力に書き込まれます。

コマンドライン構文は、次のとおりです。

-P-verbose<=true|false>

次にコマンドラインの例を示します。

-P-verbose

プロパティ・ファイルの構文は、次のとおりです。

profile.verbose<=true|false>

次にプロパティ・ファイルの例を示します。

profile.verbose

デフォルト値は、次のとおりです。

false

カスタマイザ・ハーネスの接続用オプション

ここでは、カスタマイザ・ハーネスでサポートされている接続オプションについて説明します。次のように使用されます。

- Oracleカスタマイザでは、列定義にのみデータベース接続を使用します。Oracleカスタマイザのoptcolsオプションを有効にしない場合は、カスタマイザ・ハーネスのuser、password、urlおよびdriverオプションを設定する必要はありません。

- SQLCheckerCustomizerと呼ばれる、プロファイルに対してセマンティクス・チェックを実行する特別なカスタマイザでは、オンライン・チェックの際にカスタマイザ・ハーネスのuser、password、urlおよびdriver設定が使用されます。
SQLJコマンドラインで-P-verifyを使用して、カスタマイザを起動します。

注意:
カスタマイザ・ハーネスのuser、password、urlおよびdriverオプションと、トランスレータの同名のオプションを、混同しないようにしてください。トランスレータのオプションは、変換処理でのセマンティクス・チェックに使用されるオプションです。ただし、変換と同じ接続を使用するようにカスタマイズする場合は、便宜上トランスレータの設定がカスタマイザに渡されて、利用されます。必要に応じて、カスタマイザ・ハーネス・オプションを使用してこれらの初期設定をオーバーライドしてください。

カスタマイズ用ユーザー・オプション(user)

userオプションを設定すると、カスタマイザでデータベース接続を使用する場合のデータベース・スキーマを指定できます。

userオプション設定には、ユーザー・スキーマの他にも、必要に応じてパスワードまたはURL、あるいはその両方を指定できます。次のように、パスワードの先頭にスラッシュ(/)を付け、URLの先頭にアットマーク(@)を付けます。

-P-user=scott/tiger
-P-user=scott@jdbc:oracle:oci:@
-P-user=scott/tiger@jdbc:oracle:oci:@

注意:
列定義(optcolsオプション)を使用するときに、SQLJトランスレータのユーザー設定もプロファイル・カスタマイザに転送されます。カスタマイザのuserオプションを使用すると、トランスレータの設定を上書きできます。

コマンドライン構文は、次のとおりです。

-P-user=username</password><@url>

次にコマンドラインの例を示します。

-P-user=scott
-P-user=scott/password
-P-user=scott/password@jdbc:oracle:oci:@

プロパティ・ファイルの構文は、次のとおりです。

profile.user=username</password><@url>

次にプロパティ・ファイルの例を示します。

profile.user=scott
profile.user=scott/tiger
profile.user=scott/tiger@jdbc:oracle:oci:@

デフォルト値は、次のとおりです。

null

カスタマイズ用パスワード・オプション(password)

passwordオプションは、カスタマイザでデータベース接続を使用する場合に使用します。

パスワードは、userオプションでも設定できます。「カスタマイズ用ユーザー・オプション(user)」を参照してください。

注意:
列定義(optcolsオプション)を使用するときに、SQLJトランスレータのパスワード設定もプロファイル・カスタマイザに転送されます。カスタマイザのpasswordオプションを使用すると、トランスレータの設定を上書きできます。

コマンドライン構文は、次のとおりです。

-P-password=password

次にコマンドラインの例を示します。

-P-password=password

プロパティ・ファイルの構文は、次のとおりです。

profile.password=password

次にプロパティ・ファイルの例を示します。

profile.password=password

デフォルト値は、次のとおりです。

null

カスタマイズ用URL・オプション(url)

urlオプションは、カスタマイザでデータベース接続を使用する場合に使用します。

URLは、userオプションでも設定できます。「カスタマイズ用ユーザー・オプション(user)」を参照してください。

注意:
列定義(optcolsオプション)を使用するときに、SQLJトランスレータのURL設定もプロファイル・カスタマイザに転送されます。カスタマイザのurlオプションを使用すると、トランスレータの設定を上書きできます。

コマンドライン構文は、次のとおりです。

-P-url=url

次にコマンドラインの例を示します。

-P-url=jdbc:oracle:oci:@

プロパティ・ファイルの構文は、次のとおりです。

profile.url=url

次にプロパティ・ファイルの例を示します。

profile.url=jdbc:oracle:oci:@

デフォルト値は、次のとおりです。

jdbc:oracle:oci:@

カスタマイズ用JDBCドライバ・オプション(driver)

カスタマイザでデータベース接続を使用する場合は、driverオプションを使用し、複数のJDBCドライバ・クラスをカンマで区切って登録します。次に例を示します。

-P-driver=sun.jdbc.odbc.JdbcOdbcDriver,oracle.jdbc.OracleDriver

カンマの前後には、スペースは不要です。

コマンドライン構文は、次のとおりです。

-P-driver=dvr_class1<,dvr_class2,...>

次にコマンドラインの例を示します。

-P-driver=sun.jdbc.odbc.JdbcOdbcDriver

プロパティ・ファイルの構文は、次のとおりです。

profile.driver=dvr_class1<,dvr_class2,...>

次にプロパティ・ファイルの例を示します。

profile.driver=sun.jdbc.odbc.JdbcOdbcDriver

デフォルト値は、次のとおりです。

oracle.jdbc.OracleDriver

専用のカスタマイザの起動に使用するカスタマイザ・ハーネスのオプション

特別なカスタマイザの起動には、次に示したカスタマイザ・ハーネスのオプションを使用できます。

- debug: デバッグに使用するAuditorInstallerカスタマイザを起動するためのオプション

- print: プロファイルをテキスト形式で出力するカスタマイザを起動するためのオプション

- verify: プロファイルに対してセマンティクス・チェックを実行するSQLCheckerCustomizerカスタマイザを起動するためのオプション

重要:
これらの各オプションを使用すると特定のカスタマイザを起動できますが、SQLJの1回の実行で実行できるカスタマイザは1つのみに限られています。そのため、このオプションを使用した場合は、他のカスタマイズを実行できなくなります。
print、debugおよびverifyのうち、同時に使用できるのは1つのみです。

専用カスタマイザ: プロファイル・デバッグ・オプション(debug)

debugオプションを使用すると、AuditorInstallerと呼ばれる、デバッグ文をプロファイルに挿入する専用のカスタマイザを起動できます。このオプションに、SQLJコマンドラインでファイルを指定すると、指定されたプロファイルにデバッグ文が出力されます。これらのプロファイルは、あらかじめSQLJを実行してカスタマイズしておく必要があります。

このカスタマイザでサポートされている他のオプションなどの詳細は、「デバッグ用のAuditorInstallerカスタマイザ」を参照してください。

アプリケーションを実行すると、SQLJランタイムでデバッグ文が実行され、メソッド・コールと戻り値のトレース情報が表示されます。

たとえば、次のようにdebugオプションを指定します。

% sqlj -P-debug Foo_SJProfile0.ser Bar_SJProfile0.ser

% sqlj -P-debug *.ser

コマンドライン構文は、次のとおりです。

sqlj -P-debug profile_list

次にコマンドラインの例を示します。

sqlj -P-debug Foo_SJProfile*.ser

プロパティ・ファイルの構文は、次のとおりです。

profile.debug

(SQLJファイル・リストのプロファイルにも指定します。)

次にプロパティ・ファイルの例を示します。

profile.debug

デフォルト値は、次のとおりです。

NA

専用カスタマイザ: プロファイル出力オプション(print)

printオプションを使用すると、プロファイルをテキスト・フォーマットで表示するためのカスタマイザを実行できます。このオプションに、SQLJコマンドラインでファイルを指定すると、指定された1つ以上のプロファイルの内容が出力されます。これは、SQLJの標準出力(通常はディスプレイ)に出力されます。次に例を示します。

% sqlj -P-print Foo_SJProfile0.ser Bar_SJProfile0.ser

すべてのカスタマイザ・オプションを参照するには、次のコマンドを使用します。

% sqlj -P-print *.ser

前述のコマンドによる出力は、次のとおりです。

printing contents of profile Sample_SJProfile0
created 1154609279331 (8/3/06 5:47 AM)
associated context is Mycontext1
profile loader is sqlj.runtime.profile.DefaultLoader@12a3793
contains one customization
OracleCustomization Options  :
Version is :2300
Cstmtcache :5
Ccompat    :false
Cforce     :false
Coptcols   :false
Coptparams :false
Coptparamdefaults:null
CshowSQL   :false
Csummary   :false
CuserSQL   :true

#sql { SELECT a    FROM test WHERE name= ?  }
setFixedchar is enabled
Ncharconv  is disabled

#sql { commit }
setFixedchar is disabled
Ncharconv  is disabled
………

コマンドライン構文は、次のとおりです。

sqlj -P-print profile_list

次にコマンドラインの例を示します。

sqlj -P-print Foo_SJProfile*.ser

プロパティ・ファイルの構文は、次のとおりです。

profile.print

(SQLJファイル・リストのプロファイルにも指定します。)

次にプロパティ・ファイルの例を示します。

profile.print

デフォルト値は、次のとおりです。

なし

専用カスタマイザ: プロファイルのセマンティクス・チェック用オプション(verify)

verifyオプションを指定すると、プロファイルに対してセマンティクス・チェックを実行するSQLCheckerCustomizerという特殊なカスタマイザが起動されます。これは、変換時にソース・コードに対して実行されるセマンティクス・チェックに相当します。このプロファイルは、前のSQLJトランスレータ実行時にすでに作成されています。

このオプションは、デプロイメント後やソース・コードが使用されなくなった後の、ランタイム・データベースに対するセマンティクス・チェックに役立ちます。

このカスタマイザでサポートされている他のオプションなどの詳細は、「プロファイルのセマンティクス・チェック用のSQLCheckerCustomizer」を参照してください。

注意:
プロファイルのオンライン・セマンティクス・チェックの際にも、カスタマイザ・ハーネスのuser、passwordおよびurlオプションを使用する必要があります。

たとえば、次のようにverifyオプションを指定します。次の2つの例では、どちらもSQLCheckerCustomizerのデフォルトのセマンティクス・チェッカを使用し、特定のデータベース接続によるオンライン・チェックを行います。(最初の例ではコマンドラインが折り返されて表示されていますが、全体が1行で入力されています。)

% sqlj -P-verify -P-user=scott -P-url=jdbc:oracle:oci:@ Foo_SJProfile0.ser Bar_SJProfile0.ser
Password: password

% sqlj -P-verify -P-user=scott -P-url=jdbc:oracle:oci:@ *.ser
Password: password

コマンドライン構文は、次のとおりです。

sqlj -P-verify <conn params> profile_list

次にコマンドラインの例を示します。

sqlj -P-verify <conn params> Foo_SJProfile*.ser

プロパティ・ファイルの構文は、次のとおりです。

profile.verify

(SQLJコマンドラインにはプロファイルを必ず指定してください。通常はカスタマイザ・ハーネスの接続オプションを指定します。)

次にプロパティ・ファイルの例を示します。

profile.verify

デフォルト値は、次のとおりです。

NA

カスタマイザ固有のオプションの概要

カスタマイザ固有のオプション(Oracleカスタマイザ用のオプションなど)は、SQLJコマンドラインまたはSQLJプロパティ・ファイルに設定できます。この構文は、カスタマイザ・ハーネスのオプション設定に使用する構文とほとんど同じです。

SQLJコマンドラインでカスタマイザ・オプションを設定する場合は、先頭に次の文字列を付けます。

-P-C

SQLJプロパティ・ファイルで設定するときは、先頭に次の文字列を付けます。

profile.C

このオプションの構文の詳細は、「プロファイル・カスタマイザに渡すオプション(-P)」および「プロパティ・ファイルの構文」を参照してください。

この項のこれ以降では、Oracleカスタマイザの機能について説明します。Oracleカスタマイザでは、いくつかのオプションがサポートされています。これらのオプションの大半はブール値であり、有効にするには次のようにします。

-P-Coption

または

-P-Coption=true

ブール値のオプションは、デフォルトでは無効になっています。明示的に無効にするには、次のように指定します。

-P-Coption=false

数値オプションや文字列オプションの設定は、ほとんど同じです。

-P-Coption=value

Oracleカスタマイザのオプション

ここでは、Oracleカスタマイザ固有のオプションについて説明します。まず、サポートされているオプションの概要を示します。

Oracleカスタマイザでサポートされているオプション

Oracleカスタマイザでは、次のオプションを使用できます。

- compat: バージョンの互換性に関する情報を表示するためのオプション

- force: すでに有効なカスタマイズが行われている場合でも、カスタマイズを実行するためのオプション

- optcols: パフォーマンスが最適化されるようにイテレータ列型およびサイズ定義を有効化するためのオプション。

- optparams: パラメータ・サイズを、JDBCリソース割当て量が最適化されるように定義するためのオプション(optparamdefaultsと併用します)。

- optparamdefaults: 特定のデータ型に対してパラメータ・サイズのデフォルトを設定するためのオプション(optparamsと併用します)。

- fixedchar: WHERE句に関して、空白埋めを考慮したCHAR比較を有効にするためのオプション。

- showSQL: SQL文の変換情報を表示するためのオプション。

- stmtcache: 文のキャッシュ・サイズ(実行時に各接続でキャッシングできる文の数)を設定するためのオプション。パフォーマンスの最適化に必要なサイズを設定する場合と、文のキャッシングを無効化するために0(ゼロ)が設定される場合があります。

- summary: アプリケーションで使用されているOracleの機能の概要を表示するためのオプション。

これらのオプションによって出力された内容は、SQLJの他のメッセージと同じように、標準出力に書き込まれます。

Oracleカスタマイザのバージョン互換性オプション(compat)

compatフラグを使用すると、アプリケーションと、Oracle DatabaseおよびOracle JDBCドライバの各バージョンとの互換性に関する情報が、Oracleカスタマイザによって表示されます。これは、SQLJ変換を全体的に実行した場合でも、以前に生成されたプロファイルに対して実行した場合でも、実行できます。

たとえば、次のように指定すると、MyAppというアプリケーションを変換してカスタマイズする際に、互換性の情報が出力されます。

% sqlj <...SQLJ options...> -P-Ccompat MyApp.sqlj

この例では、MyAppのプロファイルの生成、カスタマイズおよび互換性チェックが、SQLJの1回の実行で行われます。

次のように指定すると、以前に生成されたMyAppのプロファイルに関する互換性情報が出力されます。

% sqlj <...SQLJ options...> -P-Ccompat MyApp_SJProfile*.ser

この例のように指定してSQLJを実行すると、以前にSQLJを実行したときに生成された(場合によってはカスタマイズもされた)MyAppのプロファイルに対して、カスタマイズ(必要な場合)と互換性チェックが行われます。

次の2つの例は、デフォルトのOracleカスタマイザを使用している場合に、-P-Ccompatオプションを指定してSQLJを実行したときに出力される内容です。最初に、アプリケーションが、すべてのバージョンのOracle JDBCドライバで使用できる例を示します。

MyApp_SJProfile0.ser: Info: compatible with all Oracle JDBC drivers

2番目の例では、アプリケーションが、Oracle8i リリース8.1以上のJDBC実装でのみ使用できる場合を示します。

MyApp_SJProfile0.ser: Info: compatible with Oracle 8.1 or later JDBC driver

注意:
以前の有効なカスタマイズが検出されてカスタマイズが実行されなかった場合でも、compatオプションが指定されていると、互換性の情報が出力されます。

コマンドライン構文は、次のとおりです。

-P-Ccompat<=true|false>

次にコマンドラインの例を示します。

-P-Ccompat

プロパティ・ファイルの構文は、次のとおりです。

profile.Ccompat<=true|false>

次にプロパティ・ファイルの例を示します。

profile.Ccompat

デフォルト値は、次のとおりです。

false

Oracleカスタマイザの強制オプション(force)

forceフラグを有効にすると、Oracleカスタマイザによって特定の(コマンドラインで指定された)プロファイルのカスタマイズが強制的に実行されます。そのプロファイルに、すでに有効なカスタマイズが認識される場合でも、実行されます。次に例を示します。

% sqlj -P-Cforce MyApp_SJProfile*.ser

これを実行すると、カスタマイズ済かどうかにかかわらず、MyAppのプロファイルがすべてカスタマイズされます。デフォルトでは、Oracleカスタマイザは既存のカスタマイズを上書きして再インストールすることはありません(ただし、既存のカスタマイズが古いバージョンのカスタマイザでインストールされている場合を除きます)。

コマンドライン構文は、次のとおりです。

-P-Cforce<=true|false>

次にコマンドラインの例を示します。

-P-Cforce

プロパティ・ファイルの構文は、次のとおりです。

profile.Cforce<=true|false>

次にプロパティ・ファイルの例を示します。

profile.Cforce

デフォルト値は、次のとおりです。

false

Oracleカスタマイザの列定義オプション(optcols)

optcolsフラグを使用すると、Oracleカスタマイザに、イテレータまたは結果セットの列型およびサイズを判断し、この情報をプロファイルに追加するように指示できます。このようにすると、SQLJランタイムは、アプリケーション実行時にこの列をOracle JDBCドライバに自動的に登録可能になり、特定のドライバの実装にもよりますが、Oracleへのラウンドトリップが減ります。この方法は、Thinドライバと位置イテレータには特に効果的です。

列定義の概要は、「列の定義」を参照してください。

データベース接続用のユーザー名、パスワードおよびURLを指定せずに、Oracleカスタマイザのoptcolsオプションを有効にすると、エラーが発生します。この指定を行うには、ISO標準のコード生成時にカスタマイザに転送される、トランスレータのオプション-user、-passwordおよび-urlを使用するか、またはカスタマイザのオプションuser、passwordおよびurlを直接使用します。

実行時にはデータベースの接続先と同じスキーマまたはデータベースに、カスタマイザから接続する必要はありません。ただし、実行時のエラーを回避するために、関連のある列と、型およびサイズが同じ列は同じ順序で並べる必要があります。

カスタマイザ・ハーネスの接続オプションについては、「カスタマイザ・ハーネスのオプションの概要」のuser、password、urlおよびdriverの項を参照してください。

注意:
このオプションのかわりに、SQLJトランスレータの-optcolsオプションを使用できます。これは、カスタマイザのオプションを自動的に設定するオプションです。(また、プロファイルを使用しないOracle固有コード生成の場合は、トランスレータのオプションを使用する必要があります。)「列の定義(-optcols)」を参照してください。
参照先の項では、さらに概念についても説明されています。

カスタマイザのoptcolsフラグの有効化/無効化は、SQLJのコマンドラインまたはプロパティ・ファイルで設定します。

このフラグをコマンドラインで有効にするには、次のようにします。

-P-Coptcols

または

-P-Coptcols=true

このフラグは、デフォルトでは無効になっていますが、明示的に無効化することも可能です。このフラグをコマンドラインで無効化するには、次のようにします。

-P-Coptcols=false

列を定義するには、カスタマイザでデータベース接続を行って、問合せの対象とする表の列を調べる必要があります。そのために、カスタマイザ・ハーネスのuser、passwordおよびurlオプションを適切に設定する必要があります(デフォルトのOracleDriverクラスを使用しない場合は、カスタマイザ・ハーネスのdriverオプションも)。次に例を示します。

% sqlj <...SQLJ options...> -P-user=scott@jdbc:oracle:oci:@ -P-Coptcols MyApp.sqlj
Password: password

SQLJトランスレータの場合と同様に、必要に応じて、パスワードとURLをpasswordオプションとurlオプションでそれぞれ設定するかわりに、userオプションで設定できます。

または、次のようにして、列定義を既存のプロファイルに挿入することも可能です。この場合は、Oracleカスタマイザのforceオプションを使用して、カスタマイズを再実行する必要があります。

% sqlj -P-user=scott@jdbc:oracle:oci:@ -P-Cforce -P-Coptcols MyApp_SJProfile*.ser
Password: password

また、次のようにして、列定義をJARファイル中の既存のプロファイルに挿入することも可能です。

% sqlj -P-user=scott@jdbc:oracle:oci:@ -P-Cforce -P-Coptcols MyAppProfiles.jar
Password: password

Oracleカスタマイザ実行時(新規のプロファイルの変換時や生成時、または既存プロファイルのカスタマイズ時)にoptcolsフラグを有効化すると、カスタマイザ・ハーネスのverboseフラグも有効化できます。このフラグを有効化すると、処理対象のイテレータおよび結果セット、列型およびサイズ定義の情報がOracleカスタマイザに表示されます。次に例を示します。

% sqlj -P-user=scott@jdbc:oracle:oci:@ -P-verbose -P-Cforce -P-Coptcols MyApp_SJProfile*.ser
Password: password

verboseのフラグの概要は、「カスタマイザ・ハーネスのオプションの概要」の該当する項を参照してください。

Oracleカスタマイザのsummaryフラグを有効にして、既存のプロファイルの処理を実行すると、列定義がそのプロファイルに追加されたかどうかを確認できます。次のようにします。

% sqlj -P-Csummary MyApp_SJProfile*.ser

summaryフラグの概要は、「カスタマイザ固有のオプションの概要」を参照してください。

コマンドライン構文は、次のとおりです。

-P-Coptcols<=true|false>

次にコマンドラインの例を示します。

-P-Coptcols

プロパティ・ファイルの構文は、次のとおりです。

profile.Coptcols<=true|false>

次にプロパティ・ファイルの例を示します。

profile.Coptcols

デフォルト値は、次のとおりです。

false

Oracleカスタマイザのパラメータ定義オプション(optparams)

パラメータ・サイズの定義を有効化するには、optparamsフラグを使用します。SQLJではこのフラグを有効にすると、入出力パラメータ(ホスト変数)が登録され、JDBCリソース割当て量が指定したサイズに基づいて最適化されます。

パラメータ・サイズ定義の概要とソース・コード・ヒントの詳細は、「パラメータ・サイズの定義」を参照してください。

注意:
このオプションのかわりに、SQLJトランスレータの-optparamsオプションを使用できます。これは、カスタマイザのオプションを自動的に設定するオプションです。(また、プロファイルを使用しないOracle固有コード生成の場合は、トランスレータのオプションを使用する必要があります。)「パラメータの定義(-optparams)」を参照してください。
参照先の項では、さらに概念についても説明されています。

optparamsフラグの有効化/無効化は、コマンドラインまたはSQLJプロパティ・ファイルで設定します。

このフラグをコマンドラインで有効にするには、次のようにします。

-P-Coptparams

または

-P-Coptparams=true

このフラグは、デフォルトでは無効になっていますが、明示的に無効化することも可能です。このフラグをコマンドラインで無効化するには、次のようにします。

-P-Coptparams=false

注意:
optcolsオプションとは異なり、optparamsオプションではサイズを自分で指定できるので、カスタマイザでのデータベース接続は不要です。

コマンドライン(optparamdefaultsオプションの設定はここでは省略し、次の項で説明します)の例を次に示します。

% sqlj <...SQLJ options...> -P-Coptparams -P-Coptparamdefaults=defaults_string MyApp.sqlj

次の例のようにすると、既存プロファイルのパラメータ・サイズ定義が有効になります。

% sqlj -P-Coptparams -P-Coptparamdefaults=defaults_string MyApp_SJProfile*.ser

また、JARファイル中の既存のプロファイルも使用できます。

% sqlj -P-Coptparams -P-Coptparamdefaults=defaults_string MyAppProfiles.jar

コマンドライン構文は、次のとおりです。

-P-Coptparams<=true|false>

次にコマンドラインの例を示します。

-P-Coptparams

プロパティ・ファイルの構文は、次のとおりです。

profile.Coptparams<=true|false>

次にプロパティ・ファイルの例を示します。

profile.Coptparams

デフォルト値は、次のとおりです。

false

Oracleカスタマイザ用パラメータのデフォルト・サイズ・オプション(optparamdefaults)

optparamsオプションを有効にしてパラメータ・サイズを設定した場合は、必要に応じてoptparamdefaultsオプションを使用してデータ型のデフォルト・サイズを設定します。optparamsを有効にしないと、optparamdefaultsが設定されていても無視されるので注意してください。

パラメータ・サイズ定義の概要とソース・コード・ヒントの詳細は、「パラメータ・サイズの定義」を参照してください。

注意:
このオプションのかわりに、SQLJトランスレータの-optparamdefaultsオプションを使用できます。これは、カスタマイザのオプションを自動的に設定するオプションです。(また、プロファイルを使用しないOracle固有コード生成の場合は、トランスレータのオプションを使用する必要があります。)「パラメータのデフォルト・サイズ(-optparamdefaults)」を参照してください。
参照先の項では、さらに概念と構文についても説明されています。2つのオプションの機能は同じです。

optparamdefaultsフラグは、コマンドラインでもSQLJプロパティ・ファイルでも設定できます。

このフラグをコマンドラインで設定するには、次のようにします。

-P-Coptparamdefaults=datatype1(size1),datatype2(size2),...

次にコマンドラインの例を示します。この例では、optparamsも設定します。

% sqlj <..SQLJ options..> -P-Coptparams -P-Coptparamdefaults=CHAR_TYPE(50),RAW_TYPE(500),CHAR(10) MyApp.sqlj

構文は、「パラメータのデフォルト・サイズ(-optparamdefaults)」を参照してください。

既存のプロファイルに対してパラメータ・サイズのデフォルトを指定することも可能です。ただし、この場合はOracleカスタマイザのforceオプションを使用して、カスタマイズを再実行する必要があります。

% sqlj -P-Cforce -P-Coptparams -P-Coptparamdefaults=CHAR_TYPE(50),RAW_TYPE(500),CHAR(10) MyApp_SJProfile*.ser

また、次のようにして、JARファイル中の既存のプロファイルに対してパラメータ・サイズのデフォルトを指定することも可能です。

% sqlj -P-Cforce -P-Coptparams -P-Coptparamdefaults=CHAR_TYPE(50),RAW_TYPE(500),CHAR(10) MyAppProfiles.jar

注意:
実行時に、実際のサイズが登録されているパラメータのサイズを超えた場合は、ランタイム・エラーが発生します。

コマンドライン構文は、次のとおりです。

-P-Coptparamdefaults=defaults_string

次にコマンドラインの例を示します。

-P-Coptparamdefaults=VAR%(50),LONG%(500),RAW_TYPE()

プロパティ・ファイルの構文は、次のとおりです。

profile.Coptparamdefaults=defaults_string

次にプロパティ・ファイルの例を示します。

profile.Coptparamdefaults=VAR%(50),LONG%(500),RAW_TYPE()

デフォルト値は、次のとおりです。

null

Oracleカスタマイザによる空白埋めを考慮したCHAR比較(fixedchar)

WHERE句の比較で文字列をバインドするときにCHAR型のデータベース列の空白埋めを考慮するには、このフラグをtrueに設定します。この比較方法では、たとえば、"mystring"と"mystring "は同等であるとみなされます。

次に、Oracleカスタマイザのfixedcharの使用例を示します。

% sqlj -P-Cfixedchar MyProgram.sqlj AnotherProg.java ...

注意:

- このオプションのかわりに、SQLJトランスレータの-fixedcharオプションを使用できます。これは、カスタマイザのオプションを自動的に設定するオプションです。(また、プロファイルを使用しないOracle固有コード生成の場合は、トランスレータのオプションを使用する必要があります。)「空白埋めを考慮したCHAR比較(-fixedchar)」を参照してください。参照先の項では、さらに概念についても説明されています。

- Oracleカスタマイザのsummaryフラグも有効にすると、(fixedchar機能の背後で使用される)OracleのsetFixedCHAR() APIの使用数が表示されます。例については、「Oracleカスタマイザのサマリー・オプション(summary)」を参照してください。

コマンドライン構文は、次のとおりです。

-P-Cfixedchar<=true|false>

次にコマンドラインの例を示します。

-P-Cfixedchar

プロパティ・ファイルの構文は、次のとおりです。

profile.Cfixedchar<=true|false>

次にプロパティ・ファイルの例を示します。

profile.Cfixedchar

デフォルト値は、次のとおりです。

false

OracleカスタマイザのSQL表示オプション(showSQL)

showSQLフラグを有効にすると、OracleカスタマイザによってSQL文に実行されたすべての変換が表示されます。このような変換は、データベースが直接サポートしていない構文をSQLJがサポートしている場合に必要です。

次のように指定すると、MyAppというアプリケーションを変換してカスタマイズする際に、SQL変換情報が表示されます。

% sqlj <...SQLJ options...> -P-CshowSQL MyApp.sqlj

この例では、MyAppのプロファイルの生成、カスタマイズおよびSQL変換情報の表示が、SQLJの1回の実行で行われます。

次のように指定すると、以前に生成されたMyAppのプロファイルのカスタマイズ時に、SQL変換情報が表示されます。

% sqlj <...SQLJ options...> -P-CshowSQL MyApp_SJProfile*.ser

この例のように指定してSQLJを実行すると、以前にSQLJを実行したときに生成された(場合によってはカスタマイズもされた)MyAppのプロファイルに対して、カスタマイズ(必要な場合)が行われ、SQL変換情報が表示されます。

次の例は、showSQLによって出力される内容です。

MyApp.sqlj:14: Info: <<<NEW SQL>>> #sql {BEGIN  ? := VALUES(tkjsSET_f1); END};

in file MyApp, line 14, we had:

#sql {set :v1= VALUES(tkjsSET_f1) };

SET文は、カスタマイズ時にOracleカスタマイザによって、それに相当するPL/SQLブロックに置き換えられます。

注意:
以前の有効なカスタマイズが検出されてカスタマイズが実行されなかった場合でも、showSQLオプションが指定されているとSQL変換情報が出力されます。

コマンドライン構文は、次のとおりです。

-P-CshowSQL<=true|false>

次にコマンドラインの例を示します。

-P-CshowSQL

プロパティ・ファイルの構文は、次のとおりです。

profile.CshowSQL<=true|false>

次にプロパティ・ファイルの例を示します。

profile.CshowSQL

デフォルト値は、次のとおりです。

false

Oracleカスタマイザ用の文のキャッシュ・サイズ・オプション(stmtcache)

Oracleカスタマイザのstmtcacheオプションを使用すると、文のキャッシュ・サイズ(アプリケーション実行時にデータベース接続ごとにキャッシングできる文の数)を設定したり、文のキャッシングを無効化することが可能です。

文のキャッシュ・サイズのデフォルトは5です。文のキャッシングの概要は、「文のキャッシング」を参照してください。

重要:
デフォルトのOracle固有のコード生成(-codegen=oracle)を使用する場合、SQLJではプロファイルが生成されず、カスタマイズが実行されません。この場合、接続コンテキスト・メソッドを使用してSQLJ文キャッシングを制御します。「文キャッシングのための接続コンテキスト・メソッド(Oracle固有コードの場合)」を参照してください。

文のキャッシュ・サイズは、コマンドラインでもプロパティ・ファイルでも設定できます。

コマンドラインを使用して、アプリケーションMyAppでの文のキャッシュ・サイズを15に設定するには、次のようにします。

% sqlj <...SQLJ options...> -P-Cstmtcache=15 MyApp.sqlj

文のキャッシングを無効化するには、キャッシュ・サイズを0(ゼロ)に設定します。

% sqlj <...SQLJ options...> -P-Cstmtcache=0 MyApp.sqlj

アプリケーションを再変換せずに、既存プロファイル中の文のキャッシュ・サイズを変更することも可能です。ただし、この場合は、Oracleカスタマイザのforceオプションを使用して、カスタマイズを再実行する必要があります。

% sqlj -P-Cforce -P-Cstmtcache=15 MyApp_SJProfile0.ser

プロファイルが複数ある場合、各プロファイルに対して文のキャッシュ・サイズを個別に設定できます。この個別設定を行うには、アプリケーションの変換が完了した後で、各プロファイルに対してSQLJを個別に実行します。

% sqlj -P-Cforce -P-Cstmtcache=10 MyApp_SJProfile0.ser
% sqlj -P-Cforce -P-Cstmtcache=15 MyApp_SJProfile1.ser
% sqlj -P-Cforce -P-Cstmtcache=0 MyApp_SJProfile2.ser

各接続コンテキスト・クラスに対応するプロファイルを決定決することも必要です。次のように決定します。プロファイル0(ゼロ)は、アプリケーションにおける最初の実行文で使用する接続コンテキスト・クラスに対応し、プロファイル1は、最初の実行文(ただし、最初の接続コンテキスト・クラスを使用しない)で使用する接続コンテキスト・クラスに対応し、プロファイル2以降についても同様の対応になります。相関関係を検証するには、各プロファイルを調べるカスタマイザ・ハーネスのprintオプションを使用します。

コマンドライン構文は、次のとおりです。

-P-Cstmtcache=value

次にコマンドラインの例を示します。

-P-Cstmtcache=10

プロパティ・ファイルの構文は、次のとおりです。

profile.Cstmtcache=value

次にプロパティ・ファイルの例を示します。

profile.Cstmtcache=10

デフォルト値は、次のとおりです。

5

Oracleカスタマイザのサマリー・オプション(summary)

summaryフラグを使用すると、変換するアプリケーション、または指定されたプロファイル・ファイルで使用されているOracleの機能のサマリーを表示するように、Oracleカスタマイザに指示できます。これは、別のプラットフォームへの移植を妨げる機能を特定する場合に便利で、SQLJ変換を全体的に実行する場合でも、以前に生成されたプロファイルに対して実行する場合でも実施できます。

次のように指定すると、MyAppというアプリケーションを変換してカスタマイズする際に、サマリーが表示されます。

% sqlj <...SQLJ options...> -P-Csummary MyApp.sqlj

この例では、MyAppのプロファイルの生成、カスタマイズおよびサマリーの表示が、SQLJの1回の実行で行われます。

次のように指定すると、以前に生成されたMyAppのプロファイルに関するサマリーが表示されます。

% sqlj <...SQLJ options...> -P-Csummary MyApp_SJProfile*.ser

この例のように指定してSQLJを実行すると、以前にSQLJを実行したときに生成された(場合によってはカスタマイズもされた)MyAppのプロファイルに対して、カスタマイズ(必要な場合)が行われ、サマリーが表示されます。

次の2つの例は、デフォルトのOracleカスタマイザを使用している場合に、-P-Csummaryオプションを指定してSQLJを実行したときに出力される内容です。最初に、Oracleの機能を使用しない例を示します。

MyApp_SJProfile0.ser: Info: Oracle features used:
MyApp_SJProfile0.ser: Info: * none

2番目の例では、Oracleの機能が複数使用されていることを示し、oracle.sqlパッケージの複数のOracle拡張データ型の一覧を出力しています。

MyApp_SJProfile0.ser: Info: Oracle features used:
MyApp_SJProfile0.ser: Info: * oracle.sql.NUMBER: 2
MyApp_SJProfile0.ser: Info: * oracle.sql.DATE: 2
MyApp_SJProfile0.ser: Info: * oracle.sql.CHAR: 2
MyApp_SJProfile0.ser: Info: * oracle.sql.RAW: 2

次の例では、OracleのsetFixedCHAR() APIの使用数が出力されます(このAPIは、Oracleカスタマイザのfixedcharオプションによって有効化され、CHARデータと比較するために、WHERE句に文字列をバインドするときに空白埋めが考慮されます)。

% sqlj -P-Cfixedchar -P-Csummary -P-Cforce *.ser
FC_SJProfile0.ser: Info: re-installing Oracle customization
FC_SJProfile0.ser: Info: Oracle features used:
FC_SJProfile0.ser: Info: * setFixedCHAR(): 4

注意:
以前の有効なカスタマイズが検出されてカスタマイズが実行されなかった場合でも、summaryオプションが指定されていると、サマリーが出力されます。

コマンドライン構文は、次のとおりです。

-P-Csummary<=true|false>

次にコマンドラインの例を示します。

-P-Csummary

プロパティ・ファイルの構文は、次のとおりです。

profile.Csummary<=true|false>

次にプロパティ・ファイルの例を示します。

profile.Csummary

デフォルト値は、次のとおりです。

false

他のカスタマイザ用のオプション

Oracle SQLJ実装では、この章で後述する特別なカスタマイザも提供されています。これらのカスタマイザにも、コマンドラインのオプションがあります。

- SQLCheckerCustomizer(プロファイルのセマンティクス・チェック用): 概要は、「プロファイルのセマンティクス・チェック用のSQLCheckerCustomizer」を参照してください。また、オプションについては、「SQLCheckerCustomizerオプション」を参照してください。

- AuditorInstaller(デバッグ用): 概要は、「デバッグ用のAuditorInstallerカスタマイザ」を参照してください。また、オプションについては、「AuditorInstallerオプション」を参照してください。

プロファイルのカスタマイズ用のSQLJトランスレータのオプション

次のオプションは、プロファイルのカスタマイズに関連するSQLJトランスレータのオプションです。これらのオプションの詳細は、このマニュアルの各項を参照してください。

- -default-customizer: 使用するデフォルトのカスタマイザを指定します。このオプションは、カスタマイザ・ハーネスの-customizerに、プロファイル・カスタマイザが指定されていない場合に使用します。
「デフォルト・プロファイル・カスタマイザ(-default-customizer)」を参照してください。

- -profile: 今回のSQLJの実行でカスタマイズを行うかどうかを指定します。
「プロファイル・カスタマイズ・フラグ(-profile)」を参照してください。

プロファイルのJARファイル

前述のように、SQLJコマンドラインでJARファイルを指定して、そのJARファイルに含まれるすべてのプロファイルをカスタマイズします。

注意:

- SQLJコマンドラインでは、.sqljファイルまたは.javaファイル、あるいはその両方を指定して標準のSQLJ処理を実行するか、.serファイルまたは.jarファイル、あるいはその両方を指定してカスタマイズのみを実行できます。ただし、その両方の処理を同時には実行できません。

- .jarファイルには、プロファイル以外のファイルが含まれている場合があります。マニフェスト・エントリでそのファイルがプロファイルではないことが示されている場合、そのファイルはカスタマイズ時に無視されます。

- .jarファイルは、それに含まれる各プロファイルに対して、クラスをロードするコンテキストとして使用されます。プロファイルで.jarファイル内のクラスが参照される場合、そのクラスは.jarファイルからロードされます。プロファイルで参照されるクラスが.jarファイル内にない場合は、通常の処理と同じように、システム・クラス・ローダーによって、CLASSPATHの指定に従ってクラスが検出されてロードされます。

JARファイルの要件

各プロファイルのマニフェスト・エントリには要件があります。

JARファイルに含めるプロファイルごとに2行でテキスト・ファイルを作成します。「Name:」で始まる1行の後にPATHまたはパッケージと名前を記述します。もう1つの行を次に示します。

SQLJProfile: TRUE

この2行は連続していることが必要です(間に空白行を挿入しないでください)。ただし、プロファイルを追加する場合は、追加する2行の前に空白行を挿入する必要があります。

JARユーティリティの-mオプションを使用して、このファイルを入力します。

たとえば、foo/barディレクトリに、3つのプロファイルを持つMyAppというアプリケーションがあり、これらのプロファイルを含むJARファイルを作成するとします。次の手順を実行します。

1. 次のように、セパレータとして使用する空白行を含めて8行で構成されたテキスト・ファイルを作成します。

Name: foo/bar/MyApp_SJProfile0.ser
SQLJProfile: TRUE

Name: foo/bar/MyApp_SJProfile1.ser
SQLJProfile: TRUE

Name: foo/bar/MyApp_SJProfile2.ser
SQLJProfile: TRUE

ここでは、ファイルの名前をMyAppJarEntries.txtとします。

2. jarを実行してJARファイルを作成する際に、次のように-mオプションを指定して、作成したテキストを入力します(ここではJARファイルの名前をmyjarfile.jarとします)。

% jar -cvfm myjarfile.jar MyAppJarEntries.txt foo/bar/MyApp_SJProfile*.ser foo/bar/*.class

JARファイルの作成時に、JARユーティリティがマニフェストを生成する場合、このユーティリティは指定されたテキスト・ファイルを読み込み、SQLJProfile: TRUEの行を各プロファイルのマニフェスト・エントリに挿入します。この処理は、マニフェスト内のプロファイル名と、テキスト・ファイルに指定されているプロファイル名が合致すると行われます。

JARファイルのロジスティクス

SQLJコマンドラインでJARファイルを指定すると、そのJAR内の各プロファイルはシリアライズ解除され、カスタマイズされます。

JARファイルのカスタマイズは、それに含まれるすべてのプロファイルが正しくカスタマイズされたときに、正常に実行されます。カスタマイズが正常に終了すると、各プロファイルは.serファイルに再びシリアライズされ、元の.serファイルをカスタマイズ後の.serで置き換えるようにJARが変更され、新しいプロファイル・エントリを示すようにJARマニフェスト・ファイルが更新されます。

JARファイル内のプロファイルのカスタマイズ時に1度でもエラーが発生すると、JARファイルのカスタマイズは失敗し、元のJARファイルは完全には変更されません。

注意:
認証用にシグネチャ・ファイルを使用している場合、元のJARファイルに含まれているシグネチャ・ファイルは、変更されずに更新後のJARファイルに残ります。プロファイルへのアクセスに署名が必要な場合は、新しいJARファイルの署名を再登録する必要があります。

プロファイルのセマンティクス・チェック用のSQLCheckerCustomizer

OracleにはSQLCheckerCustomizerと呼ばれる特殊なカスタマイザが用意されており、トランスレータを以前実行した際に生成されたプロファイルに対してセマンティクス・チェックを実行できます。このセマンティクス・チェックは、ソース・コードの変換時に通常実行されるものとほとんど同じです。

これは、実行時に使用するデータベースが変換時のセマンティクス・チェックで使用できない場合に特に有効です。このような場合は、デプロイメント後にランタイム・データベースに対してSQLCheckerCustomizerを使用できます。通常は、ソース・コードを使用できなくなった場合に行います。

使用するチェッカは、指定可能です。SQLCheckerCustomizerでは、デフォルトのOracleCheckerフロントエンドを受け入れると、適切なオンライン・チェッカを使用したオンライン・セマンティクス・チェックが実行されます。

注意:
プロファイルのオンライン・セマンティクス・チェックでは、カスタマイザ・ハーネスの接続オプションを使用して、接続パラメータを指定することも可能です。

カスタマイザ・ハーネスのverifyオプションによるSQLCheckerCustomizerの起動

次に、Oracleカスタマイザ・ハーネスのverifyオプションを指定して、SQLCheckerCustomizerをデフォルト・モードで実行する例を示します。デフォルトではオンライン・チェッカが使用されるので、カスタマイザ・ハーネスのuser、passwordおよびurlオプションを使用して、接続パラメータを指定する必要があります。(最初の例ではコマンドラインが折り返されて表示されていますが、全体が1行で入力されています。)

% sqlj -P-verify -P-user=scott -P-url=jdbc:oracle:oci:@ Foo_SJProfile0.ser Bar_SJProfile0.ser
Password: password

% sqlj -P-verify -P-user=scott -P-url=jdbc:oracle:oci:@ *.ser
Password: password

verifyオプションを指定すると、カスタマイザ・ハーネスのインスタンスが生成され、次のクラスが起動されます。

sqlj.runtime.profile.util.SQLCheckerCustomizer

プロファイル中のSQL操作に対するセマンティクス・チェックは、このクラスによって調整されます。セマンティクス・チェッカを指定することも、デフォルトのOracleCheckerセマンティクス・チェッカのフロントエンドを受け入れることも可能です。

次のオプションを使用すると、-P-verifyオプションを使用した場合と同じ結果になります。

-P-customizer=sqlj.runtime.profile.util.SQLCheckerCustomizer

このオプションで指定したカスタマイザは、SQLJの-default-customizerオプションで指定されたカスタマイザよりも優先されます。

注意:

- どのOracleカスタマイザでも同様ですが、SQLJコマンドラインで-P-verifyと-P-helpとを指定すると、ヘルプ出力とオプション・リストを見ることが可能です。

- verifyオプションを使用するとカスタマイザが起動しますが、SQLJの1回の実行で実行できるカスタマイザは1つのみです。このため、このオプションを指定した場合は、他のカスタマイザを起動できません。

- -P-print、-P-debugおよび-P-verifyのうち、同時に使用できるのは1つのみです。このうちのどれを使用した場合にも、専用のカスタマイザが起動されるためです。

コマンドライン構文は、次のとおりです。

sqlj -P-verify <conn params> profile_list

次にコマンドラインの例を示します。

sqlj -P-verify <conn params> Foo_SJProfile*.ser

プロパティ・ファイルの構文は、次のとおりです。

profile.verify

(SQLJコマンドラインにはプロファイルを必ず指定してください。通常はカスタマイザ・ハーネスの接続オプションを指定します。)

次にプロパティ・ファイルの例を示します。

profile.verify

デフォルト値は、次のとおりです。

NA

SQLCheckerCustomizerオプション

他のカスタマイザと同様に、SQLCheckerCustomizerのオプションも、SQLJコマンドラインで接頭辞-P-Cを付けて設定できます。SQLJプロパティ・ファイルでは、接頭辞profile.Cを使用します。

SQLCheckerCustomizerでは、次のオプションがサポートされています。

- checker: 使用するセマンティクス・チェッカを指定するためのオプション。デフォルトでは、OracleCheckerフロントエンドが使用されます(SQLJ変換時のチェックに関して)。

- warn: プロファイルのセマンティクス・チェック時に出力される警告およびメッセージのカテゴリを指定するためのオプション。これは、SQLJの-warnフラグ(変換時のセマンティクス・チェックにおける警告カテゴリ用)に相当し、同じ設定をサポートし、同じデフォルトを使用します。「トランスレータからの警告(-warn)」を参照してください。

SQLCheckerCustomizerセマンティクス・チェッカのオプション(checker)

checkerオプションを使用すると、プロファイル中のSQL操作のチェックに使用するセマンティクス・チェッカを指定できます。

このオプションは、デフォルトではOracleセマンティクス・チェッカのフロントエンドoracle.sqlj.checker.OracleCheckerを使用します(これは、SQLCheckerCustomizerに対して環境に適切なオンライン・チェッカを選択します)。OracleCheckerの詳細は、「セマンティクス・チェッカおよびOracleCheckerフロントエンド(デフォルトのチェッカ)」を参照してください。

次に完全なコマンドラインの例を挙げて、SQLCheckerCustomizerのcheckerオプションと、カスタマイザ・ハーネスのverifyオプションおよび接続オプションとを併用する方法を示します。

% sqlj -P-verify -P-user=scott -P-url=jdbc:oracle:oci:@ -P-Cchecker=abc.def.MyChecker *.ser
Password: password

(折り返されて表示されていますが、全体が1行で入力されています。)

コマンドライン構文は、次のとおりです。

-P-Cchecker=checker_class

次にコマンドラインの例を示します。

-P-Cchecker=a.b.c.MyChecker

プロパティ・ファイルの構文は、次のとおりです。

profile.Cchecker=checker_class

次にプロパティ・ファイルの例を示します。

profile.Cchecker=a.b.c.MyChecker

デフォルト値は、次のとおりです。

oracle.sqlj.checker.OracleChecker

SQLCheckerCustomizerの警告オプション(warn)

warnオプションでは、SQLJトランスレータの-warnオプションと同様に、プロファイルのセマンティクス・チェック時に出力される警告やメッセージのカテゴリを選択できます。

これらのオプションの機能と使用可能な設定の詳細は、「トランスレータからの警告(-warn)」を参照してください。

このオプションのデフォルトでは、verboseおよびportableが有効化されていなければ、all,noverbose,noportableの設定値が使用され、すべての警告カテゴリが出力されます。このときに出力されるのは、継承階層の要件、データの精度、NULL化可能なデータの変換による損失、および名前付きイテレータの厳密な合致に関する警告です。これらのデフォルトは、SQLJ変換時の警告のデフォルトと同じです。

次に完全なコマンドラインの例を挙げて、SQLCheckerCustomizerのwarnオプションと、カスタマイザ・ハーネスのverifyオプションおよび接続オプションとを併用する方法を示します。このように指定すると、移植性に関する警告のみが出力されます。

% sqlj -P-verify -P-user=scott -P-url=jdbc:oracle:oci:@ -P-Cwarn=none,portable *.ser
Password: password

(折り返されて表示されていますが、全体が1行で入力されています。)

コマンドライン構文は、次のとおりです。

-P-Cwarn=comma-delimited_list_of_flags

次にコマンドラインの例を示します。

-P-Cwarn=none,verbose

プロパティ・ファイルの構文は、次のとおりです。

profile.Cwarn=comma-delimited_list_of_flags

次にプロパティ・ファイルの例を示します。

profile.Cwarn=none,verbose

デフォルト値は、次のとおりです。

all,noverbose,noportable

デバッグ用のAuditorInstallerカスタマイザ

ISOコード生成の場合、SQLJでは、AuditorInstallerという特別なカスタマイザが提供されます。このカスタマイザは、SQLJコマンドラインで指定したプロファイルに、オーディタと呼ばれるデバッグ文のセットを挿入します。これらのプロファイルは、前回のカスタマイズによって生成済であることが必要です。

アプリケーションを実行すると、SQLJランタイムでデバッグ文が実行され、メソッド・コールと戻り値のトレース情報が表示されます。

デバッグ文を挿入するには、カスタマイズの一般オプションの場合と同じように、先頭に-P-を付けて、カスタマイザ・ハーネスのdebugオプションを使用します。(このオプションの構文の詳細は、「カスタマイザ・ハーネスの-debugオプションによるAuditorInstallerの起動」を参照してください。)

オーディタとコード・レイヤーの概要

アプリケーションのカスタマイズ時に、Oracleカスタマイザは、ランタイム機能の様々なレベルのコードのレイヤー(通常のレイヤー数は4以下)に、プロファイルを実装します。一番下のレイヤーは純粋なOracle JDBCコールを使用し、JDBCの機能を通じて実行できるSQLJ文を実装します。上位の各レイヤーは、JDBCではサポートされていないSQLJ機能用のレイヤーで、SQLJランタイムによってのみ処理されます。たとえば、JDBC結果セットをSQLJイテレータに変換するイテレータ変換文(CAST)用のレイヤーがあります。他には、代入文(SET)用のレイヤーがあります。

コード・レイヤーでは、実行時に各SQLJ実行文が、まず一番上のレイヤーに渡されます。次に、その文を処理できるレイヤー(通常は、すべてのJDBCコールを実行できるレイヤー)まで、1レベルずつレイヤーを経過します。

AuditorInstallerの1回の実行でデバッグ文を挿入できるレイヤーは1つです。特定のコード・レイヤーに挿入されたデバッグ文のセットを総称して、オーディタと呼びます。実行時には、レイヤーにコールが渡されるたびに、そのレイヤーに挿入されているオーディタが起動されます。

通常、JDBCレイヤーより上にある特殊なコード・レイヤーはいずれも、本来のデバッグ対象ではないため、オーディタは一番下か一番上のレイヤーに挿入します。一番上のレイヤーにオーディタを挿入すると、ランタイム・デバッグでは、すべてのSQLJ実行文からのメソッド・コールのトレースが出力されます。一番下のレイヤーにオーディタを挿入すると、ランタイム・デバッグでは、JDBCコールを戻すすべてのSQLJ実行文からのメソッド・コールのトレースが出力されます。

複数のレベルにオーディタを挿入するには、AuditorInstallerを複数回実行します。これは、一番下のレイヤーと一番上のレイヤーにオーディタを挿入する場合などに行います。

オーディタを挿入するレイヤーの指定方法の詳細は、「AuditorInstallerのdepthオプション(depth)」を参照してください。

カスタマイザ・ハーネスの-debugオプションによるAuditorInstallerの起動

次に、Oracleカスタマイザ・ハーネスの-debugオプションを指定して、AuditorInstallerをデフォルト・モードで実行する例を示します。

% sqlj -P-debug Foo_SJProfile0.ser Bar_SJProfile0.ser

% sqlj -P-debug *.ser

% sqlj -P-debug myappjar.jar

debugオプションを指定すると、カスタマイザ・ハーネスのインスタンスが生成され、次のクラスが起動されます。

% sqlj.runtime.profile.util.AuditorInstaller

上に示したクラスは、デバッグ文の挿入作業を実行するクラスです。

次のオプションを使用すると、-P-debugオプションを使用した場合と同じ結果になります。

-P-customizer=sqlj.runtime.profile.util.AuditorInstaller

このオプションで指定したカスタマイザは、SQLJの-default-customizerオプションで指定されたカスタマイザよりも優先されます。

次の点に注意してください。

- オーディタをインストールしてアプリケーションを実行するには、CLASSPATHにSQLJファイルtranslator.jarがあることが必要です。(通常、変換済のSQLJアプリケーションを実行するには、ランタイム・ライブラリのみが必要です。)

- どのOracleカスタマイザの場合も、SQLJコマンドラインで-P-debugと-P-helpとを指定すると、ヘルプ出力とオプション・リストを見ることが可能です。

- debugオプションを使用するとカスタマイザが起動しますが、SQLJの1回の実行で実行できるカスタマイザは1つのみです。このため、このオプションを指定した場合は、他のカスタマイザを起動できません。

- -P-print、-P-debugおよび-P-verifyのうち、同時に使用できるのは1つのみです。このうちのどれを使用した場合にも、専用のカスタマイザが起動されるためです。

コマンドライン構文は、次のとおりです。

sqlj -P-debug profile_list

次にコマンドラインの例を示します。

sqlj -P-debug Foo_SJProfile*.ser

プロパティ・ファイルの構文は、次のとおりです。

profile.debug

(ファイル・リストのプロファイルにも指定します。)

次にプロパティ・ファイルの例を示します。

profile.debug

デフォルト値は、次のとおりです。

NA

AuditorInstallerのランタイム出力

AuditorInstallerでデバッグ文を挿入すると、実行時にコールされたメソッドと戻り値がトレースされます。この処理は、デバッグ文が挿入されたすべてのプロファイル・レイヤーに対して行われます。実行時にはデバッグ出力を限定できません。

AuditorInstallerの出力は、プロファイルのみに対応付けられています。元の.sqljソース・ファイル内の行とのマッピングは、現行の時点ではサポートされていません。

次は、AuditorInstallerのランタイム出力の例の抜粋です。この出力は、SQLJのSELECT INTO文の出力と似ています。

oracle.sqlj.runtime.OraProfile@1 . getProfileData (  )
oracle.sqlj.runtime.OraProfile@1 . getProfileData returned sqlj.runtime.profile.ref.ProfileDataImpl@2
oracle.sqlj.runtime.OraProfile@1 . getStatement ( 0 )
oracle.sqlj.runtime.OraProfile@1 . getStatement returned
oracle.sqlj.runtime.OraRTStatement@3
oracle.sqlj.runtime.OraRTStatement@3 . setMaxRows ( 1000 )
oracle.sqlj.runtime.OraRTStatement@3 . setMaxRows returned
oracle.sqlj.runtime.OraRTStatement@3 . setMaxFieldSize ( 3000 )
oracle.sqlj.runtime.OraRTStatement@3 . setMaxFieldSize returned
oracle.sqlj.runtime.OraRTStatement@3 . setQueryTimeout ( 1000 )
oracle.sqlj.runtime.OraRTStatement@3 . setQueryTimeout returned
oracle.sqlj.runtime.OraRTStatement@3 . setBigDecimal ( 1 , 5 )
oracle.sqlj.runtime.OraRTStatement@3 . setBigDecimal returned
oracle.sqlj.runtime.OraRTStatement@3 . setBoolean ( 2 , false )
oracle.sqlj.runtime.OraRTStatement@3 . setBoolean returned
oracle.sqlj.runtime.OraRTStatement@3 . executeRTQuery (  )
oracle.sqlj.runtime.OraRTStatement@3 . executeRTQuery returned
oracle.sqlj.runtime.OraRTResultSet@6
oracle.sqlj.runtime.OraRTStatement@3 . getWarnings (  )
oracle.sqlj.runtime.OraRTStatement@3 . getWarnings returned null
oracle.sqlj.runtime.OraRTStatement@3 . executeComplete (  )
oracle.sqlj.runtime.OraRTStatement@3 . executeComplete returned
oracle.sqlj.runtime.OraRTResultSet@6 . next (  )
oracle.sqlj.runtime.OraRTResultSet@6 . next returned true
oracle.sqlj.runtime.OraRTResultSet@6 . getBigDecimal ( 1 )
oracle.sqlj.runtime.OraRTResultSet@6 . getBigDecimal returned 5
oracle.sqlj.runtime.OraRTResultSet@6 . getDate ( 7 )
oracle.sqlj.runtime.OraRTResultSet@6 . getDate returned 1998-03-28

メソッド・コールごとに、2行出力されます。1行目はそのコールと入力パラメータ、2行目は戻り値を示します。

注意:
oracle.sqlj.runtimeパッケージ内に含まれるクラスは、SQLJランタイム・クラスで、同様の名前を持つJDBCのクラスと同等の機能を持ちます。たとえば、OraRTResultSetは、JDBC ResultSetインタフェースによるSQLJランタイム実装であり、同等の属性およびメソッドが含まれています。

AuditorInstallerオプション

他のカスタマイザと同様に、AuditorInstallerのオプションも、SQLJコマンドラインで接頭辞-P-Cを付けて設定できます(SQLJプロパティ・ファイルでは、profile.Cを使用します)。

AuditorInstallerでは、次のオプションがサポートされています。

- depth: プロファイル内のランタイム機能のレイヤーをどこまで下がるのかを指定するためのオプション。

- log: 挿入されたオーディタのデバッグ文からのランタイム出力を書き込むファイルを指定するためのオプション。

- prefix: 挿入されたデバッグ文からのランタイム出力の各行に付ける接頭辞を指定するためのオプション。

- showReturns: ランタイム・コールをトレースした際の戻りの引数を、挿入済のオーディタに書き込むためのオプション。

- showThreads: ランタイム・コールをトレースした際のスレッド名を、挿入済のオーディタに書き込むためのオプション(マルチスレッド・アプリケーション専用)。

- uninstall: プロファイルに対して、前回AuditorInstallerが起動したときにプロファイルに挿入されたデバッグ文を削除するためのオプション。

AuditorInstallerのdepthオプション(depth)

「オーディタとコード・レイヤーの概要」で説明したように、AuditorInstallerでは、オーディタと呼ばれるデバッグ文のセットを1回の実行で1つのコード・レイヤーにのみ挿入します。AuditorInstallerのdepthオプションを使用すると、挿入先のレイヤーを指定できます。複数のレベルにオーディタを挿入するには、AuditorInstallerを複数回実行します。

レイヤーには、整数で番号が付けられます。一番上がレイヤー0(ゼロ)になり、レイヤーの階層は通常最大で2つまたは3つになります。通常、一番上のレイヤーには0(ゼロ)、一番下のレイヤーには-1を設定します。実際には、これ以外の特定のレイヤーにオーディタを挿入するのは困難です。これは、各種のSQLJ実行文に使用されるレイヤー番号が、公開されていないためです。

depthオプションは、prefixオプションとともに設定できます。AuditorInstallerを複数回実行して、異なるレイヤーに異なる接頭辞を指定すると、実行時に出力される情報がどのレイヤーのものか確認できます。

depthオプションが設定されていない場合や、プロファイルに指定されているレイヤー数を超えた値が指定された場合、オーディタは一番下のレイヤーに挿入されます。

コマンドライン構文は、次のとおりです。

-P-Cdepth=n

次にコマンドラインの例を示します。

-P-Cdepth=0

プロパティ・ファイルの構文は、次のとおりです。

profile.Cdepth=n

次にプロパティ・ファイルの例を示します。

profile.Cdepth=0

デフォルト値は、次のとおりです。

-1 (deepest layer)

AuditorInstallerのlog_fileオプション(log)

logオプションを使用すると、現行の実行で挿入しているオーディタからのランタイム出力を書き込むファイルを指定できます。そうしない場合は、標準出力が使用されて、デバッグ結果がSQLJメッセージと同じ出力先に出力されるようになります。

オーディタが出力ファイルに書き込むメッセージは、以前の内容を上書きするのではなく、追加されます。そのため、複数のオーディタに対して同じログ・ファイルを指定しても、競合は起こりません。通常、アプリケーション内のすべてのレイヤーからのデバッグ情報は、同じログ・ファイルに書き込まれます。

コマンドライン構文は、次のとおりです。

-P-Clog=log_file

次にコマンドラインの例を示します。

-P-Clog=foo/bar/mylog.txt

プロパティ・ファイルの構文は、次のとおりです。

profile.Clog=log_file

次にプロパティ・ファイルの例を示します。

profile.Clog=foo/bar/mylog.txt

デフォルト値は、次のとおりです。

Empty (for standard output)

AuditorInstallerのprefixオプション(prefix)

prefixオプションを使用して、ランタイム出力の各行に付ける接頭辞を指定します。この出力は、今回の実行で起動するAuditorInstallerによって挿入されるデバッグ文からの結果です。

通常、このオプションは、depthオプションとともに使用されます。AuditorInstallerを複数回実行して、各レイヤーに異なる接頭辞を指定すると、実行時に出力される情報がどのレイヤーのものか確認できます。

コマンドライン構文は、次のとおりです。

-P-Cprefix="string"

次にコマンドラインの例を示します。

-P-Cprefix="layer 2: "

プロパティ・ファイルの構文は、次のとおりです。

profile.Cprefix="string"

次にプロパティ・ファイルの例を示します。

profile.Cprefix="layer 2: "

デフォルト値は、次のとおりです。

Empty

AuditorInstallerの戻り引数オプション(showReturns)

showReturnsオプションは、ランタイム・コールのトレース時に戻り引数の出力を有効化/無効化するためのオプションです。デフォルトでは、出力が有効化されます。

showReturnsを有効にした場合(デフォルト)のサンプル出力を数行のみ次に示します。

oracle.sqlj.runtime.OraRTStatement@3 . executeComplete (  )
oracle.sqlj.runtime.OraRTStatement@3 . executeComplete returned
oracle.sqlj.runtime.OraRTResultSet@6 . next (  )
oracle.sqlj.runtime.OraRTResultSet@6 . next returned true
oracle.sqlj.runtime.OraRTResultSet@6 . getBigDecimal ( 1 )
oracle.sqlj.runtime.OraRTResultSet@6 . getBigDecimal returned 5
oracle.sqlj.runtime.OraRTResultSet@6 . getDate ( 7 )
oracle.sqlj.runtime.OraRTResultSet@6 . getDate returned 1998-03-28

showReturnsを無効にした場合の出力は、次のようになります。

oracle.sqlj.runtime.OraRTStatement@3 . executeComplete (  )
oracle.sqlj.runtime.OraRTResultSet@6 . next (  )
oracle.sqlj.runtime.OraRTResultSet@6 . getBigDecimal ( 1 )
oracle.sqlj.runtime.OraRTResultSet@6 . getDate ( 7 )

各メソッドのコールに必要なのはコール行のみであって、コール行と戻り行の両方を使用する必要はありません。

コマンドライン構文は、次のとおりです。

-P-CshowReturns<=true|false>

次にコマンドラインの例を示します。

-P-CshowReturns=false

プロパティ・ファイルの構文は、次のとおりです。

profile.CshowReturns<=true|false>

次にプロパティ・ファイルの例を示します。

profile.CshowReturns=false

デフォルト値は、次のとおりです。

true

AuditorInstallerのスレッド名オプション(showThreads)

showThreadsオプションは、ランタイム・コールのトレース時にスレッド名の出力を有効化/無効化するためのオプションです(マルチスレッド・アプリケーション専用)。デフォルトでは、出力が無効化されます。

このオプションを有効化すると、トレース出力中のメソッド名の先頭にスレッド名が付加されます。

コマンドライン構文は、次のとおりです。

-P-CshowThreads<=true|false>

次にコマンドラインの例を示します。

-P-CshowThreads

プロパティ・ファイルの構文は、次のとおりです。

profile.CshowThreads<=true|false>

次にプロパティ・ファイルの例を示します。

profile.CshowThreads

デフォルト値は、次のとおりです。

false

AuditorInstallerのuninstallオプション(uninstall)

uninstallオプションを使用すると、前回AuditorInstallerを起動したときに挿入されたデバッグ文が削除されます。uninstallオプションを使用するたびに、最後に挿入されたオーディタが削除されます。

プロファイル内のすべてのオーディタを削除するには、プロファイルが変更されなかったことを示すメッセージが表示されるまで、AuditorInstallerを繰り返し実行します。

コマンドライン構文は、次のとおりです。

-P-Cuninstall

次にコマンドラインの例を示します。

-P-Cuninstall

プロパティ・ファイルの構文は、次のとおりです。

profile.Cuninstall

次にプロパティ・ファイルの例を示します。

profile.Cuninstall

デフォルト値は、次のとおりです。

Disabled

完全なコマンドラインの例

ここでは、AuditorInstallerの各種オプションを指定した完全なSQLJコマンドラインの例を示します。

次のコマンドラインはデバッグ文のセット、つまりオーディタを一番下のレイヤー(デフォルトのレイヤー)に挿入し、ランタイム出力を標準出力に出力します。

% sqlj -P-debug MyApp_SJProfile*.ser

次のコマンドラインは、オーディタを一番下のレイヤーに挿入し、ランタイム出力をlog.txtに出力します。

% sqlj -P-debug -P-Clog=foo/bar/log.txt MyApp_SJProfile*.ser

次のコマンドラインは、オーディタを一番下のレイヤーに挿入し、ランタイム出力を標準出力に出力します。この指定では、スレッド名は表示されますが、戻り引数は表示されません。

% sqlj -P-debug -P-CshowThreads=true -P-CshowReturns=false MyApp_SJProfile*.ser

オーディタをレイヤー0(一番上のレイヤー)に挿入します。ランタイム出力をlog.txtに送信し、ランタイム出力の各行に「Layer 0: 」という接頭辞を付けます(次のコマンドラインは折り返されて表示されていますが、全体が1行で入力されています)。

% sqlj -P-debug -P-Clog=foo/bar/log.txt -P-Cdepth=0 -P-Cprefix="Layer 0: "
MyApp_SJProfile*.ser

次のコマンドラインは、オーディタを削除します。(このコマンドを実行すると、最後に挿入されたオーディタが削除されます。すべてのオーディタを削除するには、このコマンドを繰り返し実行します。)

% sqlj -P-debug -P-Cuninstall MyApp_SJProfile*.ser

索引
A B C D E F G H I J K L M N O P R S T U V W

A

アクセス・モードの設定(トランザクション), 7.5.2

代替環境、サポート, 8.4

アプレット、SQLJの使用, 2.6.1

配列

イテレータ列, 5.1.2

VARRAY, 6.1.3

ASENSITIVE(カーソル状態), 4.1.5.1 代入文(SET), 4.6 前提、環境, 1.1.1 AuditorInstaller

コマンドラインの例, A.6.5

デバッグ用のカスタマイザ, A.6

起動, A.6.2

オプション, A.6.4

ランタイム出力, A.6.3

オーディタを持つプロファイルでのデバッグ, A.6.1 自動コミット

既存の接続での変更, 3.5.4

サーバーで未サポート, 11.2.2

新しい接続での指定, 3.5.3

B

backupオプション(カスタマイザ・ハーネス), A.3.2.1

下位互換性

Oracle SQLJ、概略, 1.1.5

バッチ更新

バッチ制限, 10.1.3

バッチ可能で互換性のある文, 10.1.3

非互換の文に対するバッチ処理, 10.1.3

バッチの取消し, 10.1.3

注意, 10.1.3

有効化と無効化, 10.1.3

実行中のエラー状態, 10.1.3

明示的および暗黙的なバッチ実行, 10.1.3

概要, 10.1.3

更新カウント, 10.1.3

暗黙的な実行コンテキストの使用, 10.1.3

再帰的コールイン, 10.1.3

BetterDate(カスタムJavaクラス), 6.2.6 BFILE

ストアド・ファンクションの結果, 5.3.2

BFILEサポート, 5.3.2

BigDecimal

マッピング(属性が対象), 6.4.2

サポート, 5.3.6

プロファイルのバイナリ移植性, 3.8.3.2 bind-by-identifierオプション(sqlj -bind-by-identifier), 8.3.2 BLOBサポート, 5.3.2 BOOLEAN型(PL/SQL), 5.1.3 builtintypesオプション(JPublisher -builtintypes), 6.4.2

C

C接頭辞(sqlj -C-x), 8.3.1

cacheオプション(sqlj -cache), 8.3.3

オンライン・チェッカの結果のキャッシング, 8.3.3

文のキャッシング, 10.1.2

ストアド・プロシージャ用のCALL構文, 4.7.1

ストアド・ファンクションのコール4.7.2

ストアド・プロシージャのコール, 4.7.1

実行時に対するコール、生成済, 9.1.3

caseオプション(JPublisher -case), 6.4.2

大/小文字を区別するSQLのUDT名, 6.2.3, 6.2.3, 6.4.2, 6.4.3

エラーの原因/処置の出力, 8.2.4

CHAR比較、空白埋め, 8.2.6, A.3.6.7

文字エンコーディング

コマンドラインの例, 9.4.2

メッセージ, 9.4.2

ソース, 9.4.2

概要, 9.4.1

実行時の設定, 9.4.4

native2asciiの使用, 9.4.4

Publicクラスに対するソース名のチェック, 8.4.1 ソースのチェック、拡張解決検索, 8.3.2 checkerオプション(SQLCheckerCustomizer), A.5.2.1 checkfilenameオプション(sqlj -checkfilename), 8.4.1 checksourceオプション(sqlj -checksource), 8.3.2 サーバーでのクラスのロード, 11.2.4 クラス・スキーマ・オブジェクトの名前付け

生成, 11.4.3

ロード, 11.3.2

CLASSPATHとPATH, 1.2.3 CLASSPATHオプション(sqlj -classpath), 8.2.1 句、SQLJ実行文, 4.2.2 サーバーでの実行のためのクライアント側変換, 11.3 CLOBサポート, 5.3.2 close()メソッド(DefaultContext), 3.2.5 close()メソッド(ExecutionContext), 7.2.4.6 close()メソッド(Oracleクラス), 3.2.4, 3.2.5 CLOSE_CONNECTION, 7.6.1 コード生成

概要, 9.1.3

Oracle固有とISO標準, 3.7.4

translator -codegenオプション, 8.2.6

プロファイルのコード・レイヤー, A.6.1 codegenオプション(SQLJ -codegen), 8.2.6 コレクション

カスタムJavaクラス, 6.2

コレクション型の作成, 6.3

データ型, 6.1.4

基本概念, 6.1.3

代替クラスへのマッピング, 6.4.2

ORADataの指定, 6.2.1

コレクションのサポートの概要, 6.1.1

型のマッピング指定, 6.4.2, 6.4.2

強い型指定, 6.6

弱い型指定の制限, 6.8.2

弱い型指定のサポート, 6.8.1

列の定義(型/サイズ)

概要, 10.1.4

Oracleカスタマイザoptcolsオプション, A.3.6.4

SQLJ -optcolsオプション, 8.2.6

コマンドライン(トランスレータ)

非実行時のエコー, 8.1.2

例, 8.1.2

概要, 8.1

構文と引数, 8.1.2

コミット

自動と手動, 3.5.2

イテレータおよび結果セットに対する影響, 3.5.6

手動, 3.5.5

既存の接続での自動コミットの変更, 3.5.4

新しい接続での自動コミットの指定, 3.5.3

compat(互換性)オプション(Oracleカスタマイザ), A.3.6.2 compatibleオプション(JPublisher -compatible), 6.4.2 コンパイル

2段階で行うコンパイル, 8.4.1

サーバーでのdebugオプション, 11.4.2

変換時, 9.1.4

有効化/無効化, 8.3.2

サーバー, 11.2.4

compileオプション(sqlj -compile), 8.3.2 コンパイラ

CLASSPATHオプション, 8.2.1

javacのオプションのサポート, 8.1.1

SQLJを介したオプション, 8.3.1

関連オプション, 8.4.1

必要な動作, 8.4.1

名前の指定, 8.4.1

compiler encodingサポート・オプション(sqlj), 8.4.1 compiler executableオプション(sqlj), 8.4.1 コンパイラ・メッセージの出力パイプ・オプション(sqlj), 8.4.1 compiler output fileオプション(sqlj -compiler...), 8.4.1 componentsオプション(sqlj -components), 8.2.5 設定およびインストールの検証, 1.2 接続文字列

OCIドライバ, 3.1.1

Thinドライバ, 3.1.1

サーバー側内部ドライバ, 3.1.1

サーバー側Thinドライバ, 3.1.1

非推奨のSID, 1.3.1

データベース・サービス名の使用, 1.3.1

connect()メソッド(Oracleクラス), 3.2.4 接続コンテキスト

接続の終了, 7.1.5

概要, 7.1.1

JDBC接続からの変換, 7.6.1

JDBC接続への変換, 7.6.1

IMPLEMENTS句を使用した宣言, 7.1.6

宣言, 4.1.3

接続コンテキスト・クラスの宣言, 7.1.3

SQLJデータ・ソース, 7.1.9, 7.1.10

デフォルトの接続の取得, 7.1.5

実行コンテキストの取得, 7.1.5

JDBC接続の取得, 7.1.5

実装と機能, 7.1.5

接続オブジェクトのインスタンス化, 7.1.3

メソッド, 7.1.5

複数の接続、例, 7.1.4

実行コンテキストとの関係, 7.2.1

セマンティクス・チェック, 7.1.7

デフォルトの接続の設定, 7.1.5

文の接続の指定, 7.1.3

実行文の指定, 4.2.3

接続

終了, 3.2.2

JDBCとの共有接続の終了, 7.6.1

サーバーでのデータベース接続, 11.2.1

SQLJデータ・ソース, 7.1.9, 7.1.10

JDBCトランザクション・メソッド, 7.5.4

自動コミットの変更, 3.5.4

複数、宣言済の接続コンテキストの使用, 3.2.3

接続のためのOracleクラス, 3.2.4

設定, 1.3.1

JDBCとの共有接続, 7.6.1

単一または複数のデフォルト・コンテキストの使用, 3.2.1

自動コミットの指定, 3.5.3

トランスレータのオプション, 8.2.3

検証, 1.3.2

コンテキスト式

実行時評価, 4.3.5

概要, 4.3.4

contextオプション(カスタマイザ・ハーネス), A.3.2.2 .serプロファイルから.classへの変換, 8.3.2 CURSOR構文(ネストした表), 6.6.1 カスタムJavaクラス

カスタムJavaクラス, 6.2

コンパイル, 6.2.4

JPublisherでの作成, 6.4

例, 6.4.6

拡張, 6.4.7

JPublisherによる生成, 6.4.2

代替クラスへのマッピング, 6.4.2

データの読込みと書込み, 6.2.5

要件, 6.2.3

サンプル・クラス, 6.2.6

メンバー名の指定, 6.4.4

強い型指定、定義, 6.1.1

オブジェクト・メソッドのサポート, 6.2.2

シリアライズ・オブジェクトへの使用, 6.7.2

弱い型指定、定義, 6.1.1

CustomDatum(現在推奨されていない), 6.2.1 カスタマイズ

.serプロファイルから.classへの変換, 8.3.2

作成と登録, A.2.3

カスタマイザ・ハーネスの接続オプション, A.3.3

カスタマイザ・ハーネスの一般オプション, A.3.2

カスタマイザ・ハーネスのオプションの概要, A.3.1

列の型/サイズの定義, A.3.6.4

パラメータ・サイズの定義, A.3.6.5

変換時, 9.1.5

有効化/無効化, 8.3.2

エラー・メッセージとステータス・メッセージ, A.2.4

強制カスタマイズ, A.3.6.3

jarファイルの使用方法, A.4

カスタマイズの詳細, A.2

オプション, A.3

特別なカスタマイザの起動のためのオプション, A.3.4

Oracleカスタマイザのオプション, A.3.6

カスタマイザ固有のオプションの概要/構文, A.3.5

パラメータのデフォルト・サイズ, A.3.6.6

関連するSQLJオプション, A.3.8

SQL変換の表示, A.3.6.8

文のキャッシュ・サイズ, A.3.6.9

処理の手順, A.2.2

使用しているOracle拡張機能の概要, A.3.6.10

バージョン互換性, A.3.6.2

カスタマイザ, 3.8.2, 3.8.2 カスタマイザ・ハーネス

接続オプション, A.3.3

一般オプション, A.3.2

特別なカスタマイザの起動, A.3.4

オプションの概要, A.3.1

概要, A.2.1

カスタマイザのオプション(カスタマイザ・ハーネス), A.3.2.3 カスタマイザ

選択, A.3

カスタマイザの選択用のオプション, A.3.2.3

概要, A.2.1

SQLJを介して渡されるオプション, 8.3.1

デフォルトの指定, 8.4.2

D

dオプション(sqlj -d), 8.2.2

データ・ソースのサポート

接続の関連付け, 7.1.8

デフォルト・コンテキストの関連付け, 7.1.8

自動コミット・モード, 7.1.8

dataSource(WITH句), 4.1.5.1

概要, 7.1.8

要件, 7.1.8

SQLJデータ・ソースのクラス, 7.1.9

SQLJデータ・ソースのインタフェース, 7.1.9

SQLJ固有のデータ・ソース, 7.1.9

データベース接続、検証, 1.3.2 データベースURL

オンライン・チェック用のデフォルトの接頭辞, 8.2.3

非推奨のSID, 1.3.1

データベース・サービス名の使用, 1.3.1

DBMS_JAVAパッケージ

サーバー出力デバイスの設定, 11.2.3

サーバー側オプションの設定, 11.4.2

DBMS_LOBパッケージ, 5.3.2 debugオプション(カスタマイザ・ハーネス), A.3.4.1 コンパイル用のdebugオプション(サーバー側), 11.4.2 デバッグ

AuditorInstallerコマンドラインの例, A.6.5

AuditorInstallerカスタマイザ, A.6

AuditorInstallerオプション, A.6.4

AuditorInstallerのランタイム出力, A.6.3

コンパイル用のdebugオプション(サーバー側), 11.4.2

debugオプション、カスタマイザ・ハーネス, A.3.4.1

JDeveloper, 10.2.4

AuditorInstallerの起動, A.6.2

行マッピング、SQLJソースからclassへ, 8.2.4

行マッピング、SQLJソースからclassへ(jdb), 8.2.4

宣言

接続コンテキスト宣言, 4.1.3

IMPLEMENTS句, 4.1.4

イテレータ宣言, 4.1.2

概要, 4.1

WITH句, 4.1.5

デフォルト接続

Oracle.connect()による設定, 3.2.1

setDefaultContext()による設定, 3.2.1

default customizerオプション(sqlj), 8.4.2 サーバーでのデフォルトの出力デバイス, 11.2.3 デフォルトのプロパティ・ファイル(トランスレータ), 8.1.3 デフォルトのセマンティクス・チェッカ, 8.3.3 デフォルトのURL接頭辞のオプション(sqlj), 8.2.3 DefaultContextクラス

close()メソッドのパラメータ, 3.2.5

コンストラクタ, 3.2.5

主要メソッド, 3.2.5

単一または複数の接続での使用, 3.2.1

列の型/サイズの定義, 10.1.4 パラメータ・サイズの定義, 10.1.5 デモ・アプリケーション(SQLJ)、可用性, 1.2.1 depthオプション(AuditorInstaller), A.6.4.1 ダイジェスト・オプション(カスタマイザ・ハーネス), A.3.2.4 dirオプション(sqlj -dir), 8.2.2 ディレクトリ

生成される.classおよび.ser, 8.2.2

生成される.java, 8.2.2

dirty reads, 7.5.3 DMSサポート

DMS用のコマンドライン・オプション, 8.2.5, 10.3.2

例, 10.3.5

DMSサポートの概要, 10.3.1

DMS用のランタイム・コマンド, 10.3.3

センサーとメトリック, 10.3.4

SQLJ DMSプロパティ・ファイル, 10.3.3

driverオプション(カスタマイザ・ハーネス), A.3.3.4 ドライバ登録オプション(sqlj -driver), 8.2.3 dropjava, 11.5 Javaスキーマ・オブジェクトの削除, 11.5 ダイナミック・モニタリング・サービス、SQLJサポート, 10.3 動的SQL

定義, 2.1

JDBCコード, 7.6

PL/SQLコード, 4.2.5

SQLJでの動的SQLのサポート

例, 7.7.2

概要, 7.7

メタ・バインド式, 7.7.1

実行時の動作, 7.7.1

変換時の動作, 7.7.1

E

echoオプション、非実行, 8.2.1

非実行でのコマンドラインのエコー, 8.1.2

エンコーディング

メッセージの文字エンコーディング, 9.4.2

ソースの文字エンコーディング, 9.4.2

コマンドラインの例, 9.4.2

コンパイラへのオプションの無効化, 8.4.1

文字エンコーディングの概要, 9.4.1

実行時の設定, 9.4.4

サーバーでの指定, 11.4.2

native2asciiの使用, 9.4.4

encodingオプション(サーバー側), 11.4.2 encodingオプション、ソース・ファイル(sqlj -encoding), 8.2.2 環境の前提と要件, 1.1 環境変数、トランスレータ・オプション, 8.1.4 環境、使用例と制限事項, 1.1.3 エラー

メッセージの文字エンコーディング, 9.4.2

カスタマイズ時のメッセージ, A.2.4

メッセージ、コードおよびSQLの状態, 3.4.2

原因と処置の出力, 8.2.4

実行時の分類, 9.3.2

サーバー側のエラー出力, 11.4.4

トランスレータのエラー、警告、情報メッセージ, 9.2.1

例外

例外処理の要件, 3.4.1

処理, 3.4.2

例外処理の設定, 3.6

SQLExceptionサブクラスの使用, 3.4.3

実行文

例, 4.2.4

概要, 4.2

規則, 4.2.1

接続/実行コンテキストの指定, 4.2.3

SQLJ句, 4.2.2

PL/SQLブロックの使用, 4.2.5

実行コンテキスト

取消しメソッド, 7.2.4.3

close()メソッド, 7.2.4.6

制御メソッド, 7.2.4.2

作成と指定, 7.2.2

メソッドの使用、例, 7.2.4.7

概要, 7.2

接続コンテキストとの関係, 7.2.1

マルチスレッドとの関係, 7.2.5

セーブポイント・メソッド, 7.2.4.5

実行文の指定, 4.2.3

状態メソッド, 7.2.4.1

同期, 7.2.3

バッチ更新メソッド, 7.2.4.4

基本スキーマ, 3.2.6 終了コード、トランスレータ, 9.2.3 explainオプション(sqlj -explain), 8.2.4 イテレータ・クラスの拡張, 7.4.3 JPub生成クラスの拡張, 6.4.7 拡張

概要, 2.3

パフォーマンスの拡張, 10.1

使用している機能の概要, A.3.6.10

拡張型, 5.3

F

FETCH CURRENT構文(イテレータ), 7.4.5

FETCH構文(スクロール可能な位置イテレータ), 7.4.5

ファイル名の要件と制限, 3.10.4

fixedcharオプション(Oracleカスタマイザ), A.3.6.7

fixedcharオプション(SQLJ -fixedchar), 8.2.6

特殊処理のフラグ, 8.3.2

forceオプション(Oracleカスタマイザ), A.3.6.3

ForUpdate/updateColumns(WITH句)、非サポート, 4.1.5.1

フル・ネーム(スキーマ名), 11.3.2

ファンクション・コール、ストアド, 4.7.2

G

getConnection()メソッド(Oracleクラス), 3.2.4

グローバリゼーション・サポート

文字エンコーディング、言語サポート, 9.4.1

SQLJ外部, 9.4.4

概要, 2.7.1

関連するデータ型, 5.1.1

関連Java型, 9.4.3

関連SQLJおよびJava設定, 9.4.2

Unicode文字のサポート, 9.4.3

H

helpオプション(カスタマイザ・ハーネス), A.3.2.5

helpオプション(sqlj -help-xxxx), 8.2.1

コードのヒント、パラメータ・サイズ, 10.1.5

holdability(カーソル状態、WITH句)、非サポート, 4.1.5.1

ホスト式

基本的な構文, 4.3.2

識別子によるバインド, 8.3.2

実行時評価, 4.3.5

例, 4.3.3

実行時評価の例, 4.3.6

ホスト変数としてのイテレータおよび結果セット, 4.5.6

概要, 4.3.1

制限, 4.3.7

ネストした表の取出し, 6.6.3

JDBC 2.0のサポート型, 5.1.2

型サポートの概要, 5.1.1

ホスト変数, 2.4.1

I

IDEへのSQLJの統合, 2.7.2

IMPLEMENTS句

接続コンテキスト宣言, 7.1.6

イテレータ宣言, 7.4.2

構文, 4.1.4

必要なクラスのインポート, 3.6 情報メッセージ、トランスレータ, 9.2.1 トランスレータへの入力, 2.4.2 INSENSITIVE(カーソル状態), 4.1.5.1 インストールおよび設定の検証, 1.2 instrumentオプション(sqlj -instrument), 8.2.5 クラス・ファイルのインストルメント(linemap), 8.2.4 JDBCとの連係動作

接続コンテキストと接続, 7.6.1

イテレータと結果セット, 7.6.2

分離レベルの設定(トランザクション), 7.5.3 イテレータ

名前付きイテレータへのアクセス, 4.5.4

位置イテレータへのアクセス, 4.5.5

配列, 5.1.2

ホスト変数, 4.5.6

イテレータ列(ネスト), 4.5.7

ストアド・ファンクションの戻り値, 4.7.3

コミット/ロールバックの影響, 3.5.6

概要, 4.5.1

結果セットからの変換, 7.6.2

結果セットへの変換, 7.6.2

宣言, 4.1.2

名前付きイテレータの宣言, 4.5.4

位置イテレータの宣言, 4.5.5

IMPLEMENTS句での宣言, 7.4.2

拡張, 7.4.3

通常の使用手順, 4.5.2

名前付きイテレータのインスタンス化/移入, 4.5.4

位置イテレータのインスタンス化/移入, 4.5.5

イテレータ・クラスの機能, 7.4.1

名前付きと位置, 4.5.3

ネストした表用のネスト・イテレータ, 6.6.5

概要, 4.5

位置イテレータ、next()の使用, 4.5.5

結果セット・イテレータ(強い型指定), 4.5.1.1

結果セット・イテレータ(弱い型指定), 4.5.1.2, 7.4.4

スクロール可能, 7.4.5

スクロール可能な結果セット・イテレータ, 7.4.5

オブジェクトおよび参照の取出し, 6.5.1

名前付きイテレータの設定(例), 3.6

サブクラス化, 7.4.3

名前付きイテレータの使用, 4.5.4

位置イテレータの使用, 4.5.5

弱い型指定のイテレータの使用, 7.6.2

シリアライズされたオブジェクト, 6.7.3

J

J接頭辞(sqlj -J-x), 8.3.1

jarファイルのダイジェスト・オプション、カスタマイズ, A.3.2.4

プロファイル用のjarファイル, A.4

Javaバインド式(動的SQL), 7.7.1

サーバーでのJava名とSQL名, 11.2.5

Javaプロパティ、getProperty(), 9.4.4

Java VM

CLASSPATHオプション, 8.2.1

SQLJを介したオプション, 8.3.1

名前の指定, 8.4.1

SQLJ接続のためのJavaBeans, 7.1.10 javac互換, 8.1.1 JDBC 2.0

LOB型のサポート, 5.3

弱い型指定の構造体、参照、配列のサポート, 6.8

サポートされている型, 5.1.2

JDBC接続メソッド(トランザクション), 7.5.4 サーバーでのJDBCの注意事項, 11.2.2 JDBCドライバ登録オプション(sqlj -driver), 8.2.3 JDBCドライバ

Oracleドライバ, 3.1.1

変換のための選択, 3.1.2

カスタマイズのための選択/登録, A.3.3.4

実行用の選択/登録, 3.1.3

検証, 1.3.3

JDBCとの連係動作

接続コンテキストと接続, 7.6.1

イテレータと結果セット, 7.6.2

JDBCマッピング(属性が対象), 6.4.2 JDBCとSQLJ、サンプル・アプリケーション, 2.5 jdblinemapオプション(sqlj -jdblinemap), 8.2.4 JDeveloper

デバッグ, 10.2.4

SQLJの統合, 2.7.2

JDK

サポートされているバージョン, 1.1.3

JNDI

デフォルト・データ・ソースの名前, 7.1.8

データ・ソースの使用、接続, 7.1.8

JPublisher

builtintypesオプション, 6.4.2

caseオプション, 6.4.2

compatibleオプション, 6.4.2

カスタムJavaクラスの作成, 6.4

カスタムJavaクラスの例, 6.4.6

生成クラスの拡張, 6.4.7

カスタムJavaクラスの生成, 6.4.2

ラッパー・メソッドの生成, 6.4.2

メソッド・ラッパーの実装, 6.4.5

入力ファイル, 6.4.3

lobtypesオプション, 6.4.2

代替クラスへのマッピング, 6.4.2

numbertypesオプション, 6.4.2

プロパティ・ファイル, 6.4.3

メンバー名の指定, 6.4.4

型のマッピングの指定, 6.4.2

sqlオプション, 6.4.2

型の分類とマッピング・オプション, 6.4.2

型のマッピング, 6.4.2

型のマッピング・モードとオプション設定, 6.4.2

typesオプション, 6.4.2

userオプション, 6.4.2

JPublisherの出力内容, 6.4.1

K

KEEP_CONNECTION, 7.6.1

L

言語サポート(グローバリゼーション・サポート), 9.4.1

linemapオプション(sqlj -linemap), 8.2.4

行マッピング

SQLJソースからclassファイルへ, 8.2.4

SQLJソースからclassへ(jdb), 8.2.4

サーバーへのクラス/リソースのロード, 11.3.1 サーバーでのソースのロードと変換, 11.4.1 loadjava

互換オプション、SQLJ, 8.1.1

クラス/リソースのロード, 11.3.1

ソースのロード、変換, 11.4.1

ソースをロードしたときの出力, 11.4.3

LOB

イテレータ列, 5.3.2

ストアド・ファンクションの結果, 5.3.2

FETCH INTO LOBホスト変数, 5.3.2

SELECT INTO LOBホスト変数, 5.3.2

サポート(oracle.sqlとDBMS_LOB), 5.3.2

lobtypesオプション(JPublisher -lobtypes), 6.4.2 ロケール

コマンドラインの例, 9.4.2

メッセージ, 9.4.2

実行時の設定, 9.4.4

logオプション(AuditorInstaller), A.6.4.2

M

代替クラスへのマッピング(UDT), 6.4.2

メンバー名(オブジェクト), 6.4.4

メッセージ・パイプ、コンパイラ, 8.4.1

メタ・バインド式(動的SQL), 7.7.1

オブジェクトに対するメソッドのサポート, 6.2.2

メソッド・ラッパー(JPub)、実装, 6.4.5

中間層での考慮事項, 3.11

マルチスレッド

サーバー, 11.6.1

SQLJ、概要, 7.3

実行コンテキストとの関係, 7.2.5

サンプル・アプリケーション, 7.3

N

nオプション(sqlj -n)(非実行でエコー), 8.2.1

コンパイラの名前, 8.4.1

Java VMの名前, 8.4.1

名前付きイテレータ

アクセス, 4.5.4

宣言, 4.5.4

インスタンス化と移入, 4.5.4

スクロール可能, 7.4.5

使用, 4.5.4

ネーミング要件および制限

ファイル名, 3.10.4

ローカル変数、クラス(Javaのネームスペース), 3.10.1

SQLのネームスペース, 3.10.3

SQLJのネームスペース, 3.10.2

スキーマ・オブジェクトの名前付け

生成されたクラス, 11.4.3

ロードされたクラス, 11.3.2

ロードされたリソース, 11.3.2

ソース, 11.4.3

文字エンコーディング用のnative2ascii, 9.4.4 NCHARクラス(グローバリゼーション・サポート), 9.4.3 NcharAsciiStreamクラス(グローバリゼーション・サポート), 9.4.3 ncharconvトランスレータ・オプション, 8.1.1, 9.4.3 NcharUnicodeStreamクラス(グローバリゼーション・サポート), 9.4.3 NCLOBクラス(グローバリゼーション・サポート), 9.4.3 ネスト・イテレータ, 6.6.5 ネストした表

アクセス, 6.6.1

SQLJへの挿入, 6.6.2

操作, 6.6.4

ホスト式への取出し, 6.6.3

型, 6.1.3

ネスト・イテレータの使用, 6.6.5

non-repeatable reads, 7.5.3 Nstringクラス, 9.4.3 NStringクラス(グローバリゼーション・サポート), 9.4.3 NULLの処理

例, 3.3.2

NULL処理用のラッパー・クラス, 3.3.1

numbertypesオプション(JPublisher -numbertypes), 6.4.2

O

オブジェクトのメソッド・ラッパー(JPub), 6.4.5

オブジェクト参照

イテレータへの取出し, 6.5.1

SQLJ上の強い型指定, 6.5

SQLJでの更新, 6.5.4

弱い型指定の制限, 6.8.2

弱い型指定のサポート, 6.8.1

Object JDBCマッピング(属性が対象), 6.4.2 オブジェクト

カスタムJavaクラス, 6.2

オブジェクト型の作成, 6.3

データ型, 6.1.4

基本概念, 6.1.2

SQLJへの挿入, 6.5.3

代替クラスへのマッピング, 6.4.2

メソッドのサポート, 6.2.2

ORADataの指定, 6.2.1

オブジェクトのサポートの概要, 6.1.1

イテレータへの取出し, 6.5.1

シリアライズ(概要), 6.7

RAWおよびBLOB列のシリアライス, 6.7.1

カスタムJavaクラスによるシリアライズ, 6.7.2

型のマッピング指定, 6.4.2, 6.4.2

SQLDataの指定, 6.2.1

SQLJ上の強い型指定, 6.5

SQLJでの参照の更新, 6.5.4

SQLJでの更新, 6.5.2

弱い型指定の制限, 6.8.2

弱い型指定のサポート, 6.8.1

ラッパー・メソッド, 6.4.2

OCIドライバ(JDBC), 3.1.1 オフライン・チェック

デフォルトのチェッカ、Oracleチェッカ, 8.3.3

チェッカの指定, 8.3.3

offlineオプション(sqlj -offline), 8.3.3 オフライン解析

sqlj -parseオプション, 8.3.3

手順, 9.1.2

オンライン・チェックとの比較, 8.3.3

オンライン・チェック

結果のキャッシング, 8.3.3

デフォルトのチェッカ、Oracleチェッカ, 8.3.3

サーバーでの有効化, 11.4.2

有効化、ユーザー・スキーマの設定, 8.2.3

ドライバの登録, 8.2.3

デフォルトのURL接頭辞の設定, 8.2.3

パスワードの設定, 8.2.3

URLの設定, 8.2.3

チェッカの指定, 8.3.3

オフライン解析との比較, 8.3.3

onlineオプション(サーバー側), 11.4.2 onlineオプション(sqlj -online), 8.3.3 opaque型, 6.9 optcolsオプション(Oracleカスタマイザ), A.3.6.4 optcolsオプション(SQLJ -optcols), 8.2.6 オプティマイザ、SQL, 10.1, 10.1 オプション(トランスレータ)

コマンドラインのみ, 8.2.1

特殊処理のフラグ, 8.3.2

接続, 8.2.3

カスタマイズ, 8.4.2

javac互換, 8.1.1

loadjava互換, 8.1.1

出力ファイルとディレクトリ, 8.2.2

レポートと行マッピング, 8.2.4

セマンティクス・チェック、オフライン解析, 8.3.3

VMとコンパイラ, 8.4.1

ヘルプ, 8.2.1

優先順位, 8.1.5

概要, 8.1.1

オプションを渡す接頭辞, 8.3.1

サマリー・リスト, 8.1.1

代替環境のサポート, 8.4

カスタマイザ・ハーネスのオプション

接続オプション, A.3.3

一般オプション, A.3.2

特別なカスタマイザの起動, A.3.4

概要, A.3.1

Oracleカスタマイザのオプション, A.3.6 サーバー側変換のオプション

固定の設定, 11.4.2

オプションの設定, 11.4.2

サポートされているオプション, 11.4.2

optparamdefaultsオプション(Oracleカスタマイザ), A.3.6.6 optparamdefaultsオプション(SQLJ -optparamdefaults), 8.2.6 optparamsオプション(Oracleカスタマイザ), A.3.6.5 optparamsオプション(SQLJ -optparams), 8.2.6 Oracleクラス

close()メソッドのパラメータ, 3.2.4

connect()メソッド, 3.2.4

DefaultContextのインスタンス, 3.2.4

getConnection()メソッド, 3.2.4

Oracleカスタマイザ

CHAR比較での空白埋め, A.3.6.7

列の型/サイズの定義, A.3.6.4

パラメータ・サイズの定義, A.3.6.5

強制カスタマイズ, A.3.6.3

オプション, A.3.6

パラメータのデフォルト・サイズの設定, A.3.6.6

SQL変換の表示, A.3.6.8

文のキャッシュ・サイズ, A.3.6.9

使用しているOracle拡張機能の概要, A.3.6.10

バージョン互換性, A.3.6.2

Oracleの拡張

概要, 2.3

パフォーマンスの拡張, 10.1

使用している機能の概要, A.3.6.10

拡張型, 5.3

Oracleマッピング(属性が対象), 6.4.2 Oracleオプティマイザ, 10.1, 10.1 接続文字列のOracleシステム識別子(SID)、非推奨, 1.3.1 OracleCheckerデフォルトのチェッカ, 8.3.3 Oracle固有コード生成

メリットとデメリット, 3.7.4

コーディング上の考慮事項、制限事項, 3.7.1

概要, 3.7, 3.9

サーバー側の考慮事項, 3.7.3

トランスレータ/カスタマイザの使用方法の変更, 3.7.2

oracle.sqlパッケージ, 5.3.1 ORAData

その他の使用例, 6.2.6

指定, 6.2.1

カスタムJavaクラスでの使用, 6.2

CustomDatumとの比較, 6.2.1

サーバーでの出力デバイス、デフォルト, 11.2.3 出力ディレクトリ

生成される.classおよび.ser, 8.2.2

生成される.java, 8.2.2

出力ファイルとディレクトリのオプション(トランスレータ), 8.2.2 コンパイラの出力ファイル, 8.4.1 サーバー側トランスレータからの出力, 11.4.3 トランスレータからの出力, 2.4.2 出力パイプ、コンパイラ・メッセージ, 8.4.1 出力、サーバー側トランスレータのエラー, 11.4.4 SQLJの概要, 2.1

P

P接頭辞(sqlj -P-x), 8.3.1

パラメータの定義(サイズ)

概要, 10.1.5

Oracleカスタマイザoptparamdefaultsオプション, A.3.6.6

Oracleカスタマイザoptparamsオプション, A.3.6.5

SQLJ -optparamdefaultsオプション, 8.2.6

SQLJ -optparamsオプション, 8.2.6

parseオプション(sqlj -parse), 8.3.3 passesオプション(sqlj -passes), 8.4.1 passes、2段階で行うコンパイル, 8.4.1 他の実行可能プログラムに対するオプション設定, 8.3.1 passwordオプション(カスタマイザ・ハーネス), A.3.3.2 チェック用のpasswordオプション(sqlj), 8.2.3 path(WITH句)、非サポート, 4.1.5.1 PATHとCLASSPATH, 1.2.3 パフォーマンスの強化, 10.1 パフォーマンス・モニタリング、DMSサポート, 10.3 phantom reads, 7.5.3 パイプ、コンパイラによるメッセージの出力, 8.4.1 PL/SQL

実行文のブロック, 4.2.5

BOOLEAN型, 5.1.3

RECORD型, 5.1.3

TABLE型, 5.1.3

位置イテレータ

アクセス, 4.5.5

宣言, 4.5.5

インスタンス化と移入, 4.5.5

next()によるナビゲーション, 4.5.5

スクロール可能, 7.4.5

使用, 4.5.5

位置指定削除, 5.3.3 位置指定更新, 5.3.3 行プリフェッチ, 10.1.1 prefixオプション(AuditorInstaller), A.6.4.3 接頭辞

カスタマイザに対するオプション設定, 8.3.1

Javaコンパイラに対するオプション設定, 8.3.1

Java VMに対するオプション設定, 8.3.1

printオプション(カスタマイザ・ハーネス), A.3.4.2 プロシージャ・コール、ストアド, 4.7.1 プロファイルのカスタマイズ(「カスタマイズ」を参照), 9.1.5 profileオプション(sqlj -profile), 8.3.2 プロファイルキー, 3.8.5.2 プロファイルキー・クラス, 3.8.4, 9.1.3 プロファイル

デバッグに使用するオーディタ, A.6.1

バイナリ移植性, 3.8.3.2

コード・レイヤー, A.6.1

コード生成時の作成, A.1.1

debugオプション, A.3.4.1

実行時の機能, A.2.5

生成されるプロファイル, 9.1.3

プロファイルの詳細, A.1

概要, 3.8.3

printオプション, A.3.4.2

プロファイル・エントリの例, A.1.2

jarファイルの使用, A.4

verifyオプション, A.3.4.3

プロパティ・ファイル(トランスレータ)

デフォルトのプロパティ・ファイル, 8.1.3

概要, 8.1.3

入力ファイルの設定, 8.2.1

構文, 8.1.3

プロパティ・ファイル、SQLJ DMS, 10.3.3 プロパティ、Java、getProperty(), 9.4.4 propsオプション(sqlj -props), 8.2.1 Publicクラス名/ソース名のチェック, 8.4.1

R

READ COMMITTEDトランザクション, 7.5.3

READ ONLYトランザクション, 7.5.2

READ UNCOMMITTEDトランザクション, 7.5.3

READ WRITEトランザクション, 7.5.2

RECORD型(PL/SQL), 5.1.3

サーバーでの再帰的SQLJコール, 11.6.2

REF CURSOR

REF CURSOR型, 5.3.4

例, 5.3.4

SQLJサポート, 5.3.4

JDBCドライバの登録

実行時, 3.1.3

変換, 8.2.3

列の型/サイズの定義, 10.1.4 パラメータ・サイズの登録, 10.1.5 REPEATABLE READトランザクション, 7.5.3 レポート・オプション(トランスレータ), 8.2.4 要件、環境, 1.1.2 リソース・スキーマ・オブジェクトの名前付け

ロード, 11.3.2

結果式

実行時評価, 4.3.5

概要, 4.3.4

結果セット・イテレータ(強い型指定)

概要, 4.5.1.1

結果セット・イテレータ(弱い型指定)

概要, 7.4.4

概要, 4.5.1.2

スクロール可能, 7.4.5

結果セット

ホスト変数, 4.5.6

イテレータ列, 4.5.7

ストアド・ファンクションの戻り値, 4.7.3

コミット/ロールバックの影響, 3.5.6

イテレータからの変換, 7.6.2

イテレータへの変換, 7.6.2

複数のコールで使用(サーバー側), 11.2.2

ResultSetIterator型, 7.4.4 returnability(カーソル状態、WITH句), 4.1.5.1, 4.1.5.3 ロールバック

イテレータおよび結果セットに対する影響, 3.5.6

手動, 3.5.5

セーブポイント, 3.5.7

行プリフェッチ, 10.1.1 ROWID

ストアド・ファンクションの結果, 5.3.3

FETCH INTO ROWIDホスト変数, 5.3.3

SELECT INTO ROWIDホスト変数, 5.3.3

サポート, 5.3.3

実行時

エラーの分類, 9.3.2

デバッグ出力(AuditorInstaller), A.6.3

機能, 9.3

プロファイルの機能, A.2.5

実行時に対し生成されたコール, 9.1.3

グローバリゼーション・サポート, 9.4

JDBCドライバの選択と登録, 3.1.3

概要, 2.2.2, 3.8.2

パッケージ, 9.3.1

接続の設定, 1.3.1

ランタイム処理の手順, 2.4.3

テスト, 1.3.4

S

サンプル・アプリケーション

JDBCとSQLJ, 2.5

複数の接続コンテキスト, 7.1.4

複数行問合せ(名前付きイテレータ), 3.6

マルチスレッド, 7.3

単一行問合せ(SELECT INTO), 3.6

サンプル・クラス

カスタムJavaクラス(BetterDate), 6.2.6

SerializableDatumクラス, 6.7.4

セーブポイント

ExecutionContextセーブポイント・メソッド, 7.2.4.5

ISO構文, 3.5.7

Oracle構文, 3.5.7

セーブポイント文, 3.5.7

スキーマ・オブジェクト

生成されたクラスの名前付け, 11.4.3

ロードされたクラスの名前付け, 11.3.2

ロードされたリソースの名前付け, 11.3.2

ソースの名前付け, 11.4.3

スクロール可能なイテレータ

宣言, 7.4.5

スクロール可能な名前付きイテレータ, 7.4.5

スクロール可能な位置イテレータ, 7.4.5

機密, 7.4.5

スクロール可能なインタフェース, 7.4.5

ScrollableResultSetIterator型, 7.4.5 SELECT INTO文

エラー状態, 4.4.4

例, 4.4.2, 4.4.3

構文, 4.4.1

セマンティクス・チェック

オンライン結果のキャッシング, 8.3.3

デフォルトのチェッカ、Oracleチェッカ, 8.3.3

サーバーでのオンラインの有効化, 11.4.2

オンラインの有効化、ユーザー・スキーマの設定, 8.2.3

SQLCheckerCustomizerの起動, A.5.1

プロファイル、カスタマイザ・ハーネス経由, A.3.4.3

オプション, 8.3.3

ドライバの登録, 8.2.3

デフォルトのURL接頭辞の設定, 8.2.3

パスワードの設定, 8.2.3

URLの設定, 8.2.3

オフライン・チェッカの指定, 8.3.3

オンライン・チェッカの指定, 8.3.3

SQLCheckerCustomizerオプション, A.5.2

手順, 9.1.2

SENSITIVE(カーソル状態), 4.1.5.1 sensitivity(カーソル状態、WITH句), 4.1.5.1 シリアライズ・プロファイル(.ser)

.classへの変換, 8.3.2

生成されるプロファイル, 9.1.3

ser2classオプション(sqlj -ser2class), 8.3.2 SERIALIZABLEトランザクション, 7.5.3 シリアライズされたオブジェクト

ホスト変数, 6.7.3

イテレータ列, 6.7.3

概要, 6.7

SerializableDatumクラス(サンプル), 6.7.4

カスタムJavaクラス, 6.7.2

RAWおよびBLOB列, 6.7.1

サーバー側内部ドライバ(JDBC), 3.1.1 サーバー側SQLJ

クラスのロード, 11.2.4

コーディングでの注意事項, 11.2

コンパイル, 11.2.4

データベース接続, 11.2.1

デフォルトの出力デバイス, 11.2.3

dropjava, 11.5

Javaスキーマ・オブジェクトの削除, 11.5

エラー出力, 11.4.4

固定の設定, 11.4.2

変換で生成される出力, 11.4.3

Javaマルチスレッド, 11.6.1

JDBCにおける違い, 11.2.2

サーバーへのクラス/リソースのロード, 11.3.1

サーバーへのソースのロード、変換, 11.4.1

生成されたクラス・スキーマ・オブジェクトの名前付け, 11.4.3

ロードされたクラス・スキーマ・オブジェクトの名前付け, 11.3.2

ロードされたリソース・スキーマ・オブジェクトの名前付け, 11.3.2

ソース・スキーマ・オブジェクトの名前付け, 11.4.3

オプション, 11.4.2

概要, 2.6.2

概要, 11.1

再帰的コール, 11.6.2

サーバーでのクライアント・プログラムの実行, 11.3.4

オプションの設定, 11.4.2

SQL名とJava名, 11.2.5

サーバーでの変換, 11.4

クライアント側での変換, 11.3

サーバーでのコード実行状況の確認, 11.6.3

サーバー側Thinドライバ(JDBC), 3.1.1 SET(代入)文, 4.6 SET TRANSACTION構文, 7.5.1 setFormOfUseメソッド, 9.4.3 SQLJの設定、テスト, 1.3 ショート・ネーム(スキーマ名), 11.3.2 showReturnsオプション(AuditorInstaller), A.6.4.4 showSQLオプション(Oracleカスタマイザ), A.3.6.8 showThreadsオプション(AuditorInstaller), A.6.4.5 接続文字列のSID、現在使用されていない, 1.3.1 型の解決を目的としたソース・チェック, 8.3.2 ソース・ファイルとの行マッピング

jdb, 8.2.4

概略, 8.2.4

ソース・ファイルのエンコーディングのオプション, 8.2.2 ソース名/Publicクラス名のチェック, 8.4.1 ソース・スキーマ・オブジェクトの名前付け, 11.4.3 サーバーでのSQL名とJava名, 11.2.5 SQLオプティマイザ, 10.1, 10.1 sqlオプション(JPublisher -sql), 6.4.2 SQL置換コード(動的SQL), 7.7.1 SQLの状態(エラー時), 3.4.2 SQLCheckerCustomizer

プロファイルのセマンティクス・チェック, A.5

起動, A.5.1

オプション, A.5.2

SQLData

指定, 6.2.1

カスタムJavaクラスでの使用, 6.2

SQLExceptionサブクラス、使用, 3.4.3 SQLJ とJDBC、サンプル・アプリケーション, 2.5 SQLJ_OPTIONS環境変数, 8.1.4 単純な接続でのSqljConnBean, 7.1.10 接続キャッシングのためのSqljConnCacheBean, 7.1.10 sqljutlパッケージ, 1.2.4 文キャッシング, 10.1.2 静的SQL、定義済, 2.1 ステータス・メッセージ

カスタマイズ, A.2.4

変換, 9.2.2

トランスレータ、有効化/無効化, 8.2.4

statusオプション(sqlj -status), 8.2.4 stmtcacheオプション(Oracleカスタマイザ), A.3.6.9 ストアド・ファンクション・コール, 4.7.2 ストアド・プロシージャ・コール, 4.7.1 ストリーム

ファンクションの戻り値, 5.2.8

出力パラメータ, 5.2.8

クラスとメソッド, 5.2.6

例, 5.2.7

SQLJでの一般的な使用方法, 5.2.1

注意, 5.2.4

データの取出し, 5.2.5

データベースへのデータの送信, 5.2.3

サポート用クラス, 5.2

強い型指定, 6.6 強い型指定のカスタムJavaクラス, 6.1.1 強い型指定のオブジェクトおよび参照, 6.5 イテレータ・クラスのサブクラス化, 7.4.3 summaryオプション(Oracleカスタマイザ), A.3.6.10 Sun JDK

サポートされているバージョン, 1.1.3

実行コンテキストの同期, 7.2.3 構文

トランスレータのコマンドライン, 8.1.2

トランスレータのプロパティ・ファイル, 8.1.3

接続文字列のシステム識別子(SID)、現在使用されていない, 1.3.1

T

TABLE構文(ネストした表), 6.6.1, 6.6.4

TABLE型(PL/SQL), 5.1.3

Thinドライバ(JDBC), 3.1.1

トランザクション

アクセス・モードの設定, 7.5.2

詳細なトランザクション制御, 7.5

自動コミットと手動コミット, 3.5.2

基本的なトランザクション制御, 3.5

分離レベルの設定, 7.5.3

JDBC接続メソッド, 7.5.4

手動コミットおよびロールバック, 3.5.5

自動コミットの変更, 3.5.4

概要, 3.5.1

ロールバックのためのセーブポイント, 3.5.7

自動コミットの指定, 3.5.3

transformGroup(WITH句)、非サポート, 4.1.5.1 TRANSLATE(オブジェクト・メンバー名), 6.4.4 サーバーでの実行のためのサーバー側変換, 11.4 サーバーでの実行のためのクライアント側変換, 11.3 トランスレータ

基本的な変換処理, 2.4.1

コード生成, 9.1.3

コンパイル, 9.1.4

カスタマイズ, 9.1.5

エラー、警告、情報メッセージ, 9.2.1

終了コード, 9.2.3

グローバリゼーション・サポート, 9.4

入出力, 2.4.2

内部操作, 9.1

JavaとSQLJのコード解析、構文チェック, 9.1.1

出力、サーバー側, 11.4.3

概要, 2.2.1, 3.8.2

SQLのセマンティクス・チェックとオフライン解析, 9.1.2

ステータス・メッセージ, 9.2.2

代替環境のサポート, 8.4

テスト, 1.3.4

拡張型, 5.3 型のマッピング

BigDecimalマッピング, 6.4.2

JDBCマッピング, 6.4.2

JPublisherマッピング・オプション, 6.4.2

Object JDBCマッピング, 6.4.2

Oracleマッピング, 6.4.2

型の分類とマッピング・モード, 6.4.2

型解決、拡張検索, 8.3.2 typeMap(WITH句), 4.1.5.1 typesオプション(JPublisher -types), 6.4.2 サポートされている型

JDBC 2.0, 5.1.2

型の概要, 5.1.1

U

uninstallオプション(AuditorInstaller), A.6.4.6

バッチ更新機能

バッチ制限, 10.1.3

バッチ可能で互換性のある文, 10.1.3

非互換の文に対するバッチ処理, 10.1.3

バッチの取消し, 10.1.3

注意, 10.1.3

有効化と無効化, 10.1.3

実行中のエラー状態, 10.1.3

明示的および暗黙的なバッチ実行, 10.1.3

概要, 10.1.3

更新カウント, 10.1.3

暗黙的な実行コンテキストの使用, 10.1.3

再帰的コールイン, 10.1.3

updateColumns/ForUpdate(WITH句)、非サポート, 4.1.5.1 urlオプション(カスタマイザ・ハーネス), A.3.3.3 チェック用のurlオプション(sqlj -url), 8.2.3 URL、データベース

オンライン・チェック用のデフォルトの接頭辞, 8.2.3

非推奨のSID, 1.3.1

データベース・サービス名の使用, 1.3.1

userオプション(カスタマイザ・ハーネス), A.3.3.1 userオプション(JPublisher -user), 6.4.2 チェック用のuserオプション(sqlj -user), 8.2.3 ユーザー定義型, 6.3

V

ストアド・ファンクション用のVALUES構文, 4.7.2

VARRAY

行の挿入, 6.6.7

ホスト式への取出し, 6.6.6

VARRAY型, 6.1.3

verboseオプション(カスタマイザ・ハーネス), A.3.2.6 verifyオプション(カスタマイザ・ハーネス), A.3.4.3 バージョン互換性(Oracleカスタマイザ), A.3.6.2 バージョン番号オプション(sqlj -version-xxxx), 8.2.1 VM

CLASSPATHオプション, 8.2.1

SQLJを介したオプション, 8.3.1

名前の指定, 8.4.1

vmオプション(sqlj -vm), 8.4.1

W

warnオプション(SQLCheckerCustomizer), A.5.2.2

warnオプション(sqlj -warn), 8.2.4

警告メッセージ、トランスレータ, 9.2.1

警告、トランスレータ、有効化/無効化, 8.2.4

弱い型指定のオブジェクト/コレクション型

制限, 6.8.2

サポート, 6.8.1

弱い型指定のカスタムJavaクラス, 6.1.1 弱い型指定のイテレータ, 7.4.4 WHERE CURRENT OF, 5.3.3 WHERE CURRENT OF句, 5.3.3 Windows、SQLJの開発, 2.7.3 WITH句構文, 4.1.5 NULL処理用のラッパー・クラス, 3.3.1 ラッパー・メソッド(JPub)、生成, 6.4.2

オラクル社の法律上の注意点について

コピーライトについて

Copyright © 1994-2013, Oracle and/or its affiliates.All rights reserved.

商標と登録商標について

OracleおよびJavaはOracle Corporationおよびその関連企業の登録商標です。その他の名称は、それぞれの所有者の商標または登録商標です。

Intel、Intel Xeonは、Intel Corporationの商標または登録商標です。すべてのSPARCの商標はライセンスをもとに使用し、SPARC International, Inc.の商標または登録商標です。AMD、Opteron、AMDロゴ、AMD Opteronロゴは、Advanced Micro Devices, Inc.の商標または登録商標です。UNIXは、The Open Groupの登録商標です。

ライセンス制約の保証と結果的に生じる損害の免責

このソフトウェアおよび関連ドキュメントの使用と開示は、ライセンス契約の制約条件に従うものとし、知的財産に関する法律により保護されています。ライセンス契約で明示的に許諾されている場合もしくは法律によって認められている場合を除き、形式、手段に関係なく、いかなる部分も使用、複写、複製、翻訳、放送、修正、ライセンス供与、送信、配布、発表、実行、公開または表示することはできません。このソフトウェアのリバース・エンジニアリング、逆アセンブル、逆コンパイルは互換性のために法律によって規定されている場合を除き、禁止されています。

保証免責

ここに記載された情報は予告なしに変更される場合があります。また、誤りが無いことの保証はいたしかねます。誤りを見つけた場合は、オラクル社までご連絡ください。

制限付権利

このソフトウェアまたは関連ドキュメントを、米国政府機関もしくは米国政府機関に代わってこのソフトウェアまたは関連ドキュメントをライセンスされた者に提供する場合は、次の通知が適用されます。

U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, delivered to U.S. Government end users are "commercial computer software" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations.As such, use, duplication, disclosure, modification, and adaptation of the programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, shall be subject to license terms and license restrictions applicable to the programs.No other rights are granted to the U.S. Government.

危険な用途への使用について

このソフトウェアもしくはハードウェアは様々な情報管理アプリケーションでの一般的な使用のために開発されたものです。このソフトウェアもしくはハードウェアは、危険が伴うアプリケーション（人的傷害を発生させる可能性があるアプリケーションを含む）への用途を目的として開発されていません。このソフトウェアもしくはハードウェアを危険が伴うアプリケーションで使用する際、安全に使用するために、適切な安全装置、バックアップ、冗長性（redundancy）、その他の対策を講じることは使用者の責任となります。このソフトウェアもしくはハードウェアを危険が伴うアプリケーションで使用したことに起因して損害が発生しても、オラクル社およびその関連会社は一切の責任を負いかねます。

第三者のコンテンツ、製品、サービスに対する免責事項

このソフトウェアまたはハードウェア、そしてドキュメントは、第三者のコンテンツ、製品、サービスへのアクセス、あるいはそれらに関する情報を提供することがあります。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスに関して一切の責任を負わず、いかなる保証もいたしません。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスへのアクセスまたは使用によって損失、費用、あるいは損害が発生しても一切の責任を負いかねます。

ドラフトのアルファ版およびベータ版ドキュメントについて

このドキュメントが試作版の場合:

このドキュメントは試作版であり、デモおよび暫定使用のみを目的としたものです。このソフトウェアを使用するハードウェアに限定するものではありません。オラクル社およびその関連会社は、このドキュメントに関して一切の責任を負わず、いかなる保証もいたしません。また、このドキュメントを使用したことによって損失、費用、あるいは損害が発生しても、一切の責任を負いかねます。