Template API
在其最基本的形态中,KeyValueTemplate 使用一个 MapAdapter,它包装了 ConcurrentHashMap,并使用 Spring Expression Language 来执行查询和排序。
KeyValueAdapter 在存储和检索数据方面承担主要工作。数据结构会影响性能和多线程行为。
你可以使用不同的类型,或者使用一些值预初始化适配器,并且可以通过使用 MapKeyValueAdapter 上的各种构造函数来实现这一点,如下面的示例所示:
@Configuration
class MyConfiguration {
@Bean
public KeyValueOperations mapKeyValueTemplate() { 1
return new KeyValueTemplate(keyValueAdapter());
}
@Bean
public KeyValueAdapter keyValueAdapter() {
return new MapKeyValueAdapter(ConcurrentHashMap.class); 2
}
}
定义一个使用默认 Bean 名称的自定义
KeyValueOperationsBean。请参阅@EnableMapRepositories的文档和属性以进行进一步自定义。定义一个使用
ConcurrentHashMap作为存储的自定义KeyValueAdapterBean,该存储供KeyValueTemplate使用。
Keyspaces
以下示例展示了一个用于 Person 对象仓库的 keyspace:
@KeySpace("persons")
class Person {
@Id String id;
String firstname;
String lastname;
}
class User extends Person {
String username;
}
template.findAllOf(Person.class); 1
template.findAllOf(User.class); 2
返回
personskeyspace 中的所有实体。返回存储在
personskeyspace 中类型为User的元素。
@KeySpace 支持 Value Expressions,可实现动态 keyspace 配置。
自定义 KeySpace 注解
你可以通过在其中一个属性上添加 @AliasFor 注解来组合你自己的 KeySpace 注解,从而实现更面向领域的用法。
组合注解必须继承 @Persistent。
以下示例展示了一个自定义 @KeySpace 注解:
@KeySpace
@Persistent
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
static @interface CacheCentricAnnotation {
@AliasFor(annotation = KeySpace.class, attribute = "value")
String cacheRegion() default "";
}
@CacheCentricAnnotation(cacheRegion = "customers")
class Customer {
//...
}
查询
查询的运行由 QueryEngine 管理。如前所述,你可以指示 KeyValueAdapter 使用特定于实现的 QueryEngine,以允许访问原生功能。在没有进一步自定义的情况下,可以使用 SpELQueryEngine 运行查询。
出于性能考虑,我们强烈建议使用已编译的 SpEL 表达式。(“SpEL”是“Spring Expression Language”的缩写。)你可以使用 -Dspring.expression.compiler.mode=IMMEDIATE 开关来启用它。
下面的示例展示了一个使用 SpEL 的查询:
KeyValueQuery<String> query = new KeyValueQuery<String>("lastname == 'targaryen'");
List<Person> targaryens = template.find(query, Person.class);
使用 SpEL 时,必须提供 getters 和 setters 才能查询属性。
排序
根据适配器提供的 store 实现,实体可能已经以某种排序方式存储,但不一定必须如此。 再次说明,底层 QueryEngine 能够执行排序操作。 在未进行进一步自定义的情况下,排序是通过使用从 Sort 子句中提取的 SpelPropertyComparator 完成的。 以下示例展示了一个带有 Sort 子句的查询:
KeyValueQuery<String> query = new KeyValueQuery<String>("lastname == 'baratheon'");
query.setSort(Sort.by(DESC, "age"));
List<Person> targaryens = template.find(query, Person.class);
请注意,若要使用 SpEL 进行排序,必须存在 getters 和 setters。