クエリメソッド

通常、リポジトリに対してトリガーするデータアクセス操作のほとんどは、LDAP ディレクトリに対してクエリを実行することになります。このようなクエリを定義するには、次の例に示すように、リポジトリインターフェースでメソッドを宣言する必要があります。

PersonRepository とクエリメソッド
interface PersonRepository extends PagingAndSortingRepository<Person, String> {

    List<Person> findByLastname(String lastname);                            (1)

    List<Person> findByLastnameFirstname(String lastname, String firstname); (2)
}
1 このメソッドは、指定された lastname を持つすべての人々のクエリを示します。クエリは、And および Or と連結できる制約のメソッド名を解析することによって導出されます。メソッド名は (&(objectclass=person)(lastname=lastname)) のクエリ式になります。
2 このメソッドは、指定された lastname および firstname を持つすべての人々に対するクエリを示します。クエリはメソッド名を解析することによって導出されます。メソッド名は (&(objectclass=person)(lastname=lastname)(firstname=firstname)) というクエリ式になります。

次の表は、クエリメソッドで使用できるキーワードのサンプルを示しています。

表 1: クエリメソッドでサポートされるキーワード
キーワード サンプル 論理的な結果

LessThanEqual

findByAgeLessThanEqual(int age)

(attribute⇐age)

GreaterThanEqual

findByAgeGreaterThanEqual(int age)

(attribute>=age)

IsNotNull, NotNull

findByFirstnameNotNull()

(firstname=*)

IsNull, Null

findByFirstnameNull()

(!(firstname=*))

Like

findByFirstnameLike(String name)

(firstname=name)

NotLike, IsNotLike

findByFirstnameNotLike(String name)

(!(firstname=name*))

StartingWith

findByStartingWith(String name)

(firstname=name*)

EndingWith

findByFirstnameLike(String name)

(firstname=*name)

Containing

findByFirstnameLike(String name)

(firstname=*name*)

(No keyword)

findByFirstname(String name)

(Firstname=name)

Not

findByFirstnameNot(String name)

(!(Firstname=name))

@Query を使用する

メソッド名から派生できないカスタムクエリを使用する必要がある場合は、@Query アノテーションを使用してクエリを定義できます。クエリはそれを実行する Java メソッドに関連付けられているため、実際にクエリに渡すパラメーターをバインドできます。

次の例は、@Query アノテーションを使用して作成されたクエリを示しています。

例 1: @Query を使用して、クエリメソッドでクエリを宣言する
interface PersonRepository extends LdapRepository<Person, Long> {

  @Query("(&(employmentType=*)(!(employmentType=Hired))(mail=:emailAddress))")
  Person findEmployeeByEmailAddress(String emailAddress);

}
Spring Data は、名前付き(パラメーター名に : というプレフィックスが付く)および位置パラメーターバインディング(ゼロベースの ?0 の形式)をサポートします。読みやすくするために、名前付きパラメーターを使用することをお勧めします。また、位置パラメーターを使用すると、パラメーターの位置に関するリファクタリング時にクエリメソッドでエラーが発生しやすくなります。

パラメーターのエンコード

文字列ベースのクエリのクエリパラメーターは、RFC2254 [IETF] (英語) に従ってエンコードされます。これにより、特定の文字が望ましくないエスケープされる可能性があります。使用する LdapEncoder (Javadoc) を定義する @LdapEncode アノテーションを使用して、独自のエンコーダを指定できます。

@LdapEncode は、クエリメソッドの個々のパラメーターに適用されます。派生クエリや値式 (SpEL、プロパティプレースホルダー) には適用されません。

例 2: クエリメソッドのカスタム LdapEncoder を宣言する
interface PersonRepository extends LdapRepository<Person, Long> {

  @Query("(&(employmentType=*)(!(employmentType=Hired))(firstName=:firstName))")
  Person findEmployeeByFirstNameLike(@LdapEncode(MyLikeEncoder.class) String firstName);

}

SpEL 式の使用

Spring Data では、クエリメソッドで SpEL 式を使用できます。SpEL 式は、Spring Data の値式サポートの一部です。SpEL 式は、クエリメソッドの引数を操作したり、Bean メソッドを呼び出すために使用できます。メソッド引数には、次の例に示すように、名前またはインデックスでアクセスできます。

例 3: リポジトリクエリメソッドでの SpEL 式の使用
@Query("(&(firstName=?#{[0]})(mail=:?#{principal.emailAddress}))")
List<Person> findByFirstnameAndCurrentUserWithCustomQuery(String firstname);
SpEL 式で提供される値は、RFC2254 に従ってエスケープされません。必要に応じて、値が適切にエスケープされていることを確認する必要があります。Spring Ldap の org.springframework.ldap.support.LdapEncoder ヘルパークラスの使用を検討してください。

プロパティプレースホルダーの使用

プロパティプレースホルダー(値式を参照)を使用すると、Spring の Environment の設定プロパティに基づいてクエリを簡単にカスタマイズできます。環境や設定に基づいてカスタマイズする必要があるクエリに便利です。

例 4: リポジトリクエリメソッドでのプロパティプレースホルダーの使用
@Query("(&(firstName=?0)(stage=:?${myapp.stage:dev}))")
List<Person> findByFirstnameAndStageWithCustomQuery(String firstname);
プロパティプレースホルダーによって提供される値は、RFC2254 に従ってエスケープされません。必要に応じて、値が適切にエスケープされていることを確認してください。Spring Ldap の org.springframework.ldap.support.LdapEncoder ヘルパークラスの使用を検討してください。