Object-Directory Mapping (ODM)
对象关系映射框架(例如 Hibernate 和 JPA)使开发人员能够使用标注将关系数据库表映射到 Java 对象。Spring LDAP 项目通过 LdapOperations
中的多种方法,提供了关于 LDAP 目录的类似功能:
Object-relational mapping frameworks (such as Hibernate and JPA) offer developers the ability to use annotations to map relational database tables to Java objects.
The Spring LDAP project offers a similar ability with respect to LDAP directories through a number of methods in LdapOperations
:
-
<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
包中的标注进行标注。可用的标注有:
Entity classes managed with the object mapping methods are required to be annotated with annotations from the org.springframework.ldap.odm.annotations
package. The available annotations are:
-
@Entry
: Class level annotation indicating theobjectClass
definitions to which the entity maps._ (required)_ -
@Id
: Indicates the entity DN. The field declaring this attribute must be a derivative of thejavax.naming.Name
class. (required) -
@Attribute
: Indicates the mapping of a directory attribute to the object class field. -
@DnAttribute
: Indicates the mapping of a DN attribute to the object class field. -
@Transient
: Indicates the field is not persistent and should be ignored by theOdmManager
.
必需在受管理类上声明 @Entry
和 @Id
标注。@Entry
用于指定实体映射到的对象类,以及 LDAP 条目目录根(可选)。需要声明所有为此映射字段的对象类。请注意,在创建受管理类的新条目时,仅使用已声明的对象类。
The @Entry
and @Id
annotations are required to be declared on managed classes.
@Entry
is used to specify which object classes the entity maps to and (optionally) the directory root of the LDAP entries represented by the class.
All object classes for which fields are mapped are required to be declared. Note that, when creating new entries of the managed class,
only the declared object classes are used.
为了使目录条目被视为受管理实体的匹配项,目录条目声明的所有对象类都必须由 @Entry
标注声明。例如,假设您的 LDAP 树中有具有以下对象类的条目:inetOrgPerson、organizationalPerson、person、top
。如果您仅对更改 person
对象类中定义的属性感兴趣,则可以使用 @Entry(objectClasses = { "person", "top" })
为 @Entry
标注。但是,如果您想管理 inetOrgPerson
对象类中定义的属性,则需要使用以下内容:@Entry(objectClasses = { "inetOrgPerson", "organizationalPerson", "person", "top" })
。
In order for a directory entry to be considered a match to the managed entity, all object classes declared by the directory entry must be declared by the @Entry
annotation.
For example, assume that you have entries in your LDAP tree that have the following object classes: inetOrgPerson,organizationalPerson,person,top
.
If you are interested only in changing the attributes defined in the person
object class, you can annotate your @Entry
with @Entry(objectClasses = { "person", "top" })
.
However, if you want to manage attributes defined in the inetOrgPerson
objectclass, you need to use the following: @Entry(objectClasses = { "inetOrgPerson", "organizationalPerson", "person", "top" })
.
所有实体字段都通过其字段名称映射到 LDAP 属性。其余标注(@Id
、@Attribute
、@Transient
和 @DnAttribute
)影响此映射的发生方式。
All entity fields are mapped by their field name to LDAP attributes. The remaining annotations — @Id
, @Attribute
, @Transient
, and @DnAttribute
— affect how that mapping occurs.
首先,@Id
标注将条目的专有名称映射到字段。该字段必须是 javax.naming.Name
的实例。
First, the @Id
annotation maps the distinguished name of the entry to a field. The field must be an instance of javax.naming.Name
.
其次,@Attribute
标注将实体字段映射到 LDAP 属性。当属性名称与字段名称不同时,这很方便。若要使用 @Attribute
,您必须声明该字段映射到的属性的名称。另外,您还可以通过包含 LDAP 属性的语法 OID 来保证精确匹配。最后,@Attribute
还提供类型声明,通过该类型声明,您可以指示 LDAP JNDI 提供程序是否将属性视为基于二进制还是基于字符串的。
Second, the @Attribute
annotation maps entity fields to LDAP attributes.
This is handy when the attribute name is different from the field name.
To use @Attribute
, you must declare the name of the attribute to which the field maps.
Optionally, you can also guarantee and exact match by including the syntax OID of the LDAP attribute.
Finally, @Attribute
also provides the type declaration, which lets you indicate whether the attribute is regarded as binary- or string-based by the LDAP JNDI provider.
第三,@Transient
标注指示给定的实体字段不映射到 LDAP 属性。
Third, the @Transient
annotation indicates that the given entity field does not map to an LDAP attribute.
最后,@DnAttribute
标注还可以将实体字段映射到条目的专有名称的组件。只有 String
类型的字段才能使用 @DnAttribute
标注。不支持其他类型。
Finally, the @DnAttribute
annotation additionally maps entity fields to components of an entry’s distinguished name.
Only fields of type String
can be annotated with @DnAttribute
. Other types are not supported.
当指定类中所有 |
When the |
记住所有字段都默认映射到 LDAP 属性。 |
Remember that all fields are mapped to LDAP attributes by default.
|
Execution
当所有组件都已正确配置并进行标注时,可以使用 LdapTemplate
的对象映射方法,如下所示:
When all components have been properly configured and annotated, the object mapping methods of LdapTemplate
can be used as follows:
@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 中进行了解释。
Security groups in LDAP commonly contain a multi-value attribute, where each of the values is the distinguished name
of a user in the system. The difficulties involved when handling these kinds of attributes are discussed in DirContextAdapter
and Distinguished Names as Attribute Values.
ODM 还支持 javax.naming.Name
属性值,这使得组修改变得容易,如下例所示:
ODM also has support for javax.naming.Name
attribute values, making group modifications easy, as the following example shows:
@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()
时,属性修改是通过使用专有名称相等性计算的,这意味着在计算它们是否相等时不考虑专有名称的文本格式。
When you modify group members by using setMembers
, addMember
, and removeMember
and then calling ldapTemplate.update()
,
attribute modifications are calculated by using distinguished name equality, meaning that the text formatting of
distinguished names is disregarded when figuring out whether they are equal.