原标题:Spring认证中国教育管理中心-Spring Data Redis框架教程六
Redis 存储库允许使用各种方法来定义排序顺序。Redis 本身在检索散列或集合时不支持动态排序。因此,Redis 存储库查询方法Comparator在将结果返回为 之前构造了应用于结果的List。让我们看一下下面的例子:
示例 36. 对查询结果进行排序
interface PersonRepository extends RedisRepository<Person, String> { List<Person> findByFirstnameOrderByAgeDesc(String firstname); List<Person> findByFirstname(String firstname, Sort sort); }
从方法名称派生的静态排序。
使用方法参数进行动态排序。
您可以在集群 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 集群时, 通过使用到特定插槽来定义和固定键空间。
存储库接口的实例通常由容器创建,因此在使用 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。
Redis 作为存储本身提供了一个非常狭窄的低级 API,将高级功能(例如二级索引和查询操作)留给用户。
本节提供了存储库抽象发出的命令的更详细视图,以便更好地理解潜在的性能影响。
考虑以下实体类作为所有操作的起点:
示例 37. 示例实体
@RedisHash("people")public class Person { @Id String id; @Indexed String firstname; String lastname; Address hometown; }public class Address { @GeoIndexed Point location; }
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> 的索引添加到条目的帮助器结构集中,以跟踪要在删除/更新时清理的索引。
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> 的索引添加到条目的帮助器结构集中,以跟踪要在删除/更新时清理的索引。
地理索引与基于普通文本的索引遵循相同的规则,但使用地理结构来存储值。保存使用地理索引属性的实体会产生以下命令:
GEOADD "people:hometown:location" "13.361389" "38.115556" "76900e94-b057-44bc-abcf-8126d51a621b" SADD "people:76900e94-b057-44bc-abcf-8126d51a621b:idx" "people:hometown:location"
将保存条目的键添加到地理索引。
跟踪索引结构。
repository.findByFirstname("egwene");
SINTER "people:firstname:egwene" HGETALL "people:d70091b5-0b9a-4c0a-9551-519e61bc9ef3" HGETALL ...
获取包含在二级索引中的键。
分别获取 <1> 返回的每个键。
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> 返回的每个键。