37
Oracle Application Server TopLink 作業ユニット入門 オラクル・ホワイト・ペーパー 2003 8

Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

  • Upload
    others

  • View
    6

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の

作業ユニット入門

オラクル・ホワイト・ペーパー 2003 年 8 月

Page 2: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

2

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

Oracle Application Server TopLink の作業ユニット入

はじめに .............................................................................................................. 3 概要................................................................................................................. 3

このドキュメントを読む前に .......................................................................... 4 オブジェクト・モデルおよびデータ・モデルの例 ................................. 4

アーキテクチャ .................................................................................................. 6 ライフサイクル............................................................................................. 6

基本 API............................................................................................................... 7 作業ユニットの取得..................................................................................... 7 オブジェクトの作成..................................................................................... 7 オブジェクトの変更..................................................................................... 9 新しいターゲットと既存のソース・オブジェクトの関連付け ............. 9 新しいソースと既存のターゲット・オブジェクトの関連付け ........... 12 既存のソースと既存のターゲット・オブジェクトの関連付け ........... 13 オブジェクトの削除................................................................................... 14

拡張 API............................................................................................................. 16 作業ユニットのトラブルシューティング ............................................... 16 1 回の操作でオブジェクトの作成および登録 ........................................ 20 registerNewObject の使用方法.................................................................... 20 registerAllObjects の使用方法 .................................................................... 22 登録および存在確認の使用方法 ............................................................... 23 集計の操作................................................................................................... 24 作業クローンの登録解除........................................................................... 24 読取り専用クラスの宣言........................................................................... 24 一致クエリー............................................................................................... 26 commitAndResume の使用方法 .................................................................. 27 ネストされた作業ユニットの使用方法 ................................................... 28 カスタム SQL での作業ユニットの使用方法 ......................................... 28 JTA での作業ユニットの使用方法 ........................................................... 29 削除順序の制御........................................................................................... 32

結論 .................................................................................................................... 34 ベスト・プラクティス .................................................................................... 35 用語集 ................................................................................................................ 36

Page 3: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

3

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

Oracle Application Server TopLink の作業ユニット入

はじめに

Oracle Application Server TopLink(TopLink)は、永続データをリレーショナル・

データベースに格納する様々な Java 2 Enterprise Edition(J2EE)や Java アプリケ

ーションに適した、高度なオブジェクトとリレーショナル間の永続化アーキテク

チャです。

TopLink では、トランザクション・パターンを使用して永続データを変更します。

トランザクションとは、1 つの単位として成功または失敗となる一連の操作(追

加、削除、変更)のことです。いずれかの操作が失敗した場合、基盤となるリレ

ーショナル・データベースまたは共有キャッシュに格納されている永続オブジェ

クトまたは永続 Bean に変更は加えられません。

TopLink でのトランザクションは作業ユニットオブジェクトによって実装されま

す。作業ユニットを使用すると、直接または J2EE の外部トランザクション・コン

トローラ(JTA など)を介して、トランザクションでオブジェクト変更ができま

す。

概要

このホワイト・ペーパーでは、TopLink の作業ユニットを理解し効率的に使用す

るために不可欠な情報と例を説明します。

本書の内容

• 作業ユニットの主要コンポーネントおよびその使用方法(「アーキテク

チャ」の項を参照)

• 開発サイクル全体にわたる も一般的に使用される主要な API コール

(「基本 API」の項を参照)

• 使用頻度が低く、パフォーマンス向上および 適化サイクルで通常使用

される特殊な API コール(「拡張 API」の項を参照)

作業ユニットは、Java の永続オブジェクトへの変更に 適なソリューションとな

るだけではなく、TopLink の EJB エンティティ Beans の Container Managed

Persistence(CMP)を対象とした永続マネージャ・ソリューション内部でも使用し

ます。このドキュメントでは、作業ユニットおよび他に関連した TopLink API の

直接の使用方法に重点を置きます。CMP を使用して開発する TopLink ユーザにと

ってもこれらの情報は役に立つかもしれませんが、コード・サンプル自体は役に

は立たないでしょう。なぜなら TopLink とのやり取りが J2EE コンテナの統合によ

って適切にカプセル化されるためです。

Page 4: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

4

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

「ベスト・プラクティス」の項には、このホワイト・ペーパー全体に引用されてい

る推奨事項とヒントがまとめてあります。

このホワイト・ペーパーに使用されている用語の定義については「用語集」を参

照してください。

このドキュメントを読む前に

先に進む前に「オブジェクト・モデルおよびスキーマの例」に説明されているオ

ブジェクト・モデル例およびデータベース・スキーマ例についての理解を深めて

ください。これらの例は、このホワイト・ペーパーの様々なページに含まれてい

ます。

オブジェクト・モデルおよびデータ・モデルの例

このホワイト・ペーパーでの例は、次に説明するオブジェクト・モデルおよびデ

ータ・モデル(エンティティ-リレーションシップ)に基づいています。

オブジェクト・モデル

次の図にオブジェクト・モデルを示します。

このオブジェクト・モデルの例では、Pet は PetOwner(ターゲット)と VetVisit

(ターゲット)の両方に対してソースであることに注意してください。VetVisit に

は Pet への後方参照が含まれています。

Page 5: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

5

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

データ・モデル

次の図にデータ・モデルを示します。

Page 6: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

6

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

アーキテクチャ

作業ユニットは、オブジェクトのコピー、言い換えればクローンに対して変更を

行います。正常に実行されると、これらの変更をデータベースおよびセッション・

キャッシュに適用します。作業ユニットは完全な自己完結型です。作業ユニット

の操作は、セッション・キャッシュ、データベースおよび作業ユニットの他のト

ランザクションと切り離され、そのコンテキスト内で発生します。

ライフサイクル アプリケーションでは、通常作業ユニットを次のように使用します。

1. クライアント・アプリケーションは、クライアント・セッション・オブ

ジェクトから作業ユニットを取得します。

2. クライアント・アプリケーションは、必要な変更対象オブジェクトの取

得にクライアント・セッションへ問い合せて、その後、キャッシュされ

たこれらのオブジェクトを作業ユニットに登録します。

オブジェクトの登録ごとに、作業ユニットはセッション・キャッシュま

たはデータベースから取得されたオブジェクトへアクセスし、次の 2 つ

のクローンを作成します。

• バックアップ・クローン

• 作業クローン

各オブジェクトが登録されると、作業ユニットは作業クローンをクライ

アント・アプリケーションに戻します。

3. クライアント・アプリケーションは作業クローンを変更します。

4. クライアント・アプリケーション(または外部トランザクション・コン

トローラ)はトランザクションをコミットします。

コミット時、作業ユニットは作業クローンをバックアップ・クローンと比較し、

チェンジ・セットを計算します(つまり、 小限必要な変更を判断します)。同

一オブジェクトの同時変更によって不正確な変更が特定されないように、比較は

バックアップ・クローンで行われます。作業ユニットは、データベースへの新し

いオブジェクトまたは変更されたオブジェクトのコミットを試行します。

コミットが成功すると、作業ユニットは変更をサーバー・セッションのキャッシ

ュにマージします。コミットが失敗した場合、共有キャッシュ内のオブジェクト

は変更されません。

Page 7: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

7

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

基本 API

次の例では、開発サイクル全体を通じて も一般的な作業ユニットの主要な API

コールの使用方法を説明します。

• 作業ユニットの取得

• オブジェクトの作成

• オブジェクトの変更

• 新しいターゲットと既存のソース・オブジェクトの関連付け

• 新しいソースと既存のターゲット・オブジェクトの関連付け

• 既存のソースと既存のターゲット・オブジェクトの関連付け

• オブジェクトの削除

これらの例ではベスト・プラクティス( 適な実施方法)を示します。また、必

要に応じて、生成される SQL、一般的なエラー、推奨されるコーディング・スタ

イルを説明します。

作業ユニットの取得

ここでは、セッション・オブジェクトからの作業ユニットの取得方法を検討しま

す。

Server server = (Server) SessionManager.getManager() .getSession( sessionName, MyServerSession.class.getClassLoader() ); Session session = (Session) server.acquireClientSession(); UnitOfWork uow = session.acquireUnitOfWork();

作業ユニットは、任意のタイプのセッションから取得できます。各トランザクシ

ョンの前に新しいセッションを作成しログインの必要はありません。クライアン

ト(またはスレッド)へのアクセスごとにクライアント・セッションを取得し、

このセッションから必要な作業ユニットの取得をお薦めします。

作業ユニットは、Commit(または Release)メソッドのコールまで有効です。コミ

ット後、トランザクションが失敗してロールバックされると作業ユニットは無効

になります。

作業ユニットは「commitAndResume の使用方法」で説明されているように

commitAndResume メソッドのコール後も有効のままです。

Java Transaction API(JTA)および Java Transaction Service(JTS)で作業ユニット

を使用する場合「JTA での作業ユニットの使用方法」で説明されているように、

セッションの拡張 API である getActiveUnitOfWork メソッドも使用できます。

オブジェクトの作成

ここでは、作業ユニットの registerObject メソッドより返されたクローンを使用し

て(リレーションシップを持たない)単純なオブジェクトを作成し、永続化する

方法を検討します。

基本 API

基本 API

Page 8: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

8

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

UnitOfWork uow = session.acquireUnitOfWork(); Pet pet = new Pet(); Pet petClone = (Pet)uow.registerObject(pet); petClone.setId(100); petClone.setName("Fluffy"); petClone.setType("Cat"); uow.commit();

前述か、または次の方法を使用します。

UnitOfWork uow = session.acquireUnitOfWork(); Pet pet = new Pet(); pet.setId(100); pet.setName("Fluffy"); pet.setType("Cat"); uow.registerObject(pet); uow.commit();

いずれの方法でも次の SQL が作成されます。

INSERT INTO PET (ID, NAME, TYPE, PET_OWN_ID) VALUES (100, 'Fluffy', 'Cat', NULL)

初の例は、クローンの操作が身につき、将来のコード変更における対応もかな

り柔軟になるため、この方法をお薦めします。後述の例では、新しいオブジェク

トとクローンを組合わせて使用することが混乱と予期せぬ結果につながり得るこ

とを示します。

一般的なエラー

• 作業ユニットでオブジェクトの登録を忘れる。

症状: データベースへのオブジェクトの書込みが行われません。

• クローンではなく、元のオブジェクトを誤って変更する。

症状: フィールドが正しくデータベースに書き込まれず、共有キャッシュ

の状態にあるオブジェクトが破壊されます(データベースと同期しませ

ん)。

• 作業ユニットのコミット後にクローンを使用する。

症状: 様々な症状が発生します。作業ユニットのコミット後に、インスタ

ンス化されていないクローンの値へアクセスすると例外が発生します。

クローンは、トランザクション中に使用する作業コピーです。したがっ

て、トランザクション終了後は使用しないでください。

コーディング・スタイル

• クローンを指す変数に"clone"または“WorkingCopy”を接尾辞として名前

を付けます。

• 作業ユニットに"UOW"を接尾辞として名前を付けます。

• 作業ユニット内のコードをインデントします(制御構造のコードのよう

に扱います)。

• クローンの発生元である作業ユニットのコミット後は、クローンを使用

しないように注意してください。

Page 9: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

9

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

オブジェクトの変更

ここでは、既存オブジェクトの単純なフィールドへのダイレクト・マッピング属

性の変更方法を検討します。

作業ユニットの読込み前に Pet を読み込みます。変数 pet は Pet のキャッシュ・コ

ピーです。作業ユニットの内部で、作業コピーを取得するためにキャッシュ・コ

ピーの登録が必要となります。その後、作業コピーを変更して作業ユニットをコ

ミットします。

// Read in any pet. Pet pet = (Pet)session.readObject(Pet.class); UnitOfWork uow = session.acquireUnitOfWork(); Pet petClone = (Pet) uow.registerObject(pet); petClone.setName("Furry"); uow.commit();

この例では、作業ユニットを介して問い合せてクローンを取得することで、登録

作業を省く機能を利用しています。ただし、キャッシュ・コピーへのハンドルが

取得できないという欠点があります。コミット後、更新済みの Pet を使用した操

作には、セッションに問合せて再取得することが必要となります(作業ユニット

のコミット後は、そのクローンが無効になるため使用できないことに注意してく

ださい)。

UnitOfWork uow = session.acquireUnitOfWork(); Pet petClone = (Pet) uow.readObject(Pet.class); petClone.setName("Furry"); uow.commit();

いずれの方法でも次の SQL が作成されます。

UPDATE PET SET NAME = 'Furry' WHERE (ID = 100)

一般的なエラー

• 作業コピーではなく元のオブジェクトを操作してしまう。変更を永続的

にするには、クローンにのみ変更が必要です。

コーディング・スタイル

• 作業ユニットを介した問合せには注意が必要です。問合せで読み込まれ

るすべてのオブジェクトは、作業ユニットに登録されるため、変更があ

るかコミット時に確認されます。 適なパフォーマンスのためには、作

業ユニットを介した ReadAllQuery の方法ではなく、セッションを介した

ReadAllQuery を実行し、変更が必要なオブジェクトのみを作業ユニット

に登録するアプリケーションの設計をお薦めします。

新しいターゲットと既存のソース・オブジェクトの関連付け

ここでは、1 対多および 1 対 1 のリレーションシップで新しいターゲット・オブ

ジェクトを既存のソース・オブジェクトに関連付ける方法を検討します。

新しいオブジェクトを既存のオブジェクトに関連付ける方法は 2 つあります。

• キャッシュ・オブジェクトへの参照を使用しない関連付け

基本 API

基本 API

Page 10: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

10

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

• キャッシュ・オブジェクトへの参照を使用する関連付け

Page 11: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

11

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

どちらの方法を使用するかは、コードが作業ユニットのコミット後に新しいオブ

ジェクトのキャッシュ・コピーを参照する必要があるか、およびコードが変更に

適応できる程度により決まります。

キャッシュ・オブジェクトへの参照を使用しない関連付け

新しいターゲットを既存のソースに関連付ける 初の方法は、Java の場合とまっ

たく同じで次のように作成します。

UnitOfWork uow = session.acquireUnitOfWork(); Pet petClone = (Pet)uow.readObject(Pet.class); PetOwner petOwner = new PetOwner(); petOwner.setId(400); petOwner.setName("Donald Smith"); petOwner.setPhoneNumber("555-1212"); VetVisit vetVisit = new VetVisit(); vetVisit.setId(500); vetVisit.setNotes("Pet was shedding a lot."); vetVisit.setSymptoms("Pet in good health."); vetVisit.setPet(petClone); petClone.setPetOwner(petOwner); petClone.getVetVisits().addElement(vetVisit); uow.commit();

これにより適切な SQL が実行されます。

INSERT INTO PETOWNER (ID, NAME, PHN_NBR) VALUES (400, 'Donald Smith', '555-1212') UPDATE PET SET PET_OWN_ID = 400 WHERE (ID = 100) INSERT INTO VETVISIT (ID, NOTES, SYMPTOMS, PET_ID) VALUES (500, 'Pet was shedding a lot.', 'Pet in good health.', 100)

新しいオブジェクトを既存のオブジェクトに関連付けると、作業ユニットは新し

いオブジェクトをクローンとして扱います。つまり、コミット後次の式が成立し

ます。

petOwner != session.readObject(petOwner)

詳細は「registerNewObject の使用方法」の項を参照してください。

したがって、作業ユニットのコミット後の変数 vetVisit および petOwner は、それ

ぞれのキャッシュ・オブジェクトではなく、作業コピーのクローンを示すことに

なります。

作業ユニットのコミット後にキャッシュ・オブジェクトが必要な場合は、このオ

ブジェクトについて問い合せるか、キャッシュ・オブジェクトへの参照の関連付

けを作成します(「キャッシュ・オブジェクトへの参照を使用する関連付け」の

項を参照)。

キャッシュ・オブジェクトへの参照を使用する関連付け

新しいターゲットを既存のソースに関連付けるもう 1 つの方法は、次のようにキ

ャッシュ・オブジェクトへの参照を使用します。

Page 12: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

12

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

UnitOfWork uow = session.acquireUnitOfWork(); Pet petClone = (Pet)uow.readObject(Pet.class); PetOwner petOwner = new PetOwner(); PetOwner petOwnerClone = (PetOwner)uow.registerObject(petOwner); petOwnerClone.setId(400); petOwnerClone.setName("Donald Smith"); petOwnerClone.setPhoneNumber("555-1212"); VetVisit vetVisit = new VetVisit(); VetVisit vetVisitClone = (VetVisit)uow.registerObject(vetVisit); vetVisitClone.setId(500); vetVisitClone.setNotes("Pet was shedding a lot."); vetVisitClone.setSymptoms("Pet in good health."); vetVisitClone.setPet(petClone); petClone.setPetOwner(petOwnerClone); petClone.getVetVisits().addElement(vetVisitClone); uow.commit();

これにより、作業ユニットのコミット後、次の式が成立します。

petOwner == session.readObject(petOwner)

つまり、コミット後に取得するのは、クローンではなくキャッシュ・コピーへの

ハンドルです。

一般的なエラー

• 既存のオブジェクトからの新しいオブジェクトの関連付けを忘れる。

症状: 新しいオブジェクトはデータベースに書き込まれません。

新しいソースと既存のターゲット・オブジェクトの関連付け

ここでは、1 対多および 1 対 1 のリレーションシップで、新しいソース・オブジ

ェクトを既存のターゲット・オブジェクトに関連付ける方法を検討します。

TopLink は、作業ユニットに登録されているすべてのオブジェクトのリレーショ

ンシップに従って、新たに追加されたオブジェクトと変更されたオブジェクトを

確認します。前述の項では、新しいターゲット・オブジェクトを既存のソースに

関連付ける際に、そのターゲットを登録するかどうかを選択できました。新しい

オブジェクトは、登録しなくとも、ソース・オブジェクトから到達可能です(ソ

ース・オブジェクトはクローンであるため登録されます)。ただし、新しいソー

ス・オブジェクトと既存のターゲット・オブジェクトの関連付けが必要な場合は、

新しいオブジェクトの登録が必要となります。新しいオブジェクトは、登録しな

いと、作業ユニット内で到達可能なオブジェクトにはなりません。また、TopLink

によるデータベースへの書込みも行われません。

新しい Pet を作成して既存する PetOwner に関連付ける例を考えます。次のコード

を使用します。

基本 API

Page 13: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

13

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

UnitOfWork uow = session.acquireUnitOfWork(); PetOwner existingPetOwnerClone = (PetOwner)uow.readObject(PetOwner.class); Pet newPet = new Pet(); Pet newPetClone = (Pet)uow.registerObject(newPet); newPetClone.setId(900); newPetClone.setType("Lizzard"); newPetClone.setName("Larry"); newPetClone.setPetOwner(existingPetOwnerClone); uow.commit();

これによって適切な SQL が生成されます。

INSERT INTO PET (ID, NAME, TYPE, PET_OWN_ID) VALUES (900, 'Larry', 'Lizzard', 400)

この場合、新しいオブジェクトを登録して作業コピーの操作が必要となります。

新しいオブジェクトを登録せずに PetOwner のクローンに関連付けると、データベ

ースへの書込みは行われません。PetOwner のクローンと Pet の新しいオブジェク

トとの関連付けが必要な場合は、拡張 API である registerNewObject

(「registerNewObject の使用方法」を参照)を使用します。

一般的なエラー

• 新しいオブジェクトの登録を忘れる。または、新しいオブジェクトは登

録したが、クローンではなく元のオブジェクトを操作してしまう。 症状: 新しいオブジェクトはデータベースに書き込まれません。

• クローンの登録を忘れ、既存のオブジェクトのキャッシュ・バージョン

を誤って新しいオブジェクトに関連付けてしまう。 症状: コミット時、親セッションからのオブジェクトのキャッシュ・バー

ジョンがこの作業ユニットからのクローンに関連付けられたことを示す

エラーが TopLink より生成されます。作業ユニットでは、作業コピーの

操作が必要です。

既存のソースと既存のターゲット・オブジェクトの関連付け

ここでは、1 対多および 1 対 1 のリレーションシップで、既存のソース・オブジ

ェクトを既存のターゲット・オブジェクトに関連付ける方法を検討します。

作業ユニット内において既存のオブジェクト同士の関連付けは、Java でのオブジ

ェクトの関連付け同様、非常に簡単です。ただし、オブジェクトの作業コピーの

みが操作対象となることに注意してください。

// Associate all VetVisits in the database to a Pet from the database UnitOfWork uow = session.acquireUnitOfWork(); Pet existingPetClone = (Pet)uow.readObject(Pet.class); Vector allVetVisitClones; allVetVisitClones = (Vector)uow.readAllObjects(VetVisit.class); Enumeration enum = allVetVisitClones.elements(); while(enum.hasMoreElements()) { VetVisit vetVisitClone =(VetVisit)enum.nextElement(); existingPetClone.getVetVisits().addElement(vetVisitClone); vetVisitClone.setPet(existingPetClone); }; uow.commit();

基本 API

Page 14: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

14

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

一般的なエラー

• 既存のオブジェクトの関連付けで も一般的なエラーは、作業コピーを

操作対象として忘れることです。

症状: コミット時にエラーが発生します。誤って、オブジェクトのキャッ

シュ・バージョンを作業コピーに関連付けると、コミット時に、親セッ

ションからのオブジェクト(キャッシュ・バージョン)がこの作業ユニ

ットからのクローンに関連付けられたことを示すエラーが表示されます。

オブジェクトの削除

ここでは、作業ユニットを使用したオブジェクトの削除方法を検討します。内容

を次に示します。

• privateOwnedRelationship の使用

• データベースからの明示的な削除

• オブジェクトの削除順序の理解

privateOwnedRelationship の使用

リレーショナル・データベースには、Java Virtual Machine(JVM)にあるようなガ

ベージ・コレクションがありません。Java でのオブジェクトの削除には、オブジ

ェクトの参照を解除します。リレーショナル・データベースの行の削除には明示

的な削除が必要です。リレーショナル・データベース内のデータを削除するタイ

ミングを管理する単調な作業のかわりに、マッピング属性

privateOwnedRelationship を使用することでリレーショナル・データベース内にお

けるガベージ・コレクションと同等の動作を TopLink に管理させます。

Java でマッピングを作成する場合、参照オブジェクトがプライベートに所有(私

有)されていること、つまり参照オブジェクトは親オブジェクトなしでは存在し

ないことを、Java の privateOwnedRelationship メソッドで TopLink に知らせること

ができます。Pet と PetOwner 間に依存関係を持たせる例を次に示します。

OneToOneMapping petOwnerMapping = new OneToOneMapping(); petOwnerMapping.setAttributeName("petOwner"); petOwnerMapping.setReferenceClass(com.top.uowprimer.model.PetOwner.class); petOwnerMapping.dontUseIndirection(); petOwnerMapping.privateOwnedRelationship(); petOwnerMapping.addForeignKeyFieldName("PET.PET_OWN_ID", "PETOWNER.ID"); descriptor.addMapping(petOwnerMapping);

Mapping Workbench でマッピングを作成する場合は「一般」タブの下にある「私

有」チェック・ボックスを選択します。

TopLink にあるリレーションシップが私有であると知らせる場合、TopLink に次の

2 つのことを指示することを意味します。

• 私有リレーションシップのソースが削除される場合は、ターゲットも削

除する。

• ターゲットへの参照をソースから解除する場合は、ターゲットを削除す

る。

基本 API

Page 15: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

15

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

共有される可能性があるオブジェクトには、私有リレーションシップを設定しな

いでください。私有リレーションシップのターゲットである場合、そのオブジェ

クトは複数のリレーションシップでターゲットになることはできません。

このルールに対する例外は、リレーション・オブジェクトがリレーション表にマ

ップされ、1 対多リレーションシップを通じてソースおよびターゲットの両方に

よって参照される多対多関係が存在する場合です。この場合、1 対多マッピング

を私有リレーションシップとして設定すると、ソースの削除の際にすべての関連

オブジェクトが削除されます。

オブジェクト・モデルおよびスキーマの使用例を次に示します。

// If the Pet-PetOwner relationship is privateOwned // then the PetOwner will be deleted at uow.commit() // otherwise, just the foreign key from PET to PETOWNER will // be set to null. The same is true for VetVisit. UnitOfWork uow = session.acquireUnitOfWork(); Pet petClone = (Pet)uow.readObject(Pet.class); petClone.setPetOwner(null); VetVisit vvClone = (VetVisit)petClone.getVetVisits().firstElement(); vvClone.setPet(null); petClone.getVetVisits().removeElement(vvClone); uow.commit();

Pet から PetOwner、および Pet から VetVisit の間のリレーションシップが私有でな

い場合、このコードによって次の SQL が生成されます。

UPDATE PET SET PET_OWN_ID = NULL WHERE (ID = 150) UPDATE VETVISIT SET PET_ID = NULL WHERE (ID = 350)

Pet から PetOwner、および Pet から VetVisit の間のリレーションシップが私有の場

合、このコードによって次の SQL が生成されます。

UPDATE PET SET PET_OWN_ID = NULL WHERE (ID = 150) UPDATE VETVISIT SET PET_ID = NULL WHERE (ID = 350) DELETE FROM VETVISIT WHERE (ID = 350) DELETE FROM PETOWNER WHERE (ID = 250)

データベースからの明示的な削除

私有リレーションシップによるガベージ・コレクションの対象にならないオブジ

ェクトの場合(特に、オブジェクト・モデル内のルート・オブジェクト)、deleteObject

API を使用してオブジェクトを表す行を明示的に削除するように TopLink に指示

することができます。次に例を示します。

UnitOfWork uow = session.acquireUnitOfWork(); pet petClone = (Pet)uow.readObject(Pet.class); uow.deleteObject(petClone); uow.commit();

前述のコードによって次の SQL が生成されます。

DELETE FROM PET WHERE (ID = 100)

Page 16: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

16

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

オブジェクトの削除順序の理解

作業ユニットは、変更または操作順序を追跡しません。作業ユニットは、データ

ベースで要求される順序でオブジェクトを変更する必要性から開発者を解放しま

す。

デフォルトでは、コミット時に、作業ユニットはスキーマで定義された制約を使

用して、すべての挿入および更新を順序付けます。すべての挿入および更新が行

われると、作業ユニットは必要な削除操作を実行します。

制約は、1 対 1 および 1 対多マッピングから判断されます。これらのマッピング

がない場合は、「削除順序の制御」で示されているように、制約に関する情報を

TopLink に追加できます。

拡張 API

次の例では、開発サイクルの後の段階で も一般的な作業ユニットの拡張 API コ

ールおよび手法を説明します。

• 作業ユニットのトラブルシューティング

• 1 回の操作でオブジェクトの作成および登録

• registerNewObject の使用方法

• registerAllObjects の使用方法

• 登録および存在チェックの使用方法

• 集計の操作

• 作業クローンの登録解除

• 読取り専用クラスの宣言

• 一致クエリー

• commitAndResume の使用方法

• ネストされた作業ユニットの使用方法

• カスタム SQL での作業ユニットの使用方法

• JTA での作業ユニットの使用方法

• 削除順序の制御

これらの例では、ベスト・プラクティス( 適な実施方法)を示します。また、

必要に応じて、生成される SQL、一般的なエラー、推奨されるコーディング・ス

タイルを説明します。

作業ユニットのトラブルシューティング

ここでは、作業ユニットの一般的な問題とデバッグ方法を検討します。

• コミット後はクローンを使用しない

• オブジェクトがキャッシュ・オブジェクトかどうかの判断

• 作業ユニットの内容のダンプ

• 例外の処理

拡張 API

Page 17: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

17

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

コミット後はクローンを使用しない

作業ユニットで起こりやすいエラーは、コミット後にクローンを解放せずそのま

ま使用することです。通常、クローンは static 変数に格納されるため、開発者はこ

のオブジェクトがキャッシュ・コピーだと思い込みます。このことにより、別の

作業ユニットによってこのオブジェクトに変更が加えられたときに、開発者はキ

ャッシュ・コピーが更新されないと誤って考えてしまいます(作業ユニットは、

古いクローンではなくキャッシュ・コピーのみを更新するためです)。

次の例でこのエラーを考えます。この例では、Pet のキャッシュ・コピーへのハン

ドルを取得して static な CACHE_PET に格納します。作業コピーへのハンドルを

取得して static な CLONE_PET に格納します。以降のある作業ユニットで Pet を変

更します。

作業ユニットからのクローンへのグローバル参照を誤って格納した開発者の多く

は、作業ユニットの中でキャッシュ・オブジェクトが変更されるときに、これら

のクローンが更新されたと考えています。しかし、更新されるのはキャッシュ・

コピーのみです。

//Read a Pet from the database, store in static CACHE_PET = (Pet)session.readObject(Pet.class); //Put a clone in a static. This is a bad idea and is a common error UnitOfWork uow = session.acquireUnitOfWork(); CLONE_PET = (Pet)uow.readObject(Pet.class); CLONE_PET.setName("Hairy"); uow.commit(); //Later, the pet is changed again UnitOfWork anotherUow = session.acquireUnitOfWork(); Pet petClone = (Pet)anotherUow.registerObject(CACHE_PET); petClone.setName("Fuzzy"); anotherUow.commit(); // If you incorrectly stored the clone in a static and thought it should be // updated when it's later changed, you would be wrong: only the cache copy is // updated; NOT OLD CLONES. System.out.println("CACHE_PET is" + CACHE_PET); System.out.println("CLONE_PET is" + CLONE_PET);

2 つの System.out コールによって、次の出力が生成されます。

CACHE_PET isPet type Cat named Fuzzy id:100 CLONE_PET isPet type Cat named Hairy id:100

オブジェクトがキャッシュ・オブジェクトかどうかの判断

「オブジェクトの変更」の項で、次のメソッドによりクラスの特定なインスタンス

の読込みができると説明しました。

session.readObject(Class);

Page 18: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

18

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

この他、オブジェクトを引数とする readObject メソッドもあります。このメソッ

ドの動作は、引き渡されたオブジェクトの主キーに対して実行する

ReadObjectQuery と同じです。次に例を示します。

session.readObject(pet);

は、次のコードと同じです。

ReadObjectQuery query = new ReadObjectQuery(); query.setReferenceClass(Pet.class); ExpressionBuilder builder = new ExpressionBuilder(); Expression exp = builder.get("id").equal(pet.getId()); query.setSelectionCriteria(exp); session.executeQuery(query);

主キーに基づく問合せの場合、デフォルトでは、データベースへアクセスせずに

キャッシュ内に格納されている内容が返されます。

これを前提とすると、次の例に示すように、オブジェクトのキャッシュ・コピー

に簡単かつ迅速にアクセス方法が使用できます。

//Here is a test to see if an object is the cache copy boolean cached = CACHE_PET == session.readObject(CACHE_PET); boolean cloned = CLONE_PET == session.readObject(CLONE_PET); System.out.println("Is CACHE_PET the Cache copy of the object: " + cached); System.out.println("Is CLONE_PET the Cache copy of the object: " + cloned);

このコードからは、次の出力が生成されます。

Is CACHE_PET the Cache copy of the object: true Is CLONE_PET the Cache copy of the object: false

作業ユニットの内容のダンプ

作業ユニットには、パフォーマンスを分析したり、コードの問題の特定に役立つ

デバッグ用のメソッドがいくつかあります。その中で も役立つのは、作業ユニ

ットの既知のオブジェクトに関するすべての情報を印刷する

printRegisteredObjects です。このメソッドは、登録されているオブジェクト数を調

べたり、操作対象のオブジェクトが登録されているかの確認に使用します。

このメソッドの使用には、作業ユニットの取得元となるセッションでログ・メッ

セージが有効である必要があります。デフォルトでは、セッションのログ・メッ

セージは無効です。ログ・メッセージを有効にするには、セッションの logMessages

メソッドを使用します。ログ・メッセージを無効にするには、セッションの

dontlogMessages メソッドを使用します(次の例を参照)。

次の例について考えます。

session.logMessages(); // enable log messages UnitOfWork uow = session.acquireUnitOfWork(); Pet petClone = (Pet)uow.readObject(Pet.class); petClone.setName("Mop Top"); Pet pet2 = new Pet(); pet2.setId(200); pet2.setName("Sparky"); pet2.setType("Dog"); uow.registerObject(pet2);

Page 19: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

19

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

uow.printRegisteredObjects(); uow.commit(); session.dontLogMessages(); // disable log messages

この例からは次の出力が生成されます。

UnitOfWork identity hashcode: 32373 Deleted Objects: All Registered Clones: Key: [100] Identity Hash Code:13901 Object: Pet type Cat named Mop Top id:100 Key: [200] Identity Hash Code:16010 Object: Pet type Dog named Sparky id:200 New Objects: Key: [200] Identity Hash Code:16010 Object: Pet type Dog named Sparky id:200

例外の処理

TopLink の例外は、RuntimeException のインスタンスです。つまり、これらのイン

スタンスをスローするメソッドを、try-catch 文中に記述する必要はありません。

ただし、作業ユニットをコミットするメソッドは発生の可能性がある問題に対処

させるため、try-catch 文の内部でコールすべきメソッドです。

次に作業ユニットの例外を処理する方法を示します。

UnitOfWork uow = session.acquireUnitOfWork(); Pet petClone = (Pet)uow.registerObject(newPet); petClone.setName("Assume this name is too long for a database constraint"); // Assume that the name argument violates a length constraint on the database. // This will cause a DatabaseException on commit. try { uow.commit(); } catch (TopLinkException tle) { System.out.println("There was an exception: " + tle); }

このコードからは次の出力が生成されます。

There was an exception: EXCEPTION [ORACLEAS TOPLINK-6004]: oracle.toplink.exceptions.DatabaseException

オプティミスティック・ロックの使用時は、発生する例外はオプティミスティッ

ク・ロックで問題が起こったことを示すため、コミット時の例外を捕捉すること

が必須です。オプティミスティック・ロックを使用すると、特定のオブジェクト

がトランザクションまたは作業ユニットで使用中でも、すべてのユーザーはその

オブジェクトへアクセスできます。作業ユニットがオブジェクトを変更すると、

作業ユニットにより 初にそのオブジェクトが読取られた後に変更が加えられて

いないかを確認します。オブジェクトが変更されている場合は例外を発生して、

作業ユニットはトランザクションをロールバックします。

Page 20: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

20

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

1 回の操作でオブジェクトの作成および登録

ここでは、新しい Pet オブジェクトの作成、作業ユニットへの登録、クローンの

戻しを 1 回で操作するため、作業ユニットの newInstance メソッドの使用を検討し

ます。オブジェクトの作成にファクトリ・パターンを使用している場合(Mapping

Workbench で指定することができます)、builder で指定すると、newInstance メソ

ッドでは適切なファクトリを使用します。

UnitOfWork uow = session.acquireUnitOfWork(); Pet petClone = (Pet)uow.newInstance(Pet.class); petClone.setId(100); petClone.setName("Fluffy"); petClone.setType("Cat"); uow.commit();

registerNewObject の使用方法

ここでは、拡張 API メソッドである registerNewObject を検討します。内容を次に

示します。

• registerNewObject による新しいオブジェクトの登録

• 新しいオブジェクト同士の関連付け

registerNewObject による新しいオブジェクトの登録

registerNewObjectメソッドは新しいオブジェクトをクローンのように登録します。

コミット時、TopLink はオブジェクトの別のインスタンスを作成しますが、それ

が、ビジネス・オブジェクトのキャッシュ・バージョンになります。

registerNewObject は、次の状況で使用します。

• コミット後、オブジェクトのキャッシュ・バージョンへのハンドルが不

要になり、新しいオブジェクトのクローンの操作が必要ない場合

• クローンを新しいオブジェクトのコンストラクタに引き渡し、新しいオ

ブジェクトの登録が必要な場合

次に例を示します。

UnitOfWork uow = session.acquireUnitOfWork(); PetOwner existingPetOwnerClone = PetOwner)uow.readObject(PetOwner.class); Pet newPet = new Pet(); newPet.setId(900); newPet.setType("Lizzard"); newPet.setName("Larry"); newPet.setPetOwner(existingPetOwnerClone); uow.registerNewObject(newPet); uow.commit();

registerNewObject を使用すると、作業ユニットのコミット後に変数 newPet は使用

できません。新しいオブジェクトはクローンなため、オブジェクトのキャッシュ・

バージョンが必要な場合、その問合せが必要です。作業ユニットのコミット後、

Pet のキャッシュ・バージョンへのハンドルが必要な場合、「新しいソースと既存

のターゲット・オブジェクトの関連付け」での 初のアプローチが必要になりま

拡張 API

拡張 API

Page 21: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

21

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

す。このアプローチでは、作業ユニットのコミット後に変数 newPet がキャッシュ・

バージョンとなります。「作業ユニットのトラブルシューティング」の方法によ

り、これらの 2 つの例に変更を加えて作業ユニットのコミット後に newPet がキャ

ッシュ・コピーになっているか例題で確認してください。

新しいオブジェクト同士の関連付け

コミット時、TopLink はオブジェクトが新規かを判断できます。「新しいターゲ

ット・オブジェクトと既存のソースの関連付け」の項では、新しいオブジェクト

がクローンから到達可能な場合、新しいオブジェクトの登録は必要ないと説明し

ています。TopLink は、登録済みオブジェクトからアクセスできる新しいすべて

のオブジェクトに事実上 registerNewObject を実行します。

新しいオブジェクトの操作では次のことに注意してください。

• 到達可能または登録済みオブジェクトのみに永続性を持たせる。

• 作業ユニット内での新しいオブジェクトまたは registerNewObject で登録

されたオブジェクトは作業コピーとみなされます。

• 新しいオブジェクトを引数として渡し registerObject を実行した場合、結

果としてクローンが返され、registerObject への引数はキャッシュ・バージ

ョンとみなされます。

作業ユニットの有効なコードを次に示します。

UnitOfWork uow = session.acquireUnitOfWork(); Pet newPet = new Pet(); newPet.setId(150); newPet.setType("Horse"); newPet.setName("Ed"); PetOwner newPetOwner = new PetOwner(); newPetOwner.setId(250); newPetOwner.setName("George"); newPetOwner.setPhoneNumber("555-9999"); VetVisit newVetVisit = new VetVisit(); newVetVisit.setId(350); newVetVisit.setNotes("Talks a lot"); newVetVisit.setSymptoms("Sore throat"); newPet.getVetVisits().addElement(newVetVisit); newVetVisit.setPet(newPet); newPet.setPetOwner(newPetOwner); uow.registerNewObject(newPet); uow.commit();

ただし、newPet、newPetOwner および newVetVisit の 3 つの変数は厳密に言えば作

業ユニットからのコピーなため、作業ユニットの完了後にこれらの変数使用しな

いでください。これらのビジネス・オブジェクトのキャッシュ・バージョンへの

ハンドルが必要な場合は、これらのオブジェクトを問い合せるか、または作業ユ

ニットを次のように実行します。

Page 22: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

22

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

UnitOfWork uow = session.acquireUnitOfWork(); Pet newPet = new Pet(); Pet newPetClone = (Pet)uow.registerObject(newPet); newPetClone.setId(150); newPetClone.setType("Horse"); newPetClone.setName("Ed"); PetOwner newPetOwner = new PetOwner(); PetOwner newPetOwnerClone = (PetOwner)uow.registerObject(newPetOwner); newPetOwnerClone.setId(250); newPetOwnerClone.setName("George"); newPetOwnerClone.setPhoneNumber("555-9999"); VetVisit newVetVisit = new VetVisit(); VetVisit newVetVisitClone = (VetVisit)uow.registerObject(newVetVisit); newVetVisitClone.setId(350); newVetVisitClone.setNotes("Talks a lot"); newVetVisitClone.setSymptoms("Sore throat"); newPetClone.getVetVisits().addElement(newVetVisitClone); newVetVisitClone.setPet(newPetClone); newPetClone.setPetOwner(newPetOwnerClone); uow.commit();

一般的なエラー

新しいオブジェクトが registerNewObject で登録されているか、または登録されて

いないが到達可能にすることで永続化されている場合、作業ユニットの完了後に

新しいオブジェクトを使用しようとする。作業ユニットのコミット後は、これら

のオブジェクトを使用しないでください。

registerAllObjects の使用方法

ここでは、拡張 API メソッドである registerAllObjects を検討します。

registerAllObjects メソッドは、オブジェクトのコレクションを引数としてとり、ク

ローンのコレクションを返します。そのため、多数のオブジェクトを一度に登録

できます。次に例を示します。

UnitOfWork uow = session.acquireUnitOfWork(); Collection toRegister = new Vector(2); VetVisit vv1 = new VetVisit(); vv1.setId(70); vv1.setNotes("May have flu"); vv1.setSymptoms("High temperature"); toRegister.add(vv1); VetVisit vv2 = new VetVisit(); vv2.setId(71); vv2.setNotes("May have flu"); vv2.setSymptoms("Sick to stomach"); toRegister.add(vv2); uow.registerAllObjects(toRegister); uow.commit();

拡張 API

Page 23: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

23

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

登録および存在チェックの使用方法

ここでは、オブジェクトの登録時間を短縮するための存在チェックポリシーを検

討します。

存在チェックについて

TopLink は、データベースへオブジェクトを書き込む場合、挿入または更新する

かの判断に存在チェックを実行します。デフォルトでは、TopLink は「キャッシ

ュのチェック」という存在チェックポリシーを使用します。デフォルトの存在チ

ェックポリシーは、プロジェクト全体またはディスクリプタ単位で指定できます。

存在チェックポリシーには、次のオプションがあります。

• キャッシュのチェック

• データベースのチェック

• 存在すると仮定

• 存在しないと仮定

「キャッシュのチェック」以外の存在チェックポリシーを使用すると、有益な方法

で TopLink の各オブジェクトへの登録に要する時間の短縮ができます。

データベースのチェック

「データベースのチェック」を存在チェックポリシーとして使用すると、TopLink

はデータベースを調べ作業ユニットに登録されているすべてのオブジェクトの存

在を確認します。ただし、オブジェクトが新規または既存かわかっている場合は、

基本となる registerObject メソッドのかわりに registerNewObject または

registerExistingObject を使用して存在チェックを省略することができます。TopLink

は、これらのメソッドで登録されたオブジェクトの存在チェックをデータベース

に対して行いません。TopLink は、registerNewObject がコールされると自動的に挿

入し、registerExistingObject がコールされると自動的に更新します。

存在すると仮定

存在チェックポリシーで「存在すると仮定」オプションを指定すると、作業ユニ

ットに登録されているすべてのオブジェクトを存在するとみなし、TopLink は登

録されているすべてのオブジェクトについて registerObject で登録した新しいオブ

ジェクトも含め、常にデータベースに対して更新を実行します。ただし、新しい

オブジェクトに registerNewObject メソッドを使用した場合は、存在チェックポリ

シーで「存在すると仮定」が指定されていても、TopLink はデータベースへ挿入

します。

存在しないと仮定

存在確認ポリシーで「存在しないと仮定」オプションを指定すると、作業ユニッ

トに登録されているすべてのオブジェクトを新規オブジェクトとみなし、TopLink

はデータベースから読み込まれたオブジェクトについてもデータベースへ挿入し

ます。ただし、既存オブジェクトに registerExistingObject メソッドを使用した場合、

TopLink はデータベースを更新します。

拡張 API

Page 24: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

24

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

集計の操作

TopLink において、集計マッピング(または集約マッピングと呼ばれます)され

たオブジェクトは絶対に登録しないでください(登録すると例外が発生します)。

集計クローニングおよび登録は、集計オブジェクトの所有側オブジェクトに基づ

いて自動的に行われます。つまり、集計の所有側オブジェクトを登録すると、所

有される側が自動的にクローン化されます。集計の所有側オブジェクトの作業コ

ピーを取得する場合、この所有される側も作業コピーです。

つまり集計の操作は、集計の所有側オブジェクトに関連してのみ、行うことがで

きます。

• 作業コピーの所有側オブジェクトから所有される側を取得すると、それ

が作業コピーになります。

• キャッシュ・バージョンの所有側オブジェクトから所有される側を取得

すると、それがキャッシュ・バージョンになります。

作業クローンの登録解除

ここでは、作業ユニットからクローンの登録を解除する方法を検討します。

作業ユニットの unregisterObject メソッドを使用すると、作業ユニットに登録済み

のオブジェクトの登録を解除できます。作業ユニットでは、登録解除されたオブ

ジェクトは無視され、その時点までにオブジェクトに対する変更でコミットされ

ていないものは破棄されます。

通常、このメソッドはほとんど使用されません。新しいオブジェクトの作成の際

には有用な場合もありますが、その場合は、同一作業ユニット内での削除を実行

することを検討してください(どちらの場合も推奨されません)。

読取り専用クラスの宣言

ここでは、拡張 API メソッドである addReadOnlyClass および addReadOnlyClasses

を使用して、作業ユニットのパフォーマンスを向上させる方法を検討します。

クラスへの変更が加えられない場合、そのクラスのインスタンスの登録前に、そ

の旨を作業ユニットに通知します。クラスが読取り専用として指定されている場

合、作業ユニットは次のインスタンスを無視します。

• そのクラスのインスタンス

• 参照する任意のクラスのインスタンス

• 拡張する任意のクラスのインスタンス

つまり、これらのオブジェクトのインスタンスを登録しても(または暗黙的な登

録も)、作業ユニットはこれらのインスタンスのクローンの作成またはマージを

行いません。これらのインスタンスはトランザクションには参加せず、これらの

オブジェクトに対して行った変更の永続化はありません。

たとえば、クラス A はクラス B を所有してクラス C はクラス B を拡張すると仮定

します。クラス A のインスタンスのみに変更が加えられ、クラス B には変更がな

いことがわかっています。クラス B のインスタンスの登録前に次のメソッドを使

用します。

拡張 API

拡張 API

拡張 API

Page 25: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

25

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

myUnitofWork.addReadOnlyClass(B.class);

Page 26: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

26

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

その後、オブジェクト A の登録、その作業コピーの変更、作業ユニットのコミッ

トなど、トランザクションを継続します。

コミット時、作業ユニットは、バックアップ・コピーのクローンをクラス B のイ

ンスタンスの作業コピーのクローンと比較する必要はありません(インスタンス

が明示的または暗黙的に登録されている場合も同様です)。そのため、オブジェ

クト・ツリーのサイズが非常に大きくなっても作業ユニットのパフォーマンスは

向上します。

クラス C のインスタンスを登録しても、作業ユニットがこのオブジェクトのクロ

ーンを作成したりマージすることはなく、クラス C での変更は永続化されません。

これは、クラス C がクラス B を拡張し、クラス B は読取り専用として指定されて

いるためです。

読取り専用として指定するクラスが複数の場合、Vector に追加して次のメソッド

を使用します。

myUnitOfWork.addReadOnlyClasses(myVectorOfClasses);

すべての作業ユニットについて読取り専用として指定するクラスが複数の場合、

プロジェクトのメソッド setDefaultReadOnlyClasses(Vector)を使用します。

一致クエリー

ここでは、コミット前に作業ユニット内の問合せに新しいオブジェクトを含める

方法を検討します。内容を次に示します。

• 一致クエリーの使用方法

• 一致クエリーにかわる手段

一致クエリーの使用方法

問合せがデータベースに対して実行されるため、作業ユニットを介した問合せに、

デフォルトでは作業ユニット内のコミットされていない新しいオブジェクトを含

みません。作業ユニットに対して明示的に指示しないかぎり、作業ユニットはそ

の中のコミットされていない新しいオブジェクトは問い合せません。

たとえば、データベースに Cat 型の Pet が存在するという前提で、次のコードを検

討します。

UnitOfWork uow = session.acquireUnitOfWork(); Pet pet2 = new Pet(); Pet petClone = (Pet)uow.registerObject(pet2); petClone.setId(200); petClone.setType("Cat"); petClone.setName("Mouser"); ReadAllQuery readAllCats = new ReadAllQuery(); readAllCats.setReferenceClass(Pet.class); ExpressionBuilder builder = new ExpressionBuilder(); Expression catExp = builder.get("type").equal("Cat"); readAllCats.setSelectionCriteria(catExp); Vector allCats = (Vector)uow.executeQuery(readAllCats); System.out.println("All 'Cats' read through UOW are: " + allCats); uow.commit();

拡張 API

Page 27: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

27

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

このコードから次の出力が生成されます。

All 'Cats' read through UOW are: [Pet type Cat named Fluffy id:100]

readAllCats という問合せに新しいオブジェクトを含むように指示するには、次の

ように指定します。

readAllCats.conformResultsInUnitOfWork();

出力は次のようになります。

All 'Cats' read through UOW are: [Pet type Cat named Fluffy id:100, Pet type Cat named Mouser id:200]

一致クエリーは、パフォーマンスに影響することに注意してください。一致クエ

リーの使用前に、実際に必要かどうかの確認が必要です。たとえば「一致クエリ

ーにかわる手段」に説明されている代替手段を検討してください。

一致クエリーにかわる手段

他のコード・モジュールに、作業ユニットで作成した新しいオブジェクトへのア

クセス権を与える必要性もあります。一致クエリーでは、このアクセス権を与え

ることができますが、次の代替手段が非常に効率的です。

ある場所でセッションから作業ユニットを取得し、必要な処理の一部に対応する

複数のモジュールに渡すことを考えます。

UnitOfWork uow = session.acquireUnitOfWork();

新しい Pet を作成するモジュールで、次のように指定します。

Pet newPet = new Pet(); Pet newPetClone = (Pet)uow.registerObject(newPet); uow.setProperty("NEW PET", newPet);

さらに変更するために newPet へのアクセスが必要な他のモジュールでは、作業ユ

ニットのプロパティから newPet を抽出できます。

Pet newPet = (Pet) uow.getProperty("NEW PET"); newPet.setType("Dog");

一致クエリーが適しているのは、オブジェクトが作成済みかどうか不明な場合、

または検索基準が動的な場合です。。

しかし、オブジェクト数が限定され既知の場合は、一致クエリーよりも単純で効

率的なこのソリューションが有用です。

commitAndResume の使用方法

ここでは、拡張 API メソッドである commitAndResume を検討します。

作業ユニットはコミットおよび再開ができます。commit ではなく

commitAndResume のコールにより、データベースおよびキャッシュは通常どおり

更新されますが、作業ユニットはオープンした状態とみなされ変更を行うことが

できます。すべてのクローンは有効の状態なため、再開した作業ユニットでオブ

ジェクトの再登録は必要ありません。

拡張 API

Page 28: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

28

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

次に例を示します。

UnitOfWork uow = session.acquireUnitOfWork(); PetOwner petOwnerClone = (PetOwner)uow.readObject(PetOwner.class); petOwnerClone.setName("Mrs. Newowner"); uow.commitAndResume(); petOwnerClone.setPhoneNumber("KL5-7721"); uow.commit();

commitAndResume のコールにより次の SQL が生成されます。

UPDATE PETOWNER SET NAME = 'Mrs. Newowner' WHERE (ID = 400)

さらに commit のコールにより次の SQL が生成されます。

UPDATE PETOWNER SET PHN_NBR = 'KL5-7721' WHERE (ID = 400)

ネストされた作業ユニットの使用方法

ここでは、作業ユニットをネストする方法を検討します。

TopLink は、ネストされた作業ユニットに完全に対応します。ネストされた作業

ユニットの作成には、acquireUnitOfWork メソッドを使用して別の作業ユニットか

ら作業ユニットを取得します。

も外側の作業ユニットがコミットされるまで、TopLink がデータベースまたは

キャッシュの更新を行うことはありません。

ある作業ユニットの作業コピーは、別の作業ユニットでは裕子ではありません。

内側と外側の作業ユニット間でも同様です。オブジェクトが使用されるすべての

レベルの作業ユニットで、オブジェクトの登録が必要です。

次に例を示します。

UnitOfWork outerUOW = session.acquireUnitOfWork(); Pet outerPetClone = (Pet)outerUOW.readObject(Pet.class); UnitOfWork innerUOWa = outerUOW.acquireUnitOfWork(); Pet innerPetCloneA = (Pet)innerUOWa.registerObject(outerPetClone); innerPetCloneA.setName("Muffy"); innerUOWa.commit(); UnitOfWork innerUOWb = outerUOW.acquireUnitOfWork(); Pet innerPetCloneB = (Pet)innerUOWb.registerObject(outerPetClone); innerPetCloneB.setName("Duffy"); innerUOWb.commit(); outerUOW.commit();

カスタム SQL での作業ユニットの使用方法

ここでは、作業ユニットの内部でのカスタム SQL の出力方法を検討します。

次のように作業ユニットの executeNonSelectingCall メソッドをコールして、カスタ

ム SQL をいつでも作業ユニットに追加できます。

uow.executeNonSelectingCall(new SQLCall(mySqlString));

拡張 API

拡張 API

Page 29: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

29

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

JTA での作業ユニットの使用方法

ここでは、Container Managed Persistence(CMP)を採用した Java Transaction API

(JTA)/Java Transaction Service(JTS)での作業ユニットの使用方法を検討します。

ホスト・アプリケーション・サーバーの JTA/JTS サービスを使用する作業ユニッ

トの構成には、トランザクションの管理および境界設定を J2EE コンテナに委任し

ます。作業ユニットは JTA/JTS トランザクションに参加しますが、その管理は行

いません。

この場合、セッションの getActiveUnitOfWork メソッドでコンテナのアクティブな

トランザクションに関連付けられた作業ユニットを取得します。コンテナは、与

えられた JDBC 接続がアクティブなトランザクションに関連付けられていること

を保証します。

2 フェーズ・コミットの場合、J2EE コンテナがトランザクションを管理するため、

作業ユニットはトランザクションにのみ参加します。2 フェーズ・コミットの使

用には、複数のリソースを同一 JTA トランザクションに登録することが必要です。

コンテナは、コミット処理の際にデータ・ソースおよび登録済みリスナー(TopLink

など)に適切なコールバックを行います。TopLink は、適切なコールバックを受

け取るとデータベースに対する SQL を発行します。

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

• sessions.xml による JTA を使用する作業ユニットの構成

• Java による JTA を使用する作業ユニットの構成

• JTA 環境での作業ユニットの取得

• 既存の JTA トランザクションでの作業ユニットの使用方法

• 新しい JTA トランザクションでの作業ユニットの使用方法

sessions.xml による JTA を使用する作業ユニットの構成

sessions.xml ファイルで外部トランザクション・コントローラを構成する手順を示

します。

1. J2EE コンテナのマニュアル(この例では MyApplicationDS)に従い、ア

プリケーション・サーバー上の JTA 対応のデータ・ソースを構成します。

2. このデータ・ソースを参照する sessions.xml ファイルのログイン要素、外

部トランザクション・コントローラおよび外部接続プールの使用を構成

します。

<data-source>jdbc/MyApplicationDS</data-source> <uses-external-transaction-controller> true </uses-external-transaction-controller> <uses-external-connection-pool> true </uses-external-connection-pool>

3. 外部トランザクション・コントローラを sessions.xml ファイルに追加しま

す。

拡張 API

Page 30: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

30

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

<external-transaction-controller-class> oracle.OracleASTopLink.jts.oracle9i.Oracle9iJTSExternal TransactionController </external-transaction-controller-class>

Java による JTA を使用する作業ユニットの構成

Java のコーディングで外部トランザクション・コントローラを構成する手順を示

します。

1. J2EE コンテナのマニュアル(この例では MyApplicationDS)に従い、ア

プリケーション・サーバー上の JTA 対応のデータ・ソースを構成します。

2. DataSource を指定するログイン、外部トランザクション・コントローラお

よび外部接続プールの使用を構成します。

login.setConnector( new JNDIConnector(new InitialContext(), "jdbc/MyApplicationDS") ); login.setUsesExternalTransactionController(true); login.setUsesExternalConnectionPooling(true);

3. ExternalTransactionControllerの特定のインスタンスを使用するセッション

を構成します。

serverSession.setExternalTransactionController( new Oracle9iJTSExternalTransactionController() );

JTA 環境での作業ユニットの取得

作業ユニットを使用して、JTA 環境でもデータベースへの書込みを可能にします。

1 つの作業ユニットのみが特定のトランザクションに関連付けられるようにする

には、次の例のように getActiveUnitOfWork メソッドを使用して作業ユニットを取

得します。

boolean shouldCommit = false; // Read in any pet. Pet pet = (Pet)clientSession.readObject(Pet.class); UnitOfWork uow = clientSession.getActiveUnitOfWork(); // If uow is not null, use existing external transaction if (uow == null) { // Start external transaction uow = clientSession.acquireUnitOfWork(); shouldCommit = true; } Pet petClone = (Pet) uow.registerObject(pet); petClone.setName("Furry"); if (shouldCommit) { uow.commit(); // Ask external transaction controller to commit }

getActiveUnitOfWork メソッドによって既存の外部トランザクションが検索されま

す。

• アクティブな外部トランザクションがあり、作業ユニットがすでに関連

付けられている場合は、この作業ユニットが返されます。

Page 31: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

31

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

• アクティブな外部トランザクションがあり、作業ユニットが関連付けら

れていない場合は新しい作業ユニットが取得され、トランザクションに

関連付けられ、その結果が返されます。

• アクティブな外部トランザクションがない場合は null が返されます。

null でない作業ユニットが返された場合、commit メソッドをコールしないこと以

外は(「外部トランザクションが存在する場合の作業ユニットの使用方法」の項

を参照)、JTA 以外の環境での使用と同様にこの作業ユニットを使用します。

null の作業ユニットが返された場合、明示的に UserTransaction インタフェースを

介して外部トランザクションを開始するか、もしくはクライアント・セッション

で acquireUnitOfWork メソッドを使用して新しい作業ユニットを取得することで

外部トランザクションを開始します(「外部トランザクションが存在しない場合

の作業ユニットの使用方法」を参照)。

外部トランザクションが存在する場合の作業ユニットの使用方法

getActiveUnitOfWork から null でないの作業ユニットが返された場合、既存の外部

トランザクションに関連付けられるため、通常どおりに作業ユニットを使用しま

す。

外部トランザクションは作業ユニットによって開始されたものでないため、この

トランザクションに対するコミットを発行しても JTA トランザクションのコミッ

トは開始されません。作業ユニットは、トランザクションを開始したアプリケー

ションまたはコンテナに従います。外部トランザクションがコンテナによってコ

ミットされた場合、TopLink はコミット時の主要なポイントで同期コールバック

を受け取ります。

作業ユニットは、beforeCompletion コールバックを受け取ると必要な SQL をデー

タベースに送ります。

作業ユニットは、afterCompletion コールバックから受け取ったブール引数を使用

して、コミットの成功(true)と失敗(false)を判断します。

コミットが成功した場合、作業ユニットは変更をセッション・キャッシュにマー

ジします。コミットが失敗した場合、作業ユニットは変更を破棄します。

Page 32: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

32

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

外部トランザクションが存在しない場合の作業ユニットの使用方法

getActiveUnitOfWork から null の作業ユニットが返された場合、既存の外部トラン

ザクションは存在しないため、新しい外部トランザクションの開始が必要です。

これには、UserTransaction インタフェースを明示的に使用して外部トランザクシ

ョンを開始するか、またはセッションで acquireUnitOfWork メソッドを使用して新

しい作業ユニットを取得します。

作業ユニットは通常どおりに使用します。

登録済みのオブジェクトへの変更が完了後、明示的に UserTransaction インタフェ

ースを介すか、または作業ユニットの commit メソッドをコールすることでトラン

ザクションのコミットが必要です。

その後、TopLink で同期コールバックが起動され、これらのコールバックに基づ

いたデータベース更新およびキャッシュ・マージが行われます。

削除順序の制御

ここでは、作業ユニットがオブジェクトを削除する順序の制御に使用できる拡張

API メソッドについて検討します。

「オブジェクトの削除」の項では、オブジェクト・モデルおよびスキーマのマッピ

ングおよび外部キーに基づいて、常に TopLink が SQL を順序付けると説明しまし

た。削除順序の制御には次のメソッドが使用できます。

• 作業ユニットの setShouldPerformDeletesFirst メソッド

• ディスクリプタの addConstraintDependencies メソッド

拡張 API

Page 33: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

33

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

作業ユニットの setShouldPerformDeletesFirst メソッド

作業ユニットの setShouldPerformDeletesFirst メソッドをコールすることにより、挿

入および更新前の削除を作業ユニットに指示できます。

デフォルトでの TopLink は参照整合性を保つため、 初に挿入および更新します。

一意制約を持つオブジェクトを置き換えるため、既存オブジェクトを削除し、そ

れに置き換わるオブジェクトを挿入する際に、もし削除前に挿入が行われた場合

は制約違反が発生します。この場合、setShouldPerformDeletesFirst をコールするこ

とで挿入前に削除を実行できます。

ディスクリプタの addConstraintDependencies メソッド

削除順序を決めるために TopLink が使用する制約は、1 対 1 および 1 対多マッピ

ングから判断されます。これらのマッピングが存在しない場合は、記述子の

addConstraintDependencies(Class)メソッドを使用して、制約に関する情報を

TopLink に追加できます。

たとえば、A に B が含まれ(1 対多の私有リレーションシップ)、B は C と 1 対 1

の私有でないリレーションシップを持つというオブジェクトの構成があるとしま

す。

A(結果としてそれに含まれる B も)削除する際に、一部の(すべてではない)B

に関連付けられた C も削除したい場合を考えます。

このケースには、次の 2 つの方法が使用できます。

• addConstraintDependencies を指定せずに deleteAllObjects を使用

• addConstraintDependencies を指定して deleteAllObjects を使用

addConstraintDependencies を指定せずに deleteAllObjects を使用する

初のオプションでは、A と B の 1 対多の私有リレーションシップは使用しませ

ん。A の削除には、A に含まれているすべての B およびすべてのインスタンス C

を削除するように注意します。次に例を示します。

uow.deleteObject(existingA); uow.deleteAllObjects(existingA.getBs()); // delete one of the C's uow.deleteObject(((B) existingA.getBs().get(1)).getC());

このオプションからは次の SQL が生成されます。

DELETE FROM B WHERE (ID = 2) DELETE FROM B WHERE (ID = 1) DELETE FROM A WHERE (ID = 1) DELETE FROM C WHERE (ID = 1)

addConstraintDependencies を指定して deleteAllObjects を使用する

2 番目のオプションでは、A と B 間の 1 対多の私有リレーションシップを保ち、A

から C に制約の依存関係を追加します。

session.getDescriptor(A.class).addConstraintDependencies(C.class);

Page 34: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

34

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

削除コードは次のようになります。

uow.deleteObject(existingA); uow.deleteAllObjects(existingA.getBs()); // delete one of the C's uow.deleteObject(((B) existingA.getBs().get(1)).getC());

このオプションからは次の SQL が生成されます。

DELETE FROM B WHERE (A = 1) DELETE FROM A WHERE (ID = 1) DELETE FROM C WHERE (ID = 1)

いずれの場合も、A および C の削除前に B が削除されます。前述のオプションと

の主な相違点は、A と関係を持つ B 全体を削除することがわかっているため、生

成される SQL 文が少なくなることです。

結論

TopLink の作業ユニットは、直接または J2EE の外部トランザクション・コントロ

ーラを介して、トランザクションとしてオブジェクト変更を行うタスクの簡素化

を図る柔軟で強力なツールです。作業ユニットは次に示す機能を備えているため、

TopLink アプリケーションでは、データベースへの書込みに 適な方法です。

• フィールド・レベルでの厳密な変更のみを更新することで、コミット時

に必要 低限の SQL をデータベースに送信します。

• トランザクション操作をトランザクション専用のメモリー空間内で独立

して行うことで、データベースのトラフィックを軽減します。

• キャッシュ間でオブジェクトではなくチェンジ・セットを受渡すことに

より、複数のキャッシュを使用するアプリケーションでのキャッシュ同

期を 適化します。

• オブジェクト変更を専用のトランザクション領域内で独立して行い、同

一オブジェクトに対する並行トランザクションが使用できます。

• SQL の順序付けを自動管理することで参照整合性を保ち、デッドロック

を 小限に抑えます。

• データベースの挿入、更新、および削除を順序付けて、マップされたオ

ブジェクトの参照整合性を保ちます。

• 双方向参照を自動的に解決します。

Page 35: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

35

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

ベスト・プラクティス

次に作業ユニットを使用する際の推奨事項を示します。

1. 常にクローンを使用する習慣を身につけてください(「オブジェクトの作成」

の項を参照)。

2. 作業ユニットを介した問合せで、クローンを取得して登録作業を省略方法で

はなく、セッションを介して ReadAllQuery を実行し、変更が必要なオブジェ

クトのみを登録する(「オブジェクトの変更」の項を参照)アプリケーショ

ンの設計をお薦めします。

3. 主キーに基づく問合せでは、デフォルトによりキャッシュ内に格納されてい

る内容が返されますが、主キーに基づかない問合せでは、データベース内に

格納されている内容が返されます(「オブジェクトがキャッシュ・オブジェ

クトかどうかの判断」の項を参照)。

4. TopLink の例外は、RunTimeException のインスタンスであるため、捕捉する

必要はありませんが、作業ユニットの commit メソッドによってスローされた

例外の処理は必要となります(「例外の処理」の項を参照)。

5. オブジェクトのキャッシュ・バージョンへのハンドルを、コミット後も保持

する場合は新しいオブジェクトを登録します。ただし、登録済みの新しいオ

ブジェクトを作業ユニットに関連付けるには、TopLink は新しいオブジェクト

をクローンとして扱うことを覚えておいてください。コミット前は、キャッ

シュ・オブジェクトが参照対象ですが、コミット後はクローンが参照対象に

なります(「新しいターゲットと既存のソース・オブジェクトの関連付け」

の項を参照)。

6. 新しいターゲットを既存のソース・ターゲットに関連付ける際、オブジェク

トを登録しない場合でも、TopLink によってクローンが作成されます(キャッ

シュ・オブジェクト参照がクローン参照になります)。ただし、新しいソー

ス・オブジェクトを既存のターゲット・オブジェクトに関連付ける場合は、

新しいオブジェクトの登録が必要です(「新しいソースと既存のターゲット・

オブジェクトの関連付け」の項を参照)。

7. コミットされていないオブジェクトを作業ユニット内で実行されるクエリー

に含むには conformResultsInUnitofWork を使用しますが、この機能は、パフォ

ーマンスに影響することに注意してください(「一致クエリー」の項を参照)。

8. コミット後も変更の継続が必要な場合は、commit ではなく commitAndResume

を使用します。登録されているすべてのクローンは有効のままで、再登録の

必要はありません(「commitAndResume の使用方法」の項を参照)。

9. クローンをオブジェクトのコンストラクタに渡した後、新しいオブジェクト

の登録が必要な場合は registerNewObject を使用します(「registerNewObject

の使用方法」の項を参照)。

10. 集計マッピングされたオブジェクトは絶対に登録しないでください。作業コ

ピーの所有側オブジェクトから所有される側のオブジェクトを取得すると、

そのオブジェクトが作業コピーになり、キャッシュ・バージョンから所有さ

れる側のオブジェクトを取得すると、そのオブジェクトがキャッシュ・バー

ジョンとなることに注意してください(「集計の操作」の項を参照)。

Page 36: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門

36

Oracle Corporation 発行「Oracle Application Server TopLink Unit of Work Primer」の翻訳版です。

11. ネストされた作業ユニットの場合、TopLink は も外側の作業ユニットがコミ

ットされるまで、コミットしません。オブジェクトが使用される作業ユニッ

トのすべてのレベルで、オブジェクトの登録が必要となります(「ネストさ

れた作業ユニットの使用方法」の項を参照)。

用語集

用語 定義 別称

キャッシュ・ バージョン

TopLink キャッシュ内のルート・セッショ

ン・レベルで格納されるオリジナルのビジ

ネス・オブジェクト。このビジネス・オブ

ジェクトの ID は、JVM 全体を通して

TopLink によって保持されます。通常、単

に「キャッシュ・コピー」と呼ばれます。

マスター・バージョン、 オリジナル・バージョン、

アイデンティティ・バージ

ョン

既存オブジェクト データベース内ですでに永続オブジェク

トになっているオブジェクト。この中に

は、データベースへの書込みが成功した新

しいオブジェクトや、データベースから読

み出されたオブジェクトも含みます。

永続オブジェクト、 書込み済みオブジェクト

トランザクション

境界の設定 トランザクションの先頭と 後を決める

こと。JTA/JTSトランザクションでは、J2EEコンテナがトランザクションの境界設定

を行います。または、作業ユニットの

commit(または commitAndResume)メソッ

ドを使用して、トランザクションの 後を

定義します。

ソース ある関係の元になるオブジェクト。 たとえば、従業員と住所の間に 1 対 1 の関

係がある場合、従業員をソースと呼びま

す。教師と生徒間に 1 対多の関係がある場

合、教師がソースになります。

ターゲット ある関係を持つソース・オブジェクトの逆

側に位置するもの。たとえば、従業員と住

所の間に 1 対 1 の関係がある場合、住所を

ターゲットと呼びます。教師と生徒間に 1対多の関係がある場合、生徒をターゲット

と呼びます。

作業ユニット 標準的なトランザクションの ACID プロパ

ティ(原子性、一貫性、隔離性、永続性)

に従うオブジェクト・レベルのトランザク

ション。

「オブジェクト・レベル」

のトランザクション、 TopLink トランザクショ

ン、UOW、トランザクシ

ョン・コンテキスト

作業ユニットの 作業コピー

作業ユニット内で個別に変更できるビジ

ネス・オブジェクトの作業コピー。 通常、単に「クローン」と呼ばれます。

クローン、作業コピー、 コピー

Page 37: Oracle Application Server TopLink の 作業ユニット入門otndnld.oracle.co.jp/products/ias/toplink/pdf/unitOfWorkWP.pdfOracle Application Server TopLink の作業ユニット入門

Oracle Application Server TopLink の作業ユニット入門 2003 年 8 月 著書: Peter Purich 寄稿者: Tatjana Obradovic、Douglas Clarke Oracle Corporation World Headquarters 500 Oracle Parkway Redwood Shores, CA 94065 U.S.A. 海外からのお問合せ窓口: 電話: +1.650.506.7000 ファックス: +1.650.506.7200 www.oracle.com Copyright © 2003, Oracle. 無断転載を禁ず この文書はあくまで参考資料であり、掲載されている情報は予告なしに変更されることがあります。 オラクル社は、本ドキュメントの無謬性を保証しません。また、本ドキュメントは、法律で明示的または暗黙的に記載

されているかどうかに関係なく、商品性または特定の目的に対する適合性に関する暗黙の保証や条件を含む一切の保証

または条件に制約されません。オラクル社は、本書の内容に関していかなる保証もいたしません。また、本書により、

契約上の直接的および間接的義務も発生しません。本書は、事前の書面による承諾を得ることなく、電子的または物理

的に、いかなる形式や方法によっても再生または伝送することはできません。 Oracle は米国 Oracle Corporation および関連会社の登録商標です。他の製品名は、それぞれの所有者の商標です。