4.7 OracleオブジェクトにアクセスするJavaツール

Oracleでは、Oracleオブジェクト機能をJavaと統合する様々な方法を提供しています。

これらのインタフェースにより、JavaからSQLデータにアクセスできるようになるのみでなく、Javaオブジェクトの永続データベース記憶域が得られます。

内容は次のとおりです。

4.7.1 Oracleオブジェクト・データへのJDBCアクセス

JDBCは、Oracleサーバーに接続するためのJavaインタフェースの集合です。

Oracleでは、オブジェクトとJDBCの間の緊密な統合が提供されます。SQL型はJavaクラスにマップでき、このマップ方法について、かなりの柔軟性が提供されています。

Oracle JDBC:

  • 動的SQLを使用して、Javaプログラム内でオブジェクト型およびコレクション型(データベースで定義)にアクセスできます。

  • デフォルトまたはカスタマイズ可能なマッピングを使用して、データベースで定義されたデータ型をJavaクラスに変換します。

JDBC 2.0では、ユーザー定義型(オブジェクト型)などのオブジェクト・リレーショナル構造がサポートされています。JDBCは、Oracleオブジェクトを特定のJavaクラスのインスタンスとして具体化します。JDBCを使用してOracleオブジェクトにアクセスするには、OracleオブジェクトについてJavaクラスを作成し、これらのクラスを移入する必要があります。次のいずれかを実行できます。

  • JDBCにオブジェクトをSTRUCTとして具体化させます。この場合、JDBCは属性のクラスを作成し、作成したクラスを移入します。

  • OracleオブジェクトとJavaクラスの間のマッピングを手動で指定します。つまり、Javaクラスをオブジェクト・データ用にカスタマイズします。この後、ドライバはカスタマイズされた指定のJavaクラスを移入し、これがJavaクラスに対する一連の制約となります。これらの制約を満たすために、SQLDataインタフェースまたはORADataインタフェースのどちらにあわせてクラスを定義するかを選択できます。

    関連項目:

    JDBCの詳細は、『Oracle Database JDBC開発者ガイド』を参照してください。

4.7.2 データ・マッピング方法

Oracle SQLJでは、イテレータまたはホスト式で使用するオブジェクト型、参照型(REF)およびコレクション型(VARRAYおよびネストした表)の強力な型指定または緩い型指定のJava表現がサポートされます。

強い型指定の表現では、特定のオブジェクト型、REF型またはコレクション型に対応するカスタムJavaクラスを使用し、インタフェースoracle.sql.ORADataを実装する必要があります。Oracle JPublisherユーティリティでは、そのようなカスタムJavaクラスを自動的に生成します。

緩い型指定の表現では、クラスoracle.sql.STRUCT(オブジェクト用)、oracle.sql.REF(参照用)またはoracle.sql.ARRAY(コレクション用)を使用します。

4.7.3 JPublisher

Oracle JPublisherはユーティリティで、次のユーザー定義データベース・エンティティをユーザーのJavaプログラムで表すJavaクラスを生成します。

  • データベース・オブジェクト・タイプ

  • データベース参照(REF)型

  • データベース・コレクション型(VARRAYまたはネストした表)

  • PL/SQLパッケージ

JPublisherにより、強力な型指定パラダイムで、データベース・オブジェクト型、参照型およびコレクション型(VARRAYまたはネストした表)をJavaクラスに対してマップする操作を指定し、カスタマイズできます。

4.7.3.1 JDBCおよびSQLJプログラム用Javaクラスの作成に使用されるJPublisher

Oracleでは、オブジェクト型、参照型およびコレクション型をJavaクラスにマップすることで、強力な型指定によるすべての利点を得ることができます。次の操作を実行できます。

  • Oracle JPublisherを使用してカスタムJavaクラスを自動的に生成し、それらのクラスを変更なしで使用します。

  • JPublisherによって生成されたクラスをサブクラス化し、独自の専用Javaクラスを作成します。

  • 『Oracle Database JPublisherユーザーズ・ガイド』に記述されている要件をクラスが満たす場合は、JPublisherを使用せず、カスタムJavaクラスを手動でコーディングします。

生成されたクラスが十分な機能を果さない場合は、JPublisherおよびサブクラスを使用することをお薦めします。

4.7.3.2 ユーザー定義のオブジェクト型に対してJPublisherで生成される内容

オブジェクト型に対してJPublisherを実行する場合、次のものが自動的に作成されます。

  • ユーザーのOracleオブジェクト型に対応する型定義として動作するカスタム・オブジェクト・クラス

    このクラスには、各属性に対する取得メソッドおよび設定メソッドが含まれます。メソッド名は、属性xxxの場合は、getXxx()およびsetXxx()の形式をとります。

    また、オプションで、サーバーで実行されるOracleオブジェクト・メソッドを起動するラッパー・メソッドをクラスに作成するように指定できます。

  • Oracleオブジェクト型へのオブジェクト参照にアクセスするためのカスタム参照クラス。

    このクラスには、ユーザーのカスタム・オブジェクト・クラスのインスタンスを戻すgetValue()メソッドおよびデータベースのオブジェクト値を更新するsetValue()メソッドが含まれます。これらのメソッドは、入力としてカスタム・オブジェクト・クラスのインスタンスをとります。

コレクション型に対してJPublisherを実行する場合、次のものが自動的に作成されます。

  • カスタム・コレクション・クラス。指定したOracleコレクション型に対応する型定義として機能します。

    このカスタム・コレクション・クラスのオーバーロード・メソッドgetArray()およびsetArray()は、コレクション単位で取得や更新を行うメソッドであり、getElement()メソッドおよびsetElement()メソッドは、コレクションの要素単位で取得や更新を行うメソッドです。このクラスには、これ以外のユーティリティ・メソッドもあります。

これらのどのカテゴリでも、JPublisherが生成するカスタムJavaクラスでは、ORADataインタフェースおよびgetFactory()メソッドが実装されます。

4.7.4 Javaオブジェクトの記憶域

JPublisherを使用すると、既存のSQL型にマップするJavaクラスを作成できます。このようにJavaクラスを作成した後、JDBCによりJavaアプリケーションからSQL型にアクセスできるようになります。

この逆を実行することもできます。つまり、既存のJavaクラスにマップするSQL型を作成できます。これにより、Javaオブジェクト用の永続ストレージが用意できます。これらのSQL型を、Java言語のSQL型またはSQLJオブジェクト型といいます。これらは、オブジェクト、属性、列、またはオブジェクト表の行の型として使用できます。オブジェクト参照または外部キーを介して、これらのタイプのオブジェクト(Javaオブジェクト)に対して、ナビゲーショナル・アクセスを行ったり、SQLからこれらのオブジェクトの問合せや操作ができます。

他のユーザー定義型と同様に、SQLJ型もCREATE TYPE文を使用して作成します。SQLJ型の場合、次の2つの特別な要素がCREATE TYPE文に追加されます。

  • それぞれのSQLJ属性とメソッドに対応するJavaの属性とメソッド、およびSQLJ型そのものに対応するJavaクラスの識別に使用するEXTERNAL NAME句。

  • サーバーに対してSQLJ型をどのように表現するかを指定するためのUSING句。USING句は、SQLJ型およびストレージの種類を取得するために使用するインタフェースを指定します。

次に例を示します。

例4-2 SQL型からJavaクラスへのマッピング

-- Mapping SQL Types to Java Classes example, not sample schema
CREATE TYPE full_address AS OBJECT (a NUMBER);
/

CREATE OR REPLACE TYPE person_t AS OBJECT
  EXTERNAL NAME 'Person' LANGUAGE JAVA
  USING SQLData (
    ss_no NUMBER (9) EXTERNAL NAME 'socialSecurityNo',
    name varchar(100) EXTERNAL NAME 'name',
    address full_address EXTERNAL NAME 'addrs',
    birth_date date EXTERNAL NAME 'birthDate',
    MEMBER FUNCTION age  RETURN NUMBER EXTERNAL NAME 'age () return int',
    MEMBER FUNCTION addressf RETURN full_address
      EXTERNAL NAME 'get_address () return long_address',
    STATIC function createf RETURN person_t EXTERNAL NAME 'create () 
         return Person',
    STATIC function createf (name VARCHAR2, addrs full_address, bDate DATE)
      RETURN person_t EXTERNAL NAME 'create (java.lang.String, Long_address,
      oracle.sql.date) return Person',
    ORDER member FUNCTION compare (in_person person_t) RETURN NUMBER
      EXTERNAL NAME 'isSame (Person) return int')
/

SQLJ型は、対応するJavaクラスを型の本体として使用します。ただし、SQLでは、通常のオブジェクト型のように、型のメソッドの実装を格納する目的で型の本体は指定しません。

4.7.4.1 SQLJオブジェクト型の作成

SQLJオブジェクト型は、SQL文を使用して作成できます。

SQLJ型を作成し、Javaへのマッピングを指定するSQL文は、デプロイメント・ディスクリプタと呼ばれるファイルの中に収められます。関連するSQL制約および権限も、このファイルに指定されます。型は、ファイルが実行されるときに作成されます。

次に、JavaタイプおよびJavaクラスのSQLバージョンを作成するプロセスの概要を示します。

  1. Javaタイプを設計します。
  2. Javaクラスを作成します。
  3. SQLJオブジェクト型の文を作成します。
  4. JARファイルを作成します。これは、必要なクラスがすべて入っている1つのファイルです。
  5. loadjavaユーティリティを使用して、JARファイルに定義されているJavaクラスをインストールします。
  6. 文を実行して、SQLJオブジェクト型を作成します。

4.7.4.2 マッピングに関するその他の注意

JavaクラスをSQL型にマップする際、次の点を考慮してください。

  • SQLJ静的ファンクションは、Javaクラスのユーザー定義コンストラクタにマップできます。このファンクションの戻り値は、ファンクションをローカルに定義したユーザー定義型をとります。

  • Javaの静的変数は、EXTERNAL NAMEで識別される対応する静的変数の値を戻すSQLJ静的メソッドにマップします。属性用のEXTERNAL NAME句は、SQLDataまたはORAData表現では任意で使用します。

  • SQL表現のSQLJ型のどの属性も、Javaフィールドにマップする必要があります。ただし、必ずしもすべてのJavaフィールドを、対応するSQLJ属性にマップする必要はありません。マッピングではJavaフィールドが省略できます。

  • クラスは省略できます。SQLJ型をルート・クラスにマップせず、またスーパークラスを介在させずに、SQLJ型をJavaクラス階層内の非ルート・クラスにマップできます。こうすることで、スーパークラスから継承した属性およびメソッドを含んだまま、スーパークラスを非表示にできます。

    ただし、クラス階層内のノード間の構造対応関係およびSQLJ型階層に存在するノード間の構造対応関係はそのまま保つ必要があります。つまり、継承により関連付け、2つのSQL型であるs_Aおよびs_Bにマップする2つのJavaクラスj_Aおよびj_Bの場合、j_Aからj_Bへの継承パスのそれぞれのノードについて、s_Aからs_Bへの継承パスに対応するノードが1つ存在する必要があります。

  • 前述の制限に違反しないかぎり、Javaクラスを複数のSQLJ型にマップできます。つまり、同一のJavaクラスにマップされた2つのSQLJ型は、共通するスーパータイプの祖先クラスを持てないということです。

  • すべてのJavaクラスをSQLJ型にマップしなければ、SQLJオブジェクト型の属性を、マップされていないJavaクラスのオブジェクトに設定することが可能です。特に、継承階層において属性がマップされたクラスの上位または下位で発生するクラスの場合、これに該当します。オブジェクトのクラスが、属性の型/クラスのスーパークラスの場合は、エラーとなります。オブジェクトのクラスが、属性の型/クラスのサブクラスであれば、SQLマッピングが存在するオブジェクトの階層の最も狭い意味での型に、オブジェクトがマップされます。

4.7.4.3 SQLJ型の進化

SQLJ型は、ALTER TYPE文を使用して進化させることができます。

ALTER TYPE文を使用すると、属性またはメソッドの追加、削除などを行うことにより、型を進化させられます。

SQLJ型を進化させる場合は、クラスと型間のマッピングを確認するために、特別な検証を行います。クラスと進化させた型が一致した場合は、有効な型であると表示されます。一致しない場合は、検証待ちと表示されます。

検証待ちという表示は、無効という表示と同じではありません。検証待ちの型は、たとえばALTER TYPEおよびGRANT文を使用して、操作を継続できます。

SQL表現を持つ型が、検証待ちと表示されても、メソッド起動を必要としないDMLまたはSELECT文を使用して、この型の表にアクセスできます。

ただし、シリアル化可能な表現を持ち、検証待ちと表示された型の表に対しては、DMLやSELECT文は実行できません。シリアル化可能な型のデータに対しては、メソッド起動を介したナビゲーショナル・アクセスのみ許可されます。検証待ちの型の場合は、このタイプのアクセスはできません。ただし、検証に合格するまで型をさらに進化させることは可能です。

型進化を参照してください。

4.7.4.4 制約

SQL表現を持つSQLJ型の場合、通常のオブジェクト型の場合と同じ制約を定義できます。

制約を定義する対象は、型ではなく表で、列レベルで定義します。SQL表現を持つSQLJ型についてサポートされている制約は、次のとおりです。

  • 一意制約

  • 主キー

  • CHECK制約

  • 属性についてのNOT NULL制約

  • 参照制約

SQL表現を持つSQLJ型の場合は、列の代入性についてのIS OF type制約もサポートされます。「代入性の制約」を参照してください。

4.7.4.5 SQLJオブジェクトの問合せ

SQLJ型に対しては、通常のSQLオブジェクト型と同様に問合せを行うことができます。

  • 通常のオブジェクト型と同様にSQLJ型を問い合せます。

SELECT文でコールされたメソッドで、属性値を変更することは避けてください。

4.7.4.6 Javaオブジェクトの挿入

Javaオブジェクトは、表に挿入できます。

SQLJ型の列が入っている表に、行を挿入するには、この型のコンストラクタ・ファンクションをコールし、この型のJavaオブジェクトを作成する必要があります。

  • システムが生成する暗黙的なコンストラクタを使用するか、またはJavaクラスのユーザー定義コンストラクタにマップする静的ファンクションを定義します。

4.7.4.7 SQLJオブジェクトの更新

SQLJオブジェクトは、いくつかの方法で更新できます。

次のようにして、SQLJオブジェクトを更新できます。

  • UPDATE文を使用して、1つ以上の属性の値を変更

  • 属性を更新しSELFを戻す(つまり、変更を行った上でオブジェクトそのものを戻す)メソッドを起動。

raise()が、指定された分のみsalaryフィールド/属性を増加し、SELFを戻すメンバー・ファンクションである場合について考えてみます。次の文により、オブジェクト表employee_objtabに含まれているすべての従業員に1000分の増額が与えられます。

UPDATE employee_objtab SET c=c.raise(1000);

SQLJ型の列は、通常のオブジェクト型と同じ構文を使用して、NULLに設定するか、または別の列に設定できます。たとえば、次の文により、列cに列dが割り当てられます。

UPDATE employee_reltab SET c=d;

4.7.5 Javaでのユーザー定義コンストラクタの定義

Javaでユーザー定義コンストラクタを実装する場合、実装ルーチンとして提供される文字列は、静的ファンクションに対応する必要があります。ファンクションの戻り型には、SQL型にマップされるJava型を指定します。

Javaでユーザー定義コンストラクタを実装する場合、実装ルーチンとして提供される文字列は、静的ファンクションに対応する必要があります。ファンクションの戻り型には、SQL型にマップされるJava型を指定します。

例4-3に、Javaで実装されたユーザー定義コンストラクタを伴う型宣言の例を示します。

例4-3 Javaにおけるユーザー定義コンストラクタの定義

-- Defining a User-Defined Constructor in Java example, not sample schema
CREATE TYPE person1_typ AS OBJECT 
 EXTERNAL NAME 'pkg1.J_Person' LANGUAGE JAVA 
 USING SQLData( 
  name VARCHAR2(30), 
  age NUMBER,
  CONSTRUCTOR FUNCTION person1_typ(SELF IN OUT NOCOPY person1_typ, name VARCHAR2,
                                   age NUMBER) RETURN SELF AS RESULT
  AS LANGUAGE JAVA 
    NAME 'pkg1.J_Person.J_Person(java.lang.String, int) return J_Person')
/

4.7.6 JDeveloper

Oracle JDeveloperは、Oracle Application ServerおよびOracle Databaseと緊密に統合された複数層のJavaアプリケーションの作成を目的としたフル機能のクロスプラットフォームの統合開発環境です。

Oracle JDeveloperにより、Javaクライアント・アプリケーション、動的HTMLアプリケーション、Webおよびアプリケーション・サーバー・コンポーネント、JavaBeanコンポーネントおよび業界標準モデルに基づいたデータベース・ストアド・プロシージャの開発、デバッグおよびデプロイができます。

JDeveloperは、ADFおよびTopLinkの統合開発環境でもあります。

4.7.6.1 アプリケーション開発フレームワーク(ADF)

ADFは、スケーラブルなエンタープライズJava EEアプリケーションを作成するフレームワークです。開発者は、ADFを使用して、アプリケーション・データが他のスキーマ・オブジェクトとともにOracleオブジェクト表に保存されるアプリケーションを作成できます。

4.7.6.2 TopLink

TopLinkは、Javaオブジェクトをデータベースを含む様々な永続性テクノロジにマップするフレームワークで、Oracleオブジェクトを利用するアプリケーションを作成する機能を提供します。