コンセプト ガイド

     前  次    新しいウィンドウで目次を開く     
ここから内容の開始

サービス データ オブジェクト (SDO) の使用

この章では、AquaLogic Data Services Platform のクライアントサイド アプリケーション プログラミング オブジェクト モデルであるサービス データ オブジェクト (SDO) について説明します。 この章の内容は以下のとおりです。

 


サービス データ オブジェクトの概要

SDO は、データへのアクセスやデータの更新に使用する、Java ベースのデータ プログラミング モデルおよびアーキテクチャです。 SDO は、BEA と IBM が共同提案した仕様 (JSR 235) で定義されています。 SDO の目的は、基底のソースやデータの形式を気にすることなくアクセスおよび更新を行えるよう、統一的で使いやすいプログラミング モデルをアプリケーションに提供することです。

JDO や JDBC といった既存のデータ アクセス技術とは異なり、SDO にはデータにアクセスするための静的インタフェースと動的インタフェースの両方が指定されています。 静的な (厳密に型指定された) インタフェースは、値へのアクセスに使用できる更新可能な使いやすいモデルを提供します。 次に、静的インタフェースの関数の例を示します。

	getCUSTOMERNAME() 

この例の関数名から分かるように、静的インタフェースを使用する場合は、開発時点においてそのデータの型 (この場合であれば CUSTOMERNAME) が判明している必要があります。 開発時点で型が不明な場合は、動的な (緩やかに型指定された) インタフェースを使用できます。 次に、動的インタフェースの関数の例を示します。

	cust.get("CUSTOMERNAME") 

動的インタフェースは、データ型が不明な場合や開発時点でまだ定義されていない場合に使用できます。動的インタフェースが特に有用なのは、プログラミング ツールや、複数のデータ ソース型にまたがるフレームワークを作成する場合です。

SDO は、プログラミング インタフェースだけでなく、データ プログラミング アーキテクチャも定義します。 このアーキテクチャには、クライアントとデータ ソースの間のアダプタとして機能する「メディエータ」というコンポーネントが含まれています。 メディエータは、データ ソースとのデータのやり取りを専門に処理するコンポーネントで、 特定のソースからデータを取得し、変更内容をソースに返します。 データは、データ オブジェクトのグラフで構成される「データ グラフ」としてやり取りされます。

SDO 仕様に明記されているように、SDO 実装にはソース タイプ (データベースなど) ごとに専用のメディエータを定義するのが一般的です。 AquaLogic Data Services Platform は、SDO クライアントとデータ統合レイヤの間に常駐する「データ サービス メディエータ」を備えています。

SDO を使用すると、クライアントは本質的にステートレスかつ非接続な方法でデータを利用できます。 AquaLogic Data Services Platform では、データベースなどのソースからデータを取得する際に、データを取得するのに十分な長さの 1 つまたは複数のデータベース接続のみを取得します。 これらの接続は、データ取得後に解放されます。 クライアントは、データ ソースから切断された状態のデータのローカル コピーを使用して処理を行います。

ネットワークへのアクセスが再度発生するのは、クライアントがデータの変更をソースに適用する必要がある場合だけです。 データ アクセスを非接続にすることで、バックエンドのシステム リソースを長い時間拘束する必要がなくなり、スケーラブルで効率的なコンピューティング環境を構築できます。

また、更新の発生時にデータの整合性が保たれるよう、オプティミスティックな同時実行性ルールが採用されています。 オプティミスティックな同時実行性の場合、クライアントによる処理中もデータ ソースのデータはロックされません。 代わりに、データの更新時 (データがソースに伝播されるとき) に、潜在的な衝突がある (たとえば、そのクライアントがデータを取得した後に、他のクライアントによって同じデータが変更された) かどうかが検出されます。

サービス データ オブジェクトの詳細 (仕様、Javadoc など) については、次のドキュメントを参照してください。


http://dev2dev.bea.com/technologies/commonj/sdo/index.jsp

データ オブジェクトの取得

AquaLogic Data Services Platform では、SDO をクライアントサイド プログラミング モデルとして使用します。 つまり、Java クライアントがデータ サービスの読み取り関数を呼び出すと、戻り値が SDO データ オブジェクトとして返されます。この点は、AquaLogic Data Services Platform Mediator API を使用して呼び出した場合も、Workshop データ サービス コントロールを使用して呼び出した場合も同様です。 データ オブジェクトは、SDO プログラミング モデルの基本的なコンポーネントです。 データ オブジェクトは、構造化された情報の単位を表し、そのデータ値を取得および設定するための静的インタフェースと動的インタフェースから構成されます。

 


SDO プログラミングのサンプル

この節では、簡単なサンプル コードをもとに、SDO のプログラミングについて解説します。 このサンプルを見ると、SDO が単純で使いやすいクライアントサイド データ プログラミング モデルをどのように提供するかが分かります。

このサンプルは、図 5-1 に示すデータ サービス用に記述されたものです。

図 5-1 データ サービスのデザイン ビュー

データ サービスのデザイン ビュー

Customer データ サービスのデータ型は CUSTOMER です。 データ型とは、スキーマと呼ばれる構造化された XML ドキュメントです。 このサンプルでは、CUSTOMER データ型が顧客 ID、名前、注文といったプロパティから構成されています。 CUSTOMER インスタンスのデータは、他の 4 つのデータ サービス (CUSTOMERS、PO_CUSTOMERS、PO_ITEMS、および getCustomerCredit) から供給されます。 これらのデータ サービスは、物理的には拡張子 .ds の XQuery ドキュメントです (例 : PO_CUSTOMERS.ds)。

サンプルの Customer データ サービスには、データ型インスタンスを取得するためのメソッドがいくつか定義されています (getCustomer()、getCustomerById()、getPaymentList() など)。 関数 getPaymentList() はナビゲーション関数です。 この関数は、CUSTOMER ドキュメントを返すのではなく、論理的な関係が定義されているデータ サービスからのデータを返します。 getPaymentList() の場合は、関連するデータ サービス PAYMENTS から、指定された顧客の支払い履歴を返します。

ナビゲーション関数を使用すると、CUSTOMER ドキュメントを処理する際に必要となることの多い追加的な関連データを簡単に取得できます。 クライアント アプリケーションからは、顧客情報の取得に使用するのと同じデータ サービス ハンドルを使って、その顧客の支払い履歴の一覧を取得できることになります。

その結果として、コード リスト 5-1 に示すように、一貫性があって読みやすく、保守も容易なコードになります。

コード リスト 5-1 SDO のサンプル
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import com.bea.dsp.dsmediator.client.*;
import org.openuri.temp.schemas.customer.CUSTOMERDocument;

public class myCust {
public static void main(String[] args) throws Exception {
Hashtable h = new Hashtable();
h.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
h.put(Context.PROVIDER_URL,"t3://localhost:7001");
h.put(Context.SECURITY_PRINCIPAL,"weblogic");
h.put(Context.SECURITY_CREDENTIALS,"weblogic");

DataService ds =
com.bea.dsp.dsmediator.client.DataServiceFactory.newXmlService(
new InitialContext(h),
"Demo",
"ld:DataServices/Customer");
Object arg[]={new Integer("987655")};
CUSTOMERDocument myCustomer =
(CUSTOMERDocument) ds.invoke("getCustomer",arg);
myCustomer.getCUSTOMER().setCUSTOMERNAME("BigCo, Inc");
ds.submit(myCustomer,"ld:DataServices/Customer");
System.out.println(" Customer information: \n" + myCustomer);
}
}

適切なパッケージがインポートされ、サーバに対する初期コンテキストが確立されると、上に示したクライアント アプリケーションの 5 行のコードによって以下の処理が実行されます。

この手順全体の複雑さを、クライアント アプリケーションの開発者が意識する必要はありません。 この複雑な部分は、データ サービス レイヤと AquaLogic Data Services Platform フレームワークで処理されています。

 


データの更新

SDO では、データの読み取りの場合と同様に、データの更新においても統一的なインタフェースが提供されます。 クライアント アプリケーションは、分散された異種データ ソースのデータを、あたかも単一のエンティティのデータであるかのように変更したり更新したりできます。 異種データ ソースに変更を伝播するという複雑な作業を、クライアントのプログラマが意識する必要はありません。

データ ソースの更新は、トランザクション的に安全な方法で行われます。つまり、複数のソースに影響する更新呼び出しが発生すると、その更新に関係するすべてのデータ ソースが正常に更新されるか、すべてのデータ ソースで更新が失敗するかのどちらかになります (必要に応じて、この動作をオーバーライドすることもできます)。

データ サービスの実装においても、更新可能なデータ サービスのライブラリを構築するという面倒な作業が、AquaLogic Data Services Platform の更新フレームワークによって大幅に軽減されます。 リレーショナル ソースの場合は、通常であればデータ ソースへの変更が自動的に伝播されます。 その他のソースの場合や、リレーショナル更新をカスタマイズする場合は、AquaLogic Data Services Platform の更新フレームワークとツールを使用してさまざまな更新可能サービスをすばやく実装できます。

図 5-2 に示すように、更新のプロセスにおいては、まず要求された変更が分析されてデータの系統が判別されます。 次に、AquaLogic Data Services Platform メディエータが送信されたオブジェクトを構成要素に分解し、それぞれの変更を各データ ソースに伝播します。

図 5-2 AquaLogic Data Services Platform でのソース更新手順

AquaLogic Data Services Platform でのソース更新手順

このプロセスのどの時点でも、独自のコードでプログラム的にプロセスに介入できます。たとえば、監査を目的として、更新の値を検証することもできます。

データ サービス メディエータ

データ サービス メディエータは、AquaLogic Data Services Platform 更新フレームワークの中核的なメカニズムです。更新フレームワークは、以下に示すプログラミング アーティファクトから構成されています。

更新プランは、より細かなレベルで見ると、DataServiceToUpdate (変更されたデータ オブジェクトから構成されるデータ サービス) インスタンスのツリーで構成された Java オブジェクトです。 SDO Mediator API のクラスとしては、DataServiceToUpdate、KeyPair、UpdatePlan、および DataServiceMediatorContext が実装されています。パッケージ名は次のとおりです。

com.bea.ld.dsmediator.update パッケージ

『アプリケーション開発者ガイド』の「クライアント アプリケーション向けのデータ サービスについて」にあるトピック「Mediator API Javadoc」を参照してください。

分解プロセス

SDO モデルの重要な性質の 1 つは、変更されたオブジェクトにバインドされているデータ サービスに対して submit( ) メソッドが呼び出されるまでは、そのオブジェクトに関連付けられているバックエンド データ ソースが変更されない点です。

メディエータは、呼び出し側のクライアント アプリケーションからデータ オブジェクト (変更された SDO) を受信すると、物理データ サービスか論理データ サービスかに関係なく、必ず最初に更新オーバーライド クラスを検索します。 更新オーバーライド クラスが見つかると、それをインスタンス化して実行します。

メディエータは最初に、データ サービスの分解関数を使用して、データ オブジェクトの各構成要素を基底のデータ ソースまたはデータ サービスにマップし、それに基づいてデータ系統 (データの供給元) を判別します。 また、データ サービスに反転関数が指定されている場合は、それらを使用して完全な分解マップを定義します (反転関数については、『データ サービス開発者ガイド』の「ベスト プラクティスと高度なトピック」を参照してください)。

図 5-3 に示したように、更新された顧客情報 (Customer データ サービスからのデータ) と更新された注文 (Orders データ サービスからのデータ) から構成されている customersDocument オブジェクトは、4 つのオブジェクトに分解されます。

論理データ サービスの更新と物理データ サービスの更新には、次のような重要な違いがあります。

物理データ サービスの更新プロセス

物理データ サービスの場合、データ サービスに更新オーバーライド クラスが関連付けられている場合を除き、データ サービスへの変更が即座に伝播されます。 分解マップや更新プランは必要ありません。

メディエータは、SDO を (submit( ) メソッド呼び出しから、または上位レベルのデータ サービスからの出力として) 受信すると、まずそのデータ サービスに UpdateOverride クラスが関連付けられているかどうかをチェックします。

論理データ サービスの更新プロセス

1 つの論理データ サービスを構成するデータ サービス (論理または物理) の数に制限はありません。 最上位レベルのデータ サービス関数を実行する際は、それを構成する下位レベルの論理データ サービスが「混入」されるため、その関数が物理データ サービスに対して直接記述されているかのように見えます。 最上位レベルのデータ サービスから出力された情報のみが、次の下位レベルのデータ サービスに渡されます。

図 5-4 に、論理データ サービスの更新手順の概要を示します。

  1. クライアント アプリケーションが submit( ) メソッドを呼び出します。その際、変更されたデータ オブジェクトとそれに関連付けられたデータ グラフがメディエータに渡されます。 データ グラフには、オブジェクトに対する変更サマリが含まれています。
  2. メディエータが、送信されたデータ オブジェクトを受信して分解プロセスを開始します。最初に、更新オーバーライド クラスが存在するかどうかをチェックします。 その結果に応じて、次のどちらかの処理を行います。
    • 更新オーバーライドがない場合 : メディエータは、更新されたオブジェクトを、基底の物理データ サービスに対する複数の submit( ) 呼び出しに分解します。
    • 更新オーバーライドがある場合 メディエータは、最上位レベルの SDO から中間レベルのデータ オブジェクトをインスタンス化し、更新オーバーライド ルーチンを呼び出します。 その後は、中間レベルのデータ サービスに対する submit () が通常どおり処理されます。
    • 注意 : 更新オーバーライド クラスは、マルチレイヤ データ サービスのレイヤごとに存在する可能性があります。 したがって、論理データ サービスが他の論理データ サービスの複数のレイヤで構成されている場合は、構成レイヤごとに更新オーバーライドをチェックする必要があります。 中間レイヤのデータ サービスに更新オーバーライドがない場合は、基底のデータ サービスの SDO オブジェクトが直接作成されるのではなく、SDO オブジェクトのインスタンス化がスキップされます。 更新フレームワークのこの動作は、更新オーバーライドが関連付けられている論理データ サービスや、物理データ サービスにも適用されます。

      performChange( ) メソッドは、更新プランや分解マップにアクセスしてこれらを変更したり、他のカスタム処理を実行したりできます (処理全体を引き継ぐことも可能)。 このメソッドは、メディエータによる処理を続行するか中止するかを示す以下のブール値を返します。

    • True。 メソッドから制御が返されると、メディエータが通常の処理手順で消費します。 新しい更新プランが自動的に生成されるため、渡された SDO に対して更新オーバーライド プラン内で加えられた新しい変更も捕捉できます。 新しいプランでは、それまでに指定されていた変更に新しい変更が結合されます。
    • False。 メディエータは、変更の適用を行いません。 メソッドが false を返すのは、たとえばすべての変更の適用がすでに完了していた場合です (更新の中止が必要になるようなエラーを処理したい場合は、メソッドから例外を送出する必要があります)。
  3. メディエータが、変更しなければならないデータ サービスの供給元を特定し、その変更方法を決定します。 メディエータは、データ サービスに関連付けられている分解関数を呼び出し、そのデータ サービスの分解マップを受信します。 デフォルトでは、データ サービスの 1 番目の読み取り関数を使用して分解マップを作成します (他の分解関数が指定されていない場合)。
    1. メディエータは、変更サマリ情報とデータ サービスの分解マップを使用して更新プランを生成します。 更新プランは、変更されたデータ ソースの各インスタンスのデータ サービス オブジェクト (更新すべき SDO オブジェクト) のツリーで構成されます。
    2. メディエータは、下位レベルのすべてのデータ サービスについても更新オーバーライドをチェックし、存在する場合は更新オーバーライド クラスを実行します。
  4. メディエータが、更新プランに従って、下位レベルのデータ サービスに順番に変更を送信します。 変更を適用する順番は、ツリー内のオブジェクトの順序と、それらのコンテナ包含関係に基づき、以下のルールに従って決定されます。
    1. 同じレベル内のオブジェクト (兄弟オブジェクト) は、データ オブジェクト内での出現順序に従って処理されます。
    2. コンテナ オブジェクトは、そのコンテナに含まれているオブジェクトよりも前に処理されます。ただし、コンテナが削除されている場合は、コンテナ オブジェクトよりも前に、そのオブジェクトに含まれているオブジェクトに変更が適用されます。
    3. オブジェクトにキーペアが指定されている場合は、変更を送信する前に、キーペアの値がそのコンテナからマッピングされます。 なお、更新の間に SDO コンテナに加えられた変更 (主キーの計算など) は、コンテナに含まれているオブジェクト内でも認識できます。
    4. 図 5-4 論理データ サービスの更新プロセス


      論理データ サービスの更新プロセス

キーペアを使用した主キーと外部キーの関係のマッピング

ほとんどの RDBMS では、主キーが自動的に生成されます。つまり、リレーショナル データベースをバックエンドとするデータ サービスに新しいデータ オブジェクトを追加する際は、コード内で主キーを戻り値として処理しなければならない場合があるということになります。 たとえば、送信されたオブジェクト データ グラフに新しいデータ オブジェクト (たとえば新しい Customer オブジェクト) が含まれている場合は、必要となる主キーが AquaLogic Data Services Platform によって生成されます。

自動付番主キーのデータ挿入の場合は、新しい主キー値が生成されてクライアントに返されます。 返されるのは最上位レベルのデータ オブジェクト (マルチレベル データ サービスの最上位レベル) の主キーのみで、計算された主キーを持つネストされたデータ オブジェクトは返されません。

AquaLogic Data Services Platform では、挿入されたタプルの最上位レベルの主キーを返すことで、必要に応じて新しい主キーでタプルをフェッチしなおすことを可能にしています。

メディエータは、主キーと外部キーの論理的な関係をキーペアとして保存します (Mediator API の KeyPair クラスを参照)。 KeyPair オブジェクトは、新しいデータ オブジェクトの作成プロセスの間に、外部キー フィールドを設定するために使用するプロパティ マップです。

プロパティがコンテナ内の自動付番主キー (つまり、自動付番された後のデータ ソース内の新しいレコード) である場合は、プロパティの値が親から子へ伝播されます。

KeyPair オブジェクトは、分解マップの隣接するレベル間で、対応するデータ要素を特定するために使用します。KeyPair オブジェクトを使用することで、親 (コンテナ) オブジェクト用に生成された主キー値を、子要素 (そのコンテナに含まれるオブジェクト) の外部キー フィールドに確実にマッピングできます。

例として、図 5-5 に Customers データ サービスの分解におけるプロパティ マッピングを示します。

図 5-5 キーペアによる論理データ サービスのプロパティ マッピング (主キー/外部キー マッピング)

キーペアによる論理データ サービスのプロパティ マッピング (主キー/外部キー マッピング)

AquaLogic Data Services Platform は、データ サービス間の主キーと外部キーの関係を管理します。管理の方法は、以下に示すように、マルチレイヤ データ サービスのレイヤによって異なります。

AquaLogic Data Services Platform では、変更の影響が主キーや外部キーに伝播されます。

たとえば、主キー フィールドが CustID の Customer オブジェクトの配列に、2 つの Customer を挿入したとします。ここで送信を実行すると、その Customer 型を基準とした CustID を名前とし、挿入された各 Customer の新しい主キー値を値として、2 つのプロパティの配列が返されます。

キーの依存関係の管理

AquaLogic Data Services Platform は、更新プロセスの間の主キーの依存関係を管理します。 主キーを識別し、述語文内の外部キーを推量できます。 たとえば、データを結合するクエリでは、次のように値を比較します。

where customer/id = order/id

メディエータは、データ サービスの更新時に、推量されたキーと外部キーの関係に基づいてさまざまなサービスを実行します。

2 つの SDOToUpdate インスタンス (更新プラン内のデータ オブジェクト) の間に述語依存関係があり、コンテナ SDOToUpdate インスタンスが挿入または変更されて、コンテナに含まれる SDOToUpdate インスタンスが挿入または変更された場合、コンテナ SDO が更新のために送信された後に、コンテナ SDO のどの値をコンテナに含まれる SDO に移動すべきかを示すキーペア リストが特定されます。

このキーペア リストは、コンテナ SDO とコンテナに含まれる SDO のフィールドのセットに基づいています。これらは、現在の SDO が作成されたときには等しくなければならなかったものです。キーペア リストは、述語フィールドからこれらの主キーのみを特定します。

キーペアは、コンテナの主キーをコンテナに含まれるフィールドにのみマッピングします。 そうしないと、コンテナの完全な主キーがマップから特定できず、どのプロパティもマッピングされていないと判断されてしまうためです。

キーペア リストには、1 つまたは複数の項目が含まれており、これらによってコンテナ内のノード名や、マップされているコンテナ内のオブジェクトを特定します。

外部キー

SDO の分解の送信によって計算が可能な場合、外部キーの値は親キーの値と一致するように設定されます。

外部キーは、更新プランの生成時に計算されます。

トランザクション管理

メディエータに対する submit() は、トランザクションとして動作します。 submit() が成功したか失敗したかに応じて、次のどちらかを実施する必要があります。

ネストされたトランザクション

送信では、常にデータ ソースの即時更新が実行されます。 ネストされたトランザクションのコンテキスト内でデータ オブジェクトの送信が発生した場合、ネスト内に含まれるトランザクションのコミットやロールバックは、送信されたデータ オブジェクトには影響しませんが、そのトランザクションに参加するすべてのデータ ソース更新には影響します。


  ページの先頭       前  次