オブジェクトディレクトリマッピング (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,topperson オブジェクトクラスで定義された属性の変更のみに関心がある場合は、@Entry に @Entry(objectClasses = { "person", "top" }) のアノテーションを付けることができます。ただし、inetOrgPerson objectclass で定義された属性を管理する場合は、次を使用する必要があります: @Entry(objectClasses = { "inetOrgPerson", "organizationalPerson", "person", "top" })

すべてのエンティティフィールドは、フィールド名によって LDAP 属性にマップされます。残りのアノテーション (@Id@Attribute@Transient@DnAttribute) は、マッピングがどのように行われるかに影響します。

まず、@Id アノテーションは、エントリの識別名をフィールドにマップします。フィールドは javax.naming.Name のインスタンスである必要があります。

2 番目に、@Attribute アノテーションはエンティティフィールドを LDAP 属性にマップします。これは、属性名がフィールド名と異なる場合に便利です。@Attribute を使用するには、フィールドがマップされる属性の名前を宣言する必要があります。オプションで、LDAP 属性の構文 OID を含めることで完全一致を保証することもできます。最後に、@Attribute は型宣言も提供します。これにより、属性が LDAP JNDI プロバイダーによってバイナリベースとみなされるか文字列ベースとみなされているかを示すことができます。

3 番目に、@Transient アノテーションは、指定されたエンティティフィールドが LDAP 属性にマップされないことを示します。

最後に、@DnAttribute アノテーションは、エンティティフィールドをエントリの識別名のコンポーネントにさらにマップします。@DnAttribute のアノテーションを付けることができるのは、型 String のフィールドのみです。他の型はサポートされていません。

クラス内のすべての @DnAttribute アノテーションの index 属性が指定されている場合、エントリの作成および更新時に DN を自動的に計算することもできます。更新シナリオの場合、識別名の一部である属性が変更された場合、ツリー内のエントリの移動も自動的に処理されます。
デフォルトでは、すべてのフィールドが LDAP 属性にマップされることに注意してください。@DnAttribute はこれを変更しません。つまり、フィールドに @Transient のアノテーションを付けない限り、@DnAttribute のアノテーションが付けられたフィールドも LDAP 属性にマップされます。

実行

すべてのコンポーネントが適切に構成され、アノテーションが付けられたら、LdapTemplate のオブジェクトマッピングメソッドを次のように使用できます。

例 1: 実行
@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 属性値もサポートしているため、グループの変更が容易になります。

例 2: 例 グループ表現
@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);
    }
}

setMembersaddMemberremoveMember を使用してから ldapTemplate.update() を呼び出してグループメンバーを変更すると、属性の変更は識別名の等価性を使用して計算されます。つまり、識別名が等しいかどうかを判断するときに、識別名のテキスト形式は無視されます。