查询方法
你在仓库上触发的大多数数据访问操作通常都会导致对 LDAP 目录执行查询。 定义这样的查询只需在仓库接口中声明一个方法,如下例所示:
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))。 |
下表提供了可在查询方法中使用的关键词示例:
| 关键字 | 示例 | 逻辑结果 |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
使用@Query
如果需要使用无法从方法名派生的自定义查询,可以使用 @Query 注解来定义该查询。
由于查询与执行它们的 Java 方法相关联,因此实际上可以将参数绑定并传递给查询。
以下示例展示了一个使用 @Query 注解创建的查询:
@Query 声明查询interface PersonRepository extends LdapRepository<Person, Long> {
@Query("(&(employmentType=*)(!(employmentType=Hired))(mail=:emailAddress))")
Person findEmployeeByEmailAddress(String emailAddress);
}
Spring Data 支持命名参数(参数名以 : 为前缀)和位置参数绑定(形式为从零开始的 ?0)。
我们建议使用命名参数,以提高可读性。
此外,在重构时,如果参数位置发生变化,使用位置参数会使查询方法更容易出错。 |
参数编码
基于字符串的查询的参数根据 RFC2254 进行编码。
这可能导致某些字符被不需要的转义。
您可以通过 @LdapEncode 注解指定自定义编码器,该注解定义了要使用的 LdapEncoder。
@LdapEncode 应用于查询方法的单个参数。
它不适用于派生查询或值表达式(SpEL、属性占位符)。
LdapEncoderinterface 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 值表达式(Value Expressions)支持的一部分。 SpEL 表达式可用于操作查询方法的参数,也可用于调用 Bean 的方法。 方法参数可以通过名称或索引进行访问,如下例所示。
@Query("(&(firstName=?#{[0]})(mail=:?#{principal.emailAddress}))")
List<Person> findByFirstnameAndCurrentUserWithCustomQuery(String firstname);
通过 SpEL 表达式提供的值不会根据 RFC2254 进行转义。
如有需要,您必须确保这些值已正确转义。
建议使用 Spring LDAP 的 org.springframework.ldap.support.LdapEncoder 辅助类。 |
使用属性占位符
属性占位符(参见值表达式)可根据 Spring Environment 中的配置属性,轻松地自定义您的查询。
这对于需要根据环境或配置进行定制的查询非常有用。
@Query("(&(firstName=?0)(stage=:?${myapp.stage:dev}))")
List<Person> findByFirstnameAndStageWithCustomQuery(String firstname);
属性占位符(Property Placeholders)所提供的值不会根据 RFC2254 进行转义。
如有需要,您必须确保这些值已被正确转义。
建议使用 Spring LDAP 提供的 org.springframework.ldap.support.LdapEncoder 辅助类。 |