5.1 スキーママッピング

次の表は、ドライバによるNovell®アイデンティティボールトブジェクトからデータベースオブジェクトへのマッピングの概要を示しています。

Table 5-1 アイデンティティボールトブジェクトからデータベースオブジェクトへのマッピング

アイデンティティボールトブジェクト

データベースオブジェクト

ツリー

スキーマ

クラス

テーブル/ビュー

属性

関連付け

プライマリキー

5.1.1 論理データベースクラス

論理データベースクラスは、データベース内でeDirectory™クラスを表現するために使用されるテーブルのセットまたはビューです。論理データベースクラスは、1つのビュー、または1つの親テーブルと子テーブル(0個以上)のセットで構成できます。

論理データベースクラス名は、親テーブルおよびビューの名前です。

5.1.2 間接同期

間接同期モデルでは、ドライバは次のようにマップします。

Table 5-2 間接同期でのマッピング

アイデンティティボールトブジェクト

データベースオブジェクト

クラス(複数)

テーブル(複数)

属性

1つのクラス

1つの親テーブル

および

0以上の子テーブル

単一値属性

親テーブルの列

複数値属性

親テーブルの列(区切られた値を保持)

または

子テーブルの列(推奨)

eDirectoryクラスから論理データベースクラスへのマッピング

次の例では、論理データベースクラスusrが、次で構成されます。

  • 1つの親テーブルusr
  • 2つの子テーブル: usr_phoneおよびusr_faxno.

論理クラスusrは、eDirectoryクラスUserにマップされます。

CREATE TABLE indirect.usr ( idu         INTEGER  NOT NULL, fname       VARCHAR2(64), lname       CHAR(64), pwdminlen   NUMBER(4), pwdexptime  DATE, disabled    NUMBER(1), username    VARCHAR2(64), loginame    VARCHAR2(64), photo       LONG RAW, manager     INTEGER, CONSTRAINT pk_usr_idu     PRIMARY KEY (idu), CONSTRAINT fk_usr_manager FOREIGN KEY (manager)         REFERENCES indirect.usr(idu) )
CREATE TABLE indirect.usr_phone ( idu      INTEGER       NOT NULL, phoneno  VARCHAR2(64)  NOT NULL, CONSTRAINT fk_phone_idu FOREIGN KEY (idu)         REFERENCES indirect.usr(idu) )
CREATE TABLE indirect.usr_fax ( idu    INTEGER       NOT NULL, faxno  VARCHAR2(64)  NOT NULL, CONSTRAINT fk_fax_idu FOREIGN KEY (idu)         REFERENCES indirect.usr(idu) )
<rule name="Schema Mapping Rule"> <attr-name-map> <class-name> <nds-name>User</nds-name> <app-name>indirect.usr</app-name> </class-name> <attr-name class-name="User"> <nds-name>Given Name</nds-name> <app-name>fname</app-name> </attr-name> <attr-name class-name="User"> <nds-name>Surname</nds-name> <app-name>lname</app-name> </attr-name> <attr-name class-name="User"> <nds-name>Password Expiration Time</nds-name> <app-name>pwdexptime</app-name> </attr-name> <attr-name class-name="User"> <nds-name>jpegPhoto</nds-name> <app-name>photo</app-name> </attr-name> <attr-name class-name="User"> <nds-name>manager</nds-name> <app-name>manager</app-name> </attr-name> <attr-name class-name="User"> <nds-name>Password Minimum Length</nds-name> <app-name>pwdminlen</app-name> </attr-name> <attr-name class-name="User"> <nds-name>Facsimile Telephone Number</nds-name> <app-name>usr_fax.faxno</app-name> </attr-name> <attr-name class-name="User"> <nds-name>Telephone Number</nds-name> <app-name>usr_phone.phoneno</app-name> </attr-name> <attr-name class-name="User"> <nds-name>Login Disabled</nds-name> <app-name>disabled</app-name> </attr-name> </attr-name-map> </rule>

親テーブル

親テーブルは、1つ以上の列を含み、明示的なプライマリキー制約を持つテーブルです。親テーブルには、ドライバが関連付けの値に含めるフィールドを認識できるように、明示的なプライマリキー制約が必要です。

CREATE TABLE indirect.usr ( idu  INTEGER  NOT NULL, -- ...CONSTRAINT pk_usr_idu PRIMARY KEY (idu) )

次の表に、indirect.usrテーブルのサンプルデータを示します。

idu

fname

lname

1

John

Doe

この行の関連付けの結果は次のようになります。

idu=1,table=usr,schema=indirect

NOTE:関連付けの値にあるデータベース識別子の大文字と小文字は、ランタイム時にデータベースメタデータから動的に決定されます。

親テーブルの列

親テーブルの列には、値を1つだけ含めることができます。したがって、単一値のeDirectory属性のマッピングに適しています。たとえば、単一値のeDirectory属性であるPassword Minimum Lengthを単一値の親テーブルの列pwdminlenにマップします。

親テーブルの列には、暗黙的にスキーマ名と親テーブル名のプリフィックスが付けられます。したがって、明示的にテーブルのプリフィックスを付ける必要はありません。たとえば、indirect.usr.fnameは、スキーママッピングの場合は、fnameと同等です。

<rule name="Schema Mapping Rule"> <attr-name-map> <class-name> <nds-name>User</nds-name> <app-name>indirect.usr</app-name> </class-name> <attr-name class-name="User"> <nds-name>Given Name</nds-name> <app-name>fname</app-name> </attr-name> </attr-name-map> </rule>

ラージバイナリおよび文字列データタイプは、通常、親テーブルの列にマップする必要があります。子テーブルの列にマップする場合は、データタイプはSQLステートメントで比較できるものである必要があります。ラージデータタイプは、通常、SQLステートメントでは比較できません。

ラージバイナリおよび文字列データタイプは、次の場合に子テーブルの列にマップできます。

  • これらのタイプでの各<remove-value>イベントが、ポリシーで、<remove-all-values> 要素に変換される。
  • <remove-value>イベントの後に<add-value>要素が続く。

子テーブル

子テーブルは、その親テーブルのプライマリキーの外部キー制約を持つテーブルです。この制約で2つのテーブルをリンクします。子テーブルの外部キーを含む列は、親テーブルのプライマリキーの列とは異なる名前にできます。

次の例は、親テーブルusrと子テーブルusr_phoneおよびusr_faxnoとの関係を示します。

CREATE TABLE indirect.usr (     idu  INTEGER  NOT NULL, -- ...CONSTRAINT pk_usr_idu  PRIMARY KEY (idu) )
CREATE TABLE indirect.usr_phone ( idu      INTEGER       NOT NULL, phoneno  VARCHAR2(64)  NOT NULL, CONSTRAINT fk_phone_idu FOREIGN KEY (idu)         REFERENCES indirect.usr(idu) )
CREATE TABLE indirect.usr_fax ( idu    INTEGER       NOT NULL, faxno  VARCHAR2(64)  NOT NULL,   CONSTRAINT fk_fax_idu FOREIGN KEY (idu)         REFERENCES indirect.usr(idu)						 )

NOTE:子テーブルではすべての列をNOT NULLで制約します。

子テーブルの最初の制約列は、親テーブルを識別します。前の例では、子テーブルusr_phoneの制約列はiduです。この列の目的は、テーブルusr_phoneおよびusrを関係付けることだけです。制約列には有用な情報は含まれていないので、発行トリガおよびスキーママッピングポリシーからは除外します。

重要な列は制約のない列です。これは、単一の複数値属性を示します。前の例で、制約のない列はphonenoおよびfaxnoです。制約のない列は複数の値を保持できるので、複数値のeDirectory属性のマッピングに適しています(たとえば、複数値のeDirectory属性であるTelephone Numberからusrphone.phonenoへのマッピング)。

次の表に、indirect.usr_phoneのサンプルデータを示します。

Table 5-3 サンプルデータ

idu

phoneno

1

111-1111

1

222-2222

親テーブルの列と同じように、子テーブルの列にも暗黙的にスキーマ名のプリフィックスが付けられています。ただし、親テーブルの列とは異なり、子テーブルの列には、明示的に子テーブル名のプリフィックスを付ける必要があります(たとえば、usr_phone.phoneno)。そうしないと、ドライバは、子テーブルの列usr_phone.phonenoではなく、phoneno列(親テーブルの列)を暗黙的にusr.phonenoと解釈します。

<rule name="Schema Mapping Rule"> <attr-name-map> <class-name> <nds-name>User</nds-name> <app-name>indirect.usr</app-name> </class-name> <attr-name class-name="User"> <nds-name>Facsimile Telephone Number</nds-name> <app-name>usr_fax.faxno</app-name> </attr-name> <attr-name class-name="User"> <nds-name>Telephone Number</nds-name> <app-name>usr_phone.phoneno</app-name> </attr-name> </attr-name-map> </rule>

NOTE:個々の複数値のeDirectory属性を異なる子テーブルにマップします。

参照属性

外部キー制約を使用して、データベースの参照の包含を表現できます。参照属性は、論理データベースクラス内の列であり、同一論理データベースクラスまたは他の論理データベースクラス内の親テーブルのプライマリキー値を参照します。

単一値の参照属性

親テーブルの単一値の列を使用して、2つの親テーブルを関係付けることができます。この列は、他方の親テーブルのプライマリキーをポイントする外部キー制約を含む必要があります。次の例では、単一の親テーブルusrをそれ自体に関係付けます。

CREATE TABLE indirect.usr ( idu      INTEGER  NOT NULL, -- ... manager  INTEGER, CONSTRAINT pk_usr_idu     PRIMARY KEY (idu), CONSTRAINT fk_usr_manager FOREIGN KEY (manager)         REFERENCES indirect.usr(idu) )

NOTE:単一値の参照列は、NULL可能である必要があります。

<rule name="Schema Mapping Rule"> <attr-name-map> <class-name> <nds-name>User</nds-name> <app-name>indirect.usr</app-name> </class-name> <attr-name class-name="User"> <nds-name>manager</nds-name> <app-name>manager</app-name> </attr-name> </attr-name-map> </rule>

この例は、ユーザごとにマネージャ(ユーザの1人)を1人だけ指定できると解釈されます。

複数値の参照属性

共通の子テーブルを使用して、2つの親テーブルを関係付けることができます。この子テーブルには、他方の親テーブルのプライマリキーをポイントする外部キーの制約がある列を含める必要があります。次の例は、親テーブルusrおよびgrpを、共通の子テーブルmemberを通じて関係付けます。

CREATE TABLE indirect.usr ( idu  INTEGER  NOT NULL, -- ...CONSTRAINT pk_usr_idu PRIMARY KEY (idu) )
CREATE TABLE indirect.grp ( idg  INTEGER  NOT NULL, -- ...CONSTRAINT pk_grp_idg PRIMARY KEY (idg) )
CREATE TABLE indirect.grp_member ( idg  INTEGER  NOT NULL, idu  INTEGER  NOT NULL, CONSTRAINT fk_member_idg FOREIGN KEY (idg)      REFERENCES indirect.grp(idg),    CONSTRAINT fk_member_idu FOREIGN KEY (idu)      REFERENCES indirect.usr(idu) )

NOTE:子テーブルのすべての列にNOT NULL制約があります。

<rule name="Schema Mapping Rule"> <attr-name-map> <class-name> <nds-name>Group</nds-name> <app-name>indirect.grp</app-name> </class-name> <class-name> <nds-name>User</nds-name> <app-name>indirect.usr</app-name> </class-name> <attr-name class-name="Group"> <nds-name>Member</nds-name> <app-name>grp_member.idu</app-name> </attr-name> </attr-name-map> </rule>

子テーブルの1つ目の制約列は、子テーブルgrp_memberが属する論理データベースクラスを指定します。前の例では、grp_memberは、論理データベースクラスgrpの一部であると見なされます。grp_memberは、grpの適切な子であることが示されます。子テーブルの2つ目の制約列は、複数値の参照属性です。

次の例では、grp_memberusrクラスに含まれるように、制約列の順序が逆になっています。より正確に関係を反映するように、grp_memberテーブルの名前がusr_mbr_ofに変更されています。

CREATE TABLE indirect.usr ( idu  INTEGER  NOT NULL, -- ...CONSTRAINT pk_usr_idu PRIMARY KEY (idu) )
CREATE TABLE indirect.grp ( idg  INTEGER  NOT NULL, -- ...CONSTRAINT pk_grp_idg PRIMARY KEY (idg) )
CREATE TABLE indirect.usr_mbr_of ( idu  INTEGER  NOT NULL, idg  INTEGER  NOT NULL, CONSTRAINT fk_mbr_of_idu FOREIGN KEY (idu)         REFERENCES indirect.usr(idu) ON DELETE CASCADE,    CONSTRAINT fk_mbr_of_idg FOREIGN KEY (idg)         REFERENCES indirect.grp(idg) ON DELETE CASCADE )
<rule name="Schema Mapping Rule"> <attr-name-map> <class-name> <nds-name>Group</nds-name> <app-name>indirect.grp</app-name> </class-name> <class-name> <nds-name>User</nds-name> <app-name>indirect.usr</app-name> </class-name> <attr-name class-name="User"> <nds-name>Group Membership</nds-name> <app-name>usr_mbr_of.idg</app-name> </attr-name> </attr-name-map> </rule>

列位置を認識しないデータベース(DB2/AS400など)では、順序は、文字列または16進の値で列名を並べ替えることによって決まります。詳細については、列名を並べ替える基準を参照してください。

一般に、双方向で複数値の参照属性だけを、両方のクラスではなくどちらか一方のクラスの一部として同期する必要があります。両方のクラスで参照属性を同期する場合は、2つ(各クラスに1つずつ)の子テーブルを作成します。たとえば、eDirectory属性であるGroup MembershipおよびMemberを同期する場合は、2つの子テーブルを作成します。

実際には、UserクラスおよびGroupクラスを同期するときに、グループクラスのMember属性の代わりに、ユーザクラスのGroup Membership属性を同期することをお勧めします。通常はユーザのグループメンバーシップを同期する方が、グループのすべてのメンバーシップを同期するよりも効率的です。

5.1.3 直接同期

直接同期モデルでは、ドライバは次のようにマップします。

Table 5-4 直接同期でのマッピング

アイデンティティボールトブジェクト

データベースオブジェクト

クラス(複数)

ビュー(複数)

属性(複数)

ビューの列(複数)

クラス(単数)

ビュー(単数)

単一値属性

ビューの列(単数)

複数値属性

ビューの列(単数)

ビューの更新機能は、データベースによってさまざまです。ほとんどのデータベースでは、ビューが1つだけのベーステーブルで構成されている(複数のテーブルを連結しないビュー)場合は更新できます。ビューが完全に読み取り専用である場合は、購読には使用できません。一部のデータベースでは、instead-of-triggerでビューに更新ロジックを定義できます。これによって、ビューで複数のベーステーブルを連結できます。更新も引き続き可能です。

instead-of-triggerをサポートするデータベースのリストについては、データベースの機能を参照してください。instead-of-triggerロジックは、埋め込みSQLを使用するデータベース機能に関係なく、シミュレートできます。仮想トリガを参照してください。

ビューの列のメタ識別子

ビューは論理テーブルです。テーブルとは異なり、ビューは物理的にはデータベースに存在しません。このため、通常、ビューは、従来からのプライマリキー/外部キー制約を保持できません。これらの構成体をシミュレートするために、JDBC用ドライバは、制約およびその他のメタデータをビューの列名に埋め込みます。これらの制約と従来の制約は、前者がデータベースレベルで強制されない点が異なります。これらは、アプリケーションレベルの構成体です。

たとえば、関連付けの値を作成するときに使用するフィールドをドライバに明確に示すには、プライマリキー制約を親テーブルに配置します。ビューでは、この結果、1つ以上の列名にプリフィックスpk_ (大文字と小文字の区別なし)が付けられます。

次の表は、ビューの列名に埋め込むことができる制約プリフィックスのリストです。

Table 5-5 制約プリフィックス

制約プリフィックス(大文字と小文字の区別なし)

解釈

pk_

プライマリキー

fk_

外部キー

sv_

単一値

mv_

複数値

次のビューの例は、これらの制約プリフィックスをすべて含んでいます。

CREATE VIEW direct.view_usr ( pk_idu,            -- primary key column; implicitly single-valued sv_fname,          -- single-valued column mv_phoneno,        -- multi-valued column fk__idu__manager,  -- self-referential foreign key column; refers                        --   to primary key column idu in view_usr;                        --   implicitly single-valued fk_mv__idg__mbr_of -- extra-referential foreign key column; refers                        --   to primary key column idg in view_grp;                        --   multi-valued ) AS -- ...
CREATE VIEW direct.view_grp ( pk_idg,            -- primary key column; implicitly single-valued fk_mv__idu__mbr    -- extra-referential foreign key column; refers --   to primary key column idu in view_usr; --   multi-valued ) AS -- ...

BNF

ビューの列のメタ識別子をBNF (バッカス表記)で表記すると次のようになります。

<view-column-name> ::= [<meta-info>] <column-name>

<column-name> ::= <legal-unquoted-database-identifier> <meta-info> ::= <referential> | <non-referential>

<non-referential> ::= [<single-value> | <multiple-value>]

<single-value> ::= "sv_"

<multiple-value> ::= "mv_"

<referential> ::= <primary-key> | <foreign-key>

<primary-key> ::= "pk_" [<single-value>] [<column-group-id>] [<referenced-column-name>]
<column-group-id> ::= <non-negative-integer> "_"

<referenced-column-name> ::= "_" <column-name> "__"

<foreign-key> ::= "fk_" [<non-referential>] [<column-group-id>] <referenced-column-name>

標準形式

デフォルトでは、すべてのビューの列名は単一値です。したがって、ビューの列名でsv_プリフィックスを明示的に指定するのは冗長です。たとえば、sv_fnamefnameは、形式は異なりますが等価であり、同じ列名を示します。

また、プライマリキー列の名前は、暗黙的にそれ自体を参照します。したがって、参照列名を指定するのは冗長です。たとえば、pk_iduは、pk__idu__iduと同等です。

JDBC用ドライバは、ビューのメタ識別子の2つの標準形式を使用します。

  • データベースのネイティブ形式

    データベースのネイティブ形式は、データベースで宣言されているとおりの列名です。この形式は、通常、スキーママッピング形式よりもさらに詳細で、必要なメタ情報をすべて含みます。

  • スキーママッピング形式

    スキーママッピング形式は、ドライバがアプリケーションスキーマを返すときに返されます。この形式は、データベースのネイティブ形式よりも簡潔です。データベースのネイティブ形式に含まれるメタ情報のほとんどは、識別子ではなくXDS XMLで表現されるからです。

    スキーママッピング形式で保持されるメタ情報は、参照プリフィックスpk_およびfk_だけです。この制限によって、後方互換性が確実になります。

次の表は、各形式の例です。

Table 5-6 ビューのメタ識別子の標準形式の例

データベースのネイティブ形式

スキーママッピング形式

pk_idu

pk_idu

sv_fname

fname

mv_phoneno

phoneno

fk_mv__idg__mbr_of

fk_mbr_of

同等の形式

ビュー内で、メタ情報を含まない列名は、その「有効」な名前と呼ばれます。これは、ディレクトリオブジェクトの「有効な」権利と同様です。ドライバの場合、ビューの列名が同等かどうかは、デフォルトで、メタ情報に関係なく判断されます。たとえば、pk_iduは、iduと同等であり、fk_mv__idg__mbr_ofは、mbr_ofと同等です。ランタイム時に、さまざまな形式のビューのメタ列識別子をドライバに渡すことができます。後方互換性を維持するためには、メタ情報を有効なビューの列名として扱うことができます。Enable Meta-Identifier Support? (メタ識別子のサポートを有効にしますか?)を参照してください。

プライマリキー列

プライマリキー列の名前は、同期スキーマ内のすべてのビューで一意である必要があります。

スキーママッピング

ビューとその列のスキーママッピングの規則は、親テーブルとその列で使用される規則と同じです。

5.1.4 プライマリキー列の同期

データベースがプライマリキー列の信頼されるソースである場合は、通常、発行者および購読者のフィルタ、スキーママッピングポリシー、および発行トリガで、列を省略します。

アイデンティティボールトがプライマリキー列の信頼されるソースである場合は、発行者フィルタおよびスキーママッピングポリシーには列を含めますが、購読者フィルタおよび発行トリガでは列を省略します。また、プライマリキーとして、CNではなくGUIDを使用することをお勧めします。CNは、複数値属性であり、変更されることがあります。GUIDは、単一値であり、変更されません。

5.1.5 複数のクラスの同期

複数のeDirectoryクラスを同期する場合は、各クラスを異なる親テーブルまたはビューに同期させます。各論理データベースクラスには、一意のプライマリキー列名が必要です。発行者チャネルは、この共通の列名を使用して、単一の論理データベースクラスに関連するイベントログテーブルのすべての列を識別します。次の例では、論理データベースクラスusrおよびgrpの両方に、一意のプライマリキー列名があります。

CREATE TABLE usr ( idu   INTEGER	     NOT NULL, lname VARCHAR2(64)  NOT NULL, --...CONSTRAINT pk_usr_idu PRIMARY KEY(idu) );
CREATE TABLE grp ( idg  INTEGER  NOT NULL, --...CONSTRAINT pk_grp_idg PRIMARY KEY(idg) );

5.1.6 複数値属性から単一値データベースフィールドへのマッピング

デフォルトで、ドライバは、親テーブルの列またはビューの列にマップされるeDirectory属性はすべて単一値を持つと見なします。ドライバはeDirectoryスキーマを認識しないので、eDirectory属性が単一値と複数値のどちらを持っているかを判断する方法がありません。したがって、複数値と単一値の属性マッピングは、まったく同じように処理されます。

ドライバは、単一値の親テーブルまたはビューの列に関して、Most Recently Touched (MRT)アルゴリズムを実装します。MRTアルゴリズムを使用すると、最後に追加された属性値、または最後に削除された属性値がデータベースに保存されます。このアルゴリズムは、該当する属性値が単一値を持つ場合は適切です。

属性値が複数値を持つ場合は、好ましくない結果につながります。複数値属性から値が削除される場合、それがマップされているデータベースフィールドは、NULLに設定され、別の値が追加されるまでNULLのままになります。この望ましくない動作の解決方法として、単一値の属性だけが親テーブルまたはビューの列にマップされるようにeDirectoryスキーマを拡張することをお勧めします。

他にも、次のような解決法があります。

  • 間接同期の場合は、個々の複数値属性をそれ自体の子テーブルにマップします。
  • 直接および間接のどちらの同期でも、ポリシーを使用して、複数値を区切ってからテーブルまたはビューの列に挿入します。
  • com.novell.nds.indirect.driver.jdbc.util.MappingPolicyクラスで提供されるメソッドを使用して、スタイルシートのレプリカポリシーごとに最初または最後の値を実装します。first-value-per-replica (FPR)ポリシーでは、eDirectoryレプリカの最初の属性値が常に同期されます。last-value-per-replica (LPR)ポリシーでは、レプリカの最後の属性値が常に同期されます。 グローバル環境設定値を使用することによって、サンプルのドライバ環境設定を、FPRまたはLPRマッピングポリシーを使用するように設定できます。複数値から単一値属性へのマッピングポリシーは、購読者コマンド変換ポリシーコンテナに含まれています。サンプルドライバ環境設定では、複数値のeDirectory属性であるGiven NameおよびSurnameを単一値の列fnameおよびlnameにそれぞれマップします。