|
A common way to model relationships between LDAP entries is to put the LDAP distinguished name of the referenced LDAP
entry to an attribute of the referencing LDAP entry. For example entries with object class groupOfNames use the attribute
member
which contains distinguished names of the group members.
We just describe 1-N relationship mapping here and distinguish between unidirectional and bidirectional relationships.
The metadata for 1-1, N-1 and M-N relationship mapping looks identical, the only difference is whether single-valued or
multi-valued attributes are used in LDAP to store the relationships.
We use the following example LDAP tree and Java classes:
dc=example,dc=com public class Department {
| String name;
|-- ou=Departments Set<Employee> employees;
| |-- cn=Sales }
| |-- cn=Engineering
| |-- ... public class Employee {
| String firstName;
|-- ou=Employees String lastName;
| |-- cn=Bugs Bunny String fullName;
| |-- cn=Daffy Duck }
| |-- cn=Speedy Gonzales
| |-- ...
We have a flat LDAP tree with one container for all the departments and one container for all the employees.
We have two Java classes,
Department
and
Employee
. The
Department
class contains a
Collection of type
Employee
. The
Employee
knows nothing about the
Department
it
belongs to.
There are 2 ways that we can persist this relationship in LDAP because the DN reference could be stored at the one
or at the other LDAP entry.
The obious way is to store the reference at the owner object side, in our case at the department entry. This is possible since
LDAP allows multi-valued attributes. The example department entry looks like this:
dn: cn=Sales,ou=Departments,dc=example,dc=com
objectClass: top
objectClass: groupOfNames
cn: Sales
member: cn=Bugs Bunny,ou=Employees,dc=example,dc=com
member: cn=Daffy Duck,ou=Employees,dc=example,dc=com
Our JDO metadata looks like this:
<jdo>
<package name="com.example">
<class name="Department" table="ou=Departments,dc=example,dc=com" schema="top,groupOfNames">
<field name="name" primary-key="true" column="cn" />
<field name="employees" column="member">
<extension vendor-name="datanucleus" key="empty-value" value="uid=admin,ou=system"/>
</field>
</class>
<class name="Employee" table="ou=Employees,dc=example,dc=com" schema="top,person,organizationalPerson,inetOrgPerson">
<field name="fullName" primary-key="true column="cn" />
<field name="firstName" column="givenName" />
<field name="lastName" column="sn" />
</class>
</package>
</jdo>
So we define that the attribute
member
should be used to persist the relationship of field
employees
.
Note: We use the extension
empty-value
here. The groupOfNames object class defines the member
attribute as mandatory attribute. In case where you remove all the employees from a department would
delete all member attributes which isn't allowed. In that case DataNucleus adds this empty value
to the member attribute. This value is also filtered when DataNucleus reads the object from LDAP.
Another possible way is to store the reference at the non-owner object side, in our case at the employee entry.
The example employee entry looks like this:
dn: cn=Bugs Bunny,ou=Employees,dc=example,dc=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
cn: Bugs Bunny
givenName: Bugs
sn: Bunny
departmentNumber: cn=Sales,ou=Departments,dc=example,dc=com
Our JDO metadata looks like this:
<jdo>
<package name="com.example">
<class name="Department" table="ou=Departments,dc=example,dc=com" schema="top,groupOfNames">
<field name="name" primary-key="true" column="cn" />
<field name="employees">
<element column="departmentNumber" />
</field>
</class>
<class name="Employee" table="ou=Employees,dc=example,dc=com" schema="top,person,organizationalPerson,inetOrgPerson">
<field name="fullName" primary-key="true column="cn" />
<field name="firstName" column="givenName" />
<field name="lastName" column="sn" />
</class>
</package>
</jdo>
We need to define the relationship at the department metadata because the employee doesn't know about
the department it belongs to.
With the
<element>
tag we specify that the relationship should be persisted at the other
side, the
column
attribute defines the LDAP attribute to use.
In this case the relationship is persisted in the
departmentNumber
attribute at the employee entry.
We use the following example LDAP tree and Java classes:
dc=example,dc=com public class Department {
| String name;
|-- ou=Departments Set<Employee> employees;
| |-- cn=Sales }
| |-- cn=Engineering
| |-- ... public class Employee {
| String firstName;
|-- ou=Employees String lastName;
| |-- cn=Bugs Bunny String fullName;
| |-- cn=Daffy Duck Department department;
| |-- cn=Speedy Gonzales }
| |-- ...
We have a flat LDAP tree with one container for all the departments and one container for all the employees.
We have two Java classes,
Department
and
Employee
. The
Department
class contains a
Collection of type
Employee
. Now each
Employee
has a reference to its
Department
.
It is possible to persist this relationship on both sides.
dn: cn=Sales,ou=Departments,dc=example,dc=com
objectClass: top
objectClass: groupOfNames
cn: Sales
member: cn=Bugs Bunny,ou=Employees,dc=example,dc=com
member: cn=Daffy Duck,ou=Employees,dc=example,dc=com
<jdo>
<package name="com.example">
<class name="Department" table="ou=Departments,dc=example,dc=com" schema="top,groupOfNames">
<field name="name" primary-key="true" column="cn" />
<field name="employees" column="member">
<extension vendor-name="datanucleus" key="empty-value" value="uid=admin,ou=system"/>
</field>
</class>
<class name="Employee" table="ou=Employees,dc=example,dc=com" schema="top,person,organizationalPerson,inetOrgPerson">
<field name="fullName" primary-key="true column="cn" />
<field name="firstName" column="givenName" />
<field name="lastName" column="sn" />
<field name="department" mapped-by="employees" />
</class>
</package>
</jdo>
In this case we store the relation at the department entry side in a multi-valued attribute
member
.
Now the employee metadata contains a department field that is
mapped-by
the employees field
of department.
Note: We use the extension
empty-value
here. The groupOfNames object class defines the member
attribute as mandatory attribute. In case where you remove all the employees from a department would
delete all member attributes which isn't allowed. In that case DataNucleus adds this empty value
to the member attribute. This value is also filtered when DataNucleus reads the object from LDAP.
|
|