この項の内容は次のとおりです。
OracleAS TopLinkの作業ユニットはトランザクションを単純化し、トランザクションのパフォーマンスを向上させます。次の理由から、作業ユニットはOracleAS TopLinkでデータベースへの書込みを行う際の推奨方法です。
正確な変更のみをフィールド・レベルで更新することにより、コミット時にデータベースに送信するSQLの量が最小限に抑えられます。
トランザクション操作を独自のメモリー領域に分離することにより、データベース・トラフィックが減少します。
キャッシュ間でオブジェクトではなくチェンジ・セットを受け渡すことにより、複数のキャッシュを使用するアプリケーションでキャッシュの同期が最適化されます。
オブジェクトの変更を独自のトランザクション領域に分離することにより、同じオブジェクトに対するパラレル・トランザクションが可能になります。
SQLの順序を自動的にメンテナンスすることにより、参照整合性が保証され、デッドロックが最小限に抑えられます。
データベースの挿入、更新および削除の順序を指定することにより、マップされるオブジェクトの参照整合性が維持されます。
双方向参照が自動的に解決されます。
変更の追跡や記録をアプリケーションで行う必要がなくなります。
到達可能性による永続性を使用することで、永続性が単純化されます(「関連付け: 新規ソースを既存のターゲット・オブジェクトへ」を参照)。
作業ユニットは次のように使用されます。
クライアント・アプリケーションがセッション・オブジェクトから作業ユニットを取得します。
クライアント・アプリケーションがOracleAS TopLinkに対して問合せを行い、変更対象のキャッシュ・オブジェクトを取得した後、そのキャッシュ・オブジェクトを作業ユニットに登録します。
最初のオブジェクトが登録されると、作業ユニットはトランザクションを開始します。
各オブジェクトが登録されるたびに、作業ユニットはセッション・キャッシュまたはデータベースのオブジェクトにアクセスし、バックアップ・クローンと作業クローンを作成します(「クローンと作業ユニット」を参照)。
作業ユニットが作業クローンをクライアント・アプリケーションに返します。
クライアント・アプリケーションが作業クローンを変更します。
クライアント・アプリケーション(または外部トランザクション・コントローラ)がトランザクションをコミットします(「コミットとロールバック」を参照)。
例7-1は、ライフ・サイクルをコードで示したものです。
// The application reads a set of objects from the database.
Vector employees = session.readAllObjects(Employee.class);
// The application specifies an employee to edit.
. . .
Employee employee = (Employee) employees.elementAt(index);
try {
// Acquire a Unit of Work from the session.
UnitOfWork uow = session.acquireUnitOfWork();
// Register the object that is to be changed. Unit of Work returns a clone
// of the object and makes a backup copy of the original employee
Employee employeeClone = (Employee)uow.registerObject(employee);
// We make changes to the employee clone by adding a new phoneNumber.
// If a new object is referred to by a clone, it does not have to be
// registered. Unit of Work determines it is a new object at commit time.
PhoneNumber newPhoneNumber = new PhoneNumber("cell","212","765-9002");
employeeClone.addPhoneNumber(newPhoneNumber);
// We commit the transaction: Unit of Work compares the employeeClone with
// the backup copy of the employee, begins a transaction, and updates the
// database with the changes. If successful, the transaction is committed
// and the changes in employeeClone are merged into employee. If there is an
// error updating the database, the transaction is rolled back and the
// changes are not merged into the original employee object.
uow.commit();
} catch (DatabaseException ex) {
// If the commit fails, the database is not changed. The Unit of Work should
// be thrown away and application-specific action taken.
}
// After the commit, the Unit of Work is no longer valid. Do not use further.
作業ユニットは、登録された元のオブジェクトのコピーを2つ保持しています。
作業クローン
バックアップ・クローン
作業クローンの変更後にトランザクションがコミットされると、作業ユニットは作業コピーのクローンをバックアップ・コピーのクローンと比較し、変更内容をデータベースに書き込みます。作業ユニットは、クローンを使用してパラレル作業ユニット(「ネストした作業ユニットとパラレル作業ユニット」を参照)の存在を可能にしています。これは、マルチユーザーの3層アプリケーションにおいては必須です。
OracleAS TopLinkのクローニング・プロセスは、登録されているオブジェクトのマップ済属性のみをクローン化し、インダイレクションをトリガーしないかぎりインダイレクション・オブジェクトで停止するため、効率的です。詳細は、「インダイレクション」を参照してください。
ディスクリプタ・コピー・ポリシーを使用して、クローニング・プロセスをカスタマイズできます。詳細は、「ディスクリプタ・コピー・ポリシー」を参照してください。
クローンの作成元である作業ユニットをコミットした後は、トランザクションが失敗してロールバックされた場合でも、そのクローンを使用しないでください。クローンはトランザクションで使用される作業コピーであるため、トランザクションがコミットされると同時に(成功したかどうかには関係なく)、使用をやめる必要があります。作業ユニットのコミット後に、インスタンス化されていないクローンのValueHolderにアクセスすると、例外が発生します。コミットの成功後にクローンを使用できるのは、「コミット後の作業ユニットの再開」で説明する拡張APIを使用する場合のみです。
OracleAS TopLinkを使用して次のものを作成できます。
ネストした作業ユニットおよびパラレル作業ユニットの使用の詳細と例は、「ネストした作業ユニットまたはパラレル作業ユニットの使用」を参照してください。
作業ユニット(子)を別の作業ユニット(親)内にネストさせることができます。ネストした作業ユニットは、変更内容をデータベースにコミットしません。かわりに、親作業ユニットに変更内容を渡し、親がコミット時に変更内容をコミットしようとします。ネストした作業ユニットを使用すると、大規模なトランザクションを小さな独立したトランザクションに分割でき、次のことが保証されます。
ネストした各作業ユニットでの変更内容は、グループとしてコミットされるか、失敗します。
ネストした作業ユニットが失敗しても、親作業ユニットにおける他の操作のコミットまたはロールバック操作には影響を与えません。
変更内容が1つのトランザクションとしてデータベースに示されます。
作業ユニットは1つのSessionです。そのため、通常のセッションの場合と同様の一連のデータベース・アクセス・メソッドを提供します。
これらのメソッドは、作業ユニットからコールされると、作業ユニット内のオブジェクトにアクセスし、選択されたオブジェクトを自動的に登録して、クローンを返します。
そのため、registerObjectおよびregisterAllObjectsメソッドをコールする必要がなくなりますが、「オブジェクトの作成」と「関連付け: 新規ソースを既存のターゲット・オブジェクトへ」で説明するオブジェクトの登録についての制限に注意してください。
作業ユニット・トランザクションがコミットされると、そのトランザクションは成功するか、失敗してロールバックされるかのいずれかです。コミットは、アプリケーションまたはJ2EEコンテナによって開始できます。
コミット時には、作業ユニットは作業クローンとバックアップ・クローンを比較して、チェンジ・セットを計算します(つまり、必要な最小限の変更を決定します)。変更には、既存のオブジェクトの更新または削除、および新規オブジェクトの作成があります。その後、作業ユニットはデータベース・トランザクションを開始し、データベースに変更内容を書き込もうとします。変更がすべて正常にデータベースでコミットされると、作業ユニットは変更されたオブジェクトをセッション・キャッシュにマージします。変更がデータベースで失敗すると、作業ユニットはデータベース上の変更内容をすべてロールバックします。変更内容はセッション・キャッシュにマージしません。
作業ユニットは、1対1マッピングと1対多マッピングの外部キー情報を使用して、コミット順序を計算します。コミット中に制約に関する問題が発生した場合は、マッピングの定義を確認してください。registerObjectメソッドを使用してオブジェクトを登録する順序は、コミット順序には影響を与えません。
アプリケーションでJTAを使用している場合、作業ユニットのコミット動作は、JTAを使用しないアプリケーションの場合とは異なります。ほとんどの場合、作業ユニットは外部トランザクションにアタッチされます。トランザクションが存在しない場合は、作業ユニットがトランザクションを作成します。この違いは、コミット動作に次のような影響を与えます。
作業ユニットが既存のトランザクションにアタッチされた場合、作業ユニットはcommitコールを無視します。外部トランザクション全体が完了すると、作業ユニットがコミットされます。
作業ユニットが外部トランザクションを開始した場合、そのトランザクションは、作業ユニットのcommitコールを外部トランザクションのコミット・リクエストとして扱います。その後、外部トランザクションはそれ自体のコミット・コードをデータベース上でコールします。
どちらの場合も、データベース接続を所有しているのは外部トランザクションであるため、外部トランザクションのみがデータベース上でcommitをコールできます。
詳細は、「J2EE統合」を参照してください。
作業ユニットのコミットは、1つの単位として成功または失敗する必要があります。データベースへの変更内容の書込みが失敗すると、作業ユニットはデータベースを以前の状態にロールバックします。データベースは何も変更されず、作業ユニットは変更内容をセッション・キャッシュにマージしません。
JTA環境では、作業ユニットはデータベース接続を所有しません。この場合、作業ユニットはロールバック・コールをデータベースではなく外部トランザクションに送信します。外部トランザクションは、ロールバック・コールをトランザクションのロールバック・リクエストとして扱います。
詳細は、「J2EE統合」を参照してください。
作業ユニットでは、オブジェクトの主キー属性は変更できません。これはサポートされていない操作であり、この操作を行うと予期しない動作(例外またはデータベースの破損、あるいはその両方)を引き起こします。
一意制約を持つオブジェクトのインスタンスを別のインスタンスと置き換える場合は、「作業ユニットのsetShouldPerformDeletesFirstメソッドの使用」を参照してください。