Object-Directory Mapping (ODM)
对象关系映射框架(例如 Hibernate 和 JPA)使开发人员能够使用标注将关系数据库表映射到 Java 对象。Spring LDAP 项目通过 LdapOperations
中的多种方法,提供了关于 LDAP 目录的类似功能:
-
<T> T findByDn(Name dn, Class<T> clazz)
-
<T> T findOne(LdapQuery query, Class<T> clazz)
-
<T> List<T> find(LdapQuery query, Class<T> clazz)
-
<T> List<T> findAll(Class<T> clazz)
-
<T> List<T> findAll(Name base, SearchControls searchControls, Class<T> clazz)
-
<T> List<T> findAll(Name base, Filter filter, SearchControls searchControls, Class<T> clazz)
-
void create(Object entry)
-
void update(Object entry)
-
void delete(Object entry)
Annotations
使用对象映射方法管理的实体类需要使用 org.springframework.ldap.odm.annotations
包中的标注进行标注。可用的标注有:
-
@Entry
:类级别的注解,用于表示实体所映射的 `objectClass`定义。(必需) -
@Id
:表示实体 DN。声明此属性的字段必须是 `javax.naming.Name`类的一个派生。 (必需) -
@Attribute
:表示将目录属性映射到对象类字段。 -
@DnAttribute
:表示将 DN 属性映射到对象类字段。 -
@Transient
:表示字段不持久,应被 `OdmManager`忽略。
必需在受管理类上声明 @Entry
和 @Id
标注。@Entry
用于指定实体映射到的对象类,以及 LDAP 条目目录根(可选)。需要声明所有为此映射字段的对象类。请注意,在创建受管理类的新条目时,仅使用已声明的对象类。
为了使目录条目被视为受管理实体的匹配项,目录条目声明的所有对象类都必须由 @Entry
标注声明。例如,假设您的 LDAP 树中有具有以下对象类的条目:inetOrgPerson、organizationalPerson、person、top
。如果您仅对更改 person
对象类中定义的属性感兴趣,则可以使用 @Entry(objectClasses = { "person", "top" })
为 @Entry
标注。但是,如果您想管理 inetOrgPerson
对象类中定义的属性,则需要使用以下内容:@Entry(objectClasses = { "inetOrgPerson", "organizationalPerson", "person", "top" })
。
所有实体字段都通过其字段名称映射到 LDAP 属性。其余标注(@Id
、@Attribute
、@Transient
和 @DnAttribute
)影响此映射的发生方式。
首先,@Id
标注将条目的专有名称映射到字段。该字段必须是 javax.naming.Name
的实例。
其次,@Attribute
标注将实体字段映射到 LDAP 属性。当属性名称与字段名称不同时,这很方便。若要使用 @Attribute
,您必须声明该字段映射到的属性的名称。另外,您还可以通过包含 LDAP 属性的语法 OID 来保证精确匹配。最后,@Attribute
还提供类型声明,通过该类型声明,您可以指示 LDAP JNDI 提供程序是否将属性视为基于二进制还是基于字符串的。
第三,@Transient
标注指示给定的实体字段不映射到 LDAP 属性。
最后,@DnAttribute
标注还可以将实体字段映射到条目的专有名称的组件。只有 String
类型的字段才能使用 @DnAttribute
标注。不支持其他类型。
当指定类中所有 |
记住所有字段都默认映射到 LDAP 属性。 |
Execution
当所有组件都已正确配置并进行标注时,可以使用 LdapTemplate
的对象映射方法,如下所示:
@Entry(objectClasses = { "person", "top" }, base="ou=someOu")
public class Person {
@Id
private Name dn;
@Attribute(name="cn")
@DnAttribute(value="cn", index=1)
private String fullName;
// No @Attribute annotation means this will be bound to the LDAP attribute
// with the same value
private String description;
@DnAttribute(value="ou", index=0)
@Transient
private String company;
@Transient
private String someUnmappedField;
// ...more attributes below
}
public class OdmPersonRepo {
@Autowired
private LdapTemplate ldapTemplate;
public Person create(Person person) {
ldapTemplate.create(person);
return person;
}
public Person findByUid(String uid) {
return ldapTemplate.findOne(query().where("uid").is(uid), Person.class);
}
public void update(Person person) {
ldapTemplate.update(person);
}
public void delete(Person person) {
ldapTemplate.delete(person);
}
public List<Person> findAll() {
return ldapTemplate.findAll(Person.class);
}
public List<Person> findByLastName(String lastName) {
return ldapTemplate.find(query().where("sn").is(lastName), Person.class);
}
public Stream<Person> streamFindByLastName(String lastName) {
return ldapTemplate.findStream(query().where("sn").is(lastName), Person.class);
}
}
ODM and Distinguished Names as Attribute Values
LDAP 中的安全组通常包含一个多值属性,其中每个值都是系统中用户的 distinguished name。有关处理此类属性时的困难已在 xref:dirobjectfactory.adoc#dns-as-attribute-values[DirContextAdapter
和 Distinguished Names as Attribute Values 中进行了解释。
ODM 还支持 javax.naming.Name
属性值,这使得组修改变得容易,如下例所示:
@Entry(objectClasses = {"top", "groupOfUniqueNames"}, base = "cn=groups")
public class Group {
@Id
private Name dn;
@Attribute(name="cn")
@DnAttribute("cn")
private String name;
@Attribute(name="uniqueMember")
private Set<Name> members;
public Name getDn() {
return dn;
}
public void setDn(Name dn) {
this.dn = dn;
}
public Set<Name> getMembers() {
return members;
}
public void setMembers(Set<Name> members) {
this.members = members;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void addMember(Name member) {
members.add(member);
}
public void removeMember(Name member) {
members.remove(member);
}
}
当您使用 setMembers
、addMember
和 removeMember
修改组成员,然后调用 ldapTemplate.update()
时,属性修改是通过使用专有名称相等性计算的,这意味着在计算它们是否相等时不考虑专有名称的文本格式。