Original title: Spring certified China Education Management Center - Spring Data Redis framework tutorial 6
13.10.1. Sorting query method results
Redis repository allows various methods to define sorting order. Redis itself does not support dynamic sorting when retrieving hashes or collections. Therefore, the redis repository query method Comparator constructs a List applied to the results before returning the results to. Let's look at the following example:
Example 36. Sorting Query Results
interface PersonRepository extends RedisRepository<Person, String> { List<Person> findByFirstnameOrderByAgeDesc(String firstname); List<Person> findByFirstname(String firstname, Sort sort); }
Static sort derived from method name.
Use method parameters for dynamic sorting.
13.11. Redis repository running on the cluster
You can use Redis repository support in a clustered Redis environment. For configuration details, see the "Redis cluster" section ConnectionFactory. However, some additional configuration is necessary because the default key is distributed throughout the cluster and its slots, propagating entities and secondary indexes.
The following table shows the data details on the cluster (based on the previous example):
key | type | a slot | node |
---|---|---|---|
Person: e2c7dcee-b8cd-4424-883e-736ce564363e | Hash id | 15171 | 127.0.0.1:7381 |
Person: a9d4b3a0-50d3-4538-a2fc-f7fc2581ee56 | Hash id | 7373 | 127.0.0.1:7380 |
Person: Name: Rand | index | 1700 | 127.0.0.1:7379 |
When all the keys involved are mapped to the same slot, some commands (such as SINTER and SUNION) can only be processed on the server side. Otherwise, the calculation must be performed on the client. Therefore, it is very useful to fix the key space to a single slot, which allows us to use Redis server-side computing immediately. The following table shows what happens when you do this (note the changes in the slot column and the port values in the node column):
key | type | a slot | node |
---|---|---|---|
{person}: e2c7dcee-b8cd-4424-883e-736ce564363e | Hash id | 2399 | 127.0.0.1:7379 |
{person}: a9d4b3a0-50d3-4538-a2fc-f7fc2581ee56 | Hash id | 2399 | 127.0.0.1:7379 |
{person}: Name: Rand | index | 2399 | 127.0.0.1:7379 |
@RedisHash("{yourkeyspace}") when you use a Redis cluster, you define and fix the key space by using a specific slot.
13.12.CDI integration
Instances of repository interfaces are usually created by containers, so spring is the most natural choice when using Spring Data. Spring provides a complex way to create bean instances. Spring Data Redis comes with a custom CDI extension that allows you to use repository abstraction in a CDI environment. This extension is part of the JAR, so to activate it, put the Spring Data Redis JAR in your classpath.
Then, you can set up infrastructure RedisOperations by implementing CDI Producer for RedisConnectionFactoryand, as shown in the following example:
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; } }
The necessary settings may vary, depending on your Java EE environment.
The Spring Data Redis CDI extension selects all available repositories as CDI bean s and creates a proxy for the Spring Data repository when the container requests a bean of repository type. Therefore, getting an instance of the Spring Data repository is a matter of declaring the @ Injected attribute, as shown in the following example:
class RepositoryClient { @Inject PersonRepository repository; public void businessMethod() { List<Person> people = repository.findAll(); } }
Redis repository requires RedisKeyValueAdapter and RedisKeyValueTemplate instances. If the provided beans are not found, they are created and managed by the Spring Data CDI extension. You can, however, provide your own bean configuration specific properties RedisKeyValueAdapter and RedisKeyValueTemplate.
13.13.Redis repository analysis
Redis provides a very narrow low-level API as storage itself, leaving advanced functions (such as secondary index and query operations) to users.
This section provides a more detailed view of the commands issued by the repository abstraction to better understand the potential performance impact.
Consider the following entity classes as a starting point for all operations:
Example 37. Example entity
@RedisHash("people") public class Person { @Id String id; @Indexed String firstname; String lastname; Address hometown; } public class Address { @GeoIndexed Point location; }
13.13.1. Insert new
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"
Saves flattened entries as hashes.
Add the hash key written in < 1 > to the secondary index of the entity in the same key space.
Add the hash key written in < 2 > to the secondary index of the name with the attribute value.
Add the index of < 3 > to the helper structure set of entries to track the index to be cleaned up on deletion / update.
13.13.2. Replace existing
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"
Delete the existing hash to avoid that the remainder of the hash key may no longer exist.
Saves flattened entries as hashes.
Add the hash key written in < 1 > to the secondary index of the entity in the same key space.
Gets the existing index structure that may need to be updated.
Check whether the index exists and what type it is (text, geography, etc.).
Removes possible keys from the index.
Delete the assistant that saved the index information.
Add the hash key added in < 2 > to the secondary index with the name of the attribute value.
Add the index of < 6 > to the helper structure set of entries to track the indexes to be cleaned up on deletion / update.
13.13.3. Saving geographic data
Geographic indexes follow the same rules as plain text-based indexes, but use geographic structures to store values. Saving entities that use geo index properties results in the following commands:
GEOADD "people:hometown:location" "13.361389" "38.115556" "76900e94-b057-44bc-abcf-8126d51a621b" SADD "people:76900e94-b057-44bc-abcf-8126d51a621b:idx" "people:hometown:location"
Add the key to save the entry to the geographic index.
Tracking index structure.
13.13.4. Find using simple index
repository.findByFirstname("egwene");
SINTER "people:firstname:egwene" HGETALL "people:d70091b5-0b9a-4c0a-9551-519e61bc9ef3" HGETALL ...
Gets the key contained in the secondary index.
Get each key returned by < 1 > separately.
13.13.5. Use geographic index to find
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 ...
Gets the key contained in the secondary index.
Get each key returned by < 1 > separately.