原标题:Spring认证中国教育管理中心-Spring Data Redis框架教程六
13.10.1.排序查询方法结果
Redis 存储库允许使用各种方法来定义排序顺序。Redis 本身在检索散列或集合时不支持动态排序。因此,Redis 存储库查询方法Comparator在将结果返回为 之前构造了应用于结果的List。让我们看一下下面的例子:
示例 36. 对查询结果进行排序
interface PersonRepository extends RedisRepository<Person, String> {
List<Person> findByFirstnameOrderByAgeDesc(String firstname);
List<Person> findByFirstname(String firstname, Sort sort);
}
从方法名称派生的静态排序。
使用方法参数进行动态排序。
13.11.在集群上运行的 Redis 存储库
您可以在集群 Redis 环境中使用 Redis 存储库支持。有关配置详细信息,请参阅“ Redis 集群”部分ConnectionFactory。尽管如此,还必须进行一些额外的配置,因为默认的密钥分布在整个集群及其插槽中传播实体和二级索引。
下表显示了集群上的数据详细信息(基于前面的示例):
钥匙 | 类型 | 投币口 | 节点 |
人:e2c7dcee-b8cd-4424-883e-736ce564363e | 哈希的 id | 15171 | 127.0.0.1:7381 |
人:a9d4b3a0-50d3-4538-a2fc-f7fc2581ee56 | 哈希的 id | 7373 | 127.0.0.1:7380 |
人:名字:兰德 | 指数 | 1700 | 127.0.0.1:7379 |
当所有涉及的键都映射到同一个槽时,某些命令(例如SINTER和SUNION)只能在服务器端处理。否则,必须在客户端进行计算。因此,将键空间固定到单个插槽非常有用,这让我们可以立即使用 Redis 服务器端计算。下表显示了当您执行此操作时会发生什么(注意插槽列中的更改和节点列中的端口值):
钥匙 | 类型 | 投币口 | 节点 |
{人}:e2c7dcee-b8cd-4424-883e-736ce564363e | 哈希的 id | 2399 | 127.0.0.1:7379 |
{人}:a9d4b3a0-50d3-4538-a2fc-f7fc2581ee56 | 哈希的 id | 2399 | 127.0.0.1:7379 |
{人}:名字:兰德 | 指数 | 2399 | 127.0.0.1:7379 |
@RedisHash("{yourkeyspace}")当您使用 Redis 集群时, 通过使用到特定插槽来定义和固定键空间。
13.12.CDI集成
存储库接口的实例通常由容器创建,因此在使用 Spring Data 时,Spring 是最自然的选择。Spring 提供了复杂的创建 bean 实例的方法。Spring Data Redis 附带一个自定义 CDI 扩展,允许您在 CDI 环境中使用存储库抽象。该扩展是 JAR 的一部分,因此要激活它,请将 Spring Data Redis JAR 放入您的类路径中。
然后,您可以通过为RedisConnectionFactoryand实现 CDI Producer 来设置基础结构RedisOperations,如以下示例所示:
class RedisOperationsProducer {
@Produces
RedisConnectionFactory redisConnectionFactory() {
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(new RedisStandaloneConfiguration());
jedisConnectionFactory.afterPropertiesSet();
return jedisConnectionFactory;
}
void disposeRedisConnectionFactory(@Disposes RedisConnectionFactory redisConnectionFactory) throws Exception {
if (redisConnectionFactory instanceof DisposableBean) {
((DisposableBean) redisConnectionFactory).destroy();
}
}
@Produces
@ApplicationScoped
RedisOperations<byte[], byte[]> redisOperationsProducer(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
template.setConnectionFactory(redisConnectionFactory);
template.afterPropertiesSet();
return template;
}
}
必要的设置可能会有所不同,具体取决于您的 JavaEE 环境。
Spring Data Redis CDI 扩展选择所有可用的存储库作为 CDI bean,并在容器请求存储库类型的 bean 时为 Spring Data 存储库创建代理。因此,获取 Spring Data 存储库的实例是声明@Injected属性的问题,如以下示例所示:
class RepositoryClient {
@Inject
PersonRepository repository;
public void businessMethod() {
List<Person> people = repository.findAll();
}
}
Redis 存储库需要RedisKeyValueAdapter和RedisKeyValueTemplate实例。如果未找到提供的 bean,则这些 bean 由 Spring Data CDI 扩展创建和管理。你可以,但是,提供自己的豆子配置的特定属性RedisKeyValueAdapter和RedisKeyValueTemplate。
13.13.Redis 存储库剖析
Redis 作为存储本身提供了一个非常狭窄的低级 API,将高级功能(例如二级索引和查询操作)留给用户。
本节提供了存储库抽象发出的命令的更详细视图,以便更好地理解潜在的性能影响。
考虑以下实体类作为所有操作的起点:
示例 37. 示例实体
@RedisHash("people")
public class Person {
@Id String id;
@Indexed String firstname;
String lastname;
Address hometown;
}
public class Address {
@GeoIndexed Point location;
}
13.13.1.插入新的
repository.save(new Person("rand", "al'thor"));
HMSET "people:19315449-cda2-4f5c-b696-9cb8018fa1f9" "_class" "Person" "id" "19315449-cda2-4f5c-b696-9cb8018fa1f9" "firstname" "rand" "lastname" "al'thor"
SADD "people" "19315449-cda2-4f5c-b696-9cb8018fa1f9"
SADD "people:firstname:rand" "19315449-cda2-4f5c-b696-9cb8018fa1f9"
SADD "people:19315449-cda2-4f5c-b696-9cb8018fa1f9:idx" "people:firstname:rand"
将展平的条目保存为哈希。
将 <1> 中写入的哈希键添加到同一键空间中实体的辅助索引中。
将 <2> 中写入的哈希键添加到具有属性值的名字的二级索引中。
将 <3> 的索引添加到条目的帮助器结构集中,以跟踪要在删除/更新时清理的索引。
13.13.2.替换现有
repository.save(new Person("e82908cf-e7d3-47c2-9eec-b4e0967ad0c9", "Dragon Reborn", "al'thor"));
DEL "people:e82908cf-e7d3-47c2-9eec-b4e0967ad0c9"
HMSET "people:e82908cf-e7d3-47c2-9eec-b4e0967ad0c9" "_class" "Person" "id" "e82908cf-e7d3-47c2-9eec-b4e0967ad0c9" "firstname" "Dragon Reborn" "lastname" "al'thor"
SADD "people" "e82908cf-e7d3-47c2-9eec-b4e0967ad0c9"
SMEMBERS "people:e82908cf-e7d3-47c2-9eec-b4e0967ad0c9:idx"
TYPE "people:firstname:rand"
SREM "people:firstname:rand" "e82908cf-e7d3-47c2-9eec-b4e0967ad0c9"
DEL "people:e82908cf-e7d3-47c2-9eec-b4e0967ad0c9:idx"
SADD "people:firstname:Dragon Reborn" "e82908cf-e7d3-47c2-9eec-b4e0967ad0c9"
SADD "people:e82908cf-e7d3-47c2-9eec-b4e0967ad0c9:idx" "people:firstname:Dragon Reborn"
删除现有的散列以避免散列键的剩余部分可能不再存在。
将展平的条目保存为哈希。
将 <1> 中写入的哈希键添加到同一键空间中实体的辅助索引中。
获取可能需要更新的现有索引结构。
检查索引是否存在以及它是什么类型(文本、地理等)。
从索引中删除可能存在的键。
删除保存索引信息的助手。
将 <2> 中添加的哈希键添加到具有属性值的名字的二级索引中。
将 <6> 的索引添加到条目的帮助器结构集中,以跟踪要在删除/更新时清理的索引。
13.13.3.保存地理数据
地理索引与基于普通文本的索引遵循相同的规则,但使用地理结构来存储值。保存使用地理索引属性的实体会产生以下命令:
GEOADD "people:hometown:location" "13.361389" "38.115556" "76900e94-b057-44bc-abcf-8126d51a621b"
SADD "people:76900e94-b057-44bc-abcf-8126d51a621b:idx" "people:hometown:location"
将保存条目的键添加到地理索引。
跟踪索引结构。
13.13.4.使用简单索引查找
repository.findByFirstname("egwene");
SINTER "people:firstname:egwene"
HGETALL "people:d70091b5-0b9a-4c0a-9551-519e61bc9ef3"
HGETALL ...
获取包含在二级索引中的键。
分别获取 <1> 返回的每个键。
13.13.5.使用地理索引查找
repository.findByHometownLocationNear(new Point(15, 37), new Distance(200, KILOMETERS));
GEORADIUS "people:hometown:location" "15.0" "37.0" "200.0" "km"
HGETALL "people:76900e94-b057-44bc-abcf-8126d51a621b"
HGETALL ...
获取包含在二级索引中的键。
分别获取 <1> 返回的每个键。