对象-目录映射 (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)
注解
使用对象映射方法管理的实体类需要使用 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
注释。不支持其他类型。
当类中所有 @DnAttribute 注解的 index 属性都被指定时,在创建和更新条目时也可以自动计算 DN。对于更新场景,这也会自动处理将条目移动到树中,如果作为可分辨名称一部分的属性发生了更改。
|
请记住,默认情况下所有字段都映射到 LDAP 属性。@DnAttribute 不会改变这一点;换句话说,用 @DnAttribute 注释的字段也将映射到 LDAP 属性,除非您还用 @Transient 注释该字段。
|
执行
当所有组件都已正确配置和注释后,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 和作为属性值的识别名称
LDAP 中的安全组通常包含一个多值属性,其中每个值都是系统中用户的识别名称。在处理这些类型的属性时遇到的困难在 DirContextAdapter
和作为属性值的识别名称 中讨论。
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()
时,属性修改是通过使用识别名称相等性来计算的,这意味着在确定识别名称是否相等时,会忽略识别名称的文本格式。