下表显示了驱动程序将 Novell® Identity Vault 对象映射到数据库对象的高级视图。
逻辑数据库类是用于表示数据库中的 eDirectory™ 类的表集或视图。 逻辑数据库类可以由单个视图组成,也可以由一个父表以及零个或多个子表组成。
逻辑数据库类的名称是父表或视图的名称。
在间接同步模式下,驱动程序将映射下列项目:
Table 5-2 在间接同步模式下进行映射
|
Identity Vault 对象 |
数据库对象 |
|---|---|
|
类 |
表 |
|
特性 |
列 |
|
1 个类 |
1 个父表 和 0 个或多个子表 |
|
单值特性 |
父表列 |
|
多值特性 |
父表列(保存定界值) 或者 子表列(优先) |
在以下示例中,逻辑数据库类 usr 包括以下项目:
逻辑类 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>
父表具有包含一个或多个列的显式主键约束。 父表中必需显式主键约束,以便驱动程序知道关联值中要包含哪些字段。
CREATE TABLE indirect.usr ( idu INTEGER NOT NULL, -- ... CONSTRAINT pk_usr_idu PRIMARY KEY (idu) )
下表包含表 indirect.usr 的样本数据。
为该行生成的关联为
idu=1,table=usr,schema=indirect
NOTE:关联值中的数据库标识符的大小写由数据库元数据在运行时动态确定。
父表列只能包含一个值。 因此,它们非常适用于映射 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 语句中比较大型数据类型。
如果发生以下情况,则可以将大型二进制数据类型和字符串数据类型映射到子表列:
子表是其父表的主键上具有外键约束的表,两个表通过外键约束链接在一起。 构成子表外键的列的名称可以与父表主键中的列名不同。
以下示例显示父表 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 的样本数据。
与父表列一样,可以对子表列隐式添加纲要前缀。 但是,与父表列不同,必须使用子表名对子表列名显式添加前缀(例如 usr_phone.phoneno)。 否则,驱动程序会将列 phoneno(父表列)隐式解释为 usr.phoneno,而不是解释为子表列 usr_phone.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 多值特性映射到不同的子表。
可以使用外键约束表示数据库中的参照包容。 参照特性是逻辑数据库类中的列,这些列参照同一个逻辑数据库类中的父表的主键列,或参照其它逻辑数据库类的对应项。
可通过单值父表列将两个父表相关联。 该列必须具有指向其它父表主键的外键约束。 以下示例将单个父表 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:单值参照列应该可以为空。
<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>
以上示例的解释是每个用户只能有一个经理,并且该经理本人是用户。
可通过一个通用子表将两个父表相关联。 该子表有一个列受外键约束,该外键指向其它父表的主键。 以下示例通过一个通用子表 member 将 usr 和 grp 这两个父表相关联。
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>
子表中的第一个受限列确定子表 grp_member 所属的逻辑数据库类。 在以上示例中,grp_member 被视为逻辑数据库类 grp 的一部分。grp_member 被视为 grp 的专有子项。 子表中的第二个约束列为多值参照特性。
在以下示例中,约束列的顺序已颠倒,以便 grp_member 成为 usr 类的一部分。 为了更准确地反映关系,已将表 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)中,通过按字符串或十六进制值对列名排序来确定顺序。有关其它信息,请参见Sort Column Names By。
一般而言,只需要同步作为一个类或另一个类(而不是两个类)的一部分的双向多值参照特性。 如果需要同步两个类的参照特性,请为每个类构造一个子表,共两个子表。 例如,如果需要同步 eDirectory 特性 Group Membership 和 Member,则需要两个子表。
实际上,如果您要同步 User 和 Group 类,我们建议您同步 User 类的 Group Membership 特性,而不是同步 Group 类的 Member 特性。 同步用户的组成员资格通常比同步组的所有成员更有效。
在直接同步模式下,驱动程序将映射下列项目:
视图的更新功能随数据库的不同而不同。 如果视图由单个基表组成,则大多数数据库允许更新这些视图。 (也就是说,这些视图没有连接多个表。) 如果视图是绝对只读的,则不能将它们用于订购。 某些数据库允许在 Instead of 触发器中的视图上定义更新逻辑,这样,视图便可以与多个基表连接,因此仍可更新。
有关支持 Instead of 触发器的数据库的列表,请参见数据库功能。 无论使用嵌入式 SQL 的数据库功能如何,均可以模拟 Instead of 触发器逻辑。请参见 虚拟触发器。
视图是一个逻辑表。 与表不同的是,视图并不在数据库中以物理形式存在。 因此,通常不能对视图设置传统的主键/外键约束。 为模拟这些构造,JDBC 的驱动程序将在视图列名中嵌入约束和其它元数据。 这些约束与传统约束之间的差别在于,前者不是在数据库级别实施的, 它们是应用程序级别的构造。
例如,要使驱动程序确定在构造关联值时使用哪些字段,可以在父表上设置主键约束。 对视图执行此操作的结果是给一个或多个列名添加前缀 pk_(不区分大小写)。
下表列出了可以嵌入到视图列名中的约束前缀。
以下示例视图包含所有这些约束前缀:
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(巴科斯-诺尔范式)表示法:
<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_fname 和 fname 是同一列名的等效格式。
同时,主键列名将隐式参照其自身。 因此,指定被参照列名是多余的操作。 例如,pk_idu 等效于 pk__idu__idu。
Driver for JDBC 对视图元标识符使用两种规范化格式:
数据库自带格式是在数据库中声明的列名。 该格式通常比纲要映射格式冗长得多,并且包含所有必需的元信息。
驱动程序返回应用程序纲要时,将返回纲要映射格式。 该格式比数据库自带格式精简得多,因为数据库自带格式中包含的大量元信息以 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?。
同步纲要中的所有视图的主键列名必须唯一。
视图和视图列的纲要映射约定相当于父表和父表列使用的纲要映射约定。
如果数据库是主键列的权威来源,则一般会省略《发布者》和《订购者》过滤器、纲要映射策略和发布触发器中的列。
如果 Identity Vault 是主键列的权威来源,则会在《订购者》过滤器和纲要映射策略中包含列,但是会省略《发布者》过滤器和发布触发器中的列。 同时,建议将 GUID 而不是 CN 用作主键。 CN 是多值特性,并可以更改。 GUID 是单值,并且是静态的。
同步多个 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) );
默认情况下,驱动程序假定映射到父表列或视图列的所有 eDirectory 特性都具有单个值。 由于驱动程序不了解 eDirectory 纲要,因此它无法知道 eDirectory 特性是具有单个值还是具有多个值。 因此,将以相同的方式处理多值特性映射和单值特性映射。
针对单值父表或视图列,驱动程序将执行 Most Recently Touched (MRT) 算法。 MRT 算法可确保将最近添加或删除的特性值储存在数据库中。 如果有问题的特性具有单个值,则此算法的功能是足够的。
如果特性具有多个值,则此算法会导致某些不希望出现的结果。 如果从多值特性中删除了某个值,则该值映射到的数据库字段将设置为 NULL,并且在添加另一个值之前,一直保持为 NULL。 这种不希望出现的行为的优先解决方案是扩展 eDirectory 纲要,以便只将单值特性映射到父表或视图列。
其它解决方案包括: