You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Set EnableRedisRepositories.enableKeyspaceEvents default to OFF. Expiry notifications require to opt-in. Add JavaDoc. Add documentation for delayed/disabled event listener. Fix spelling. Use property value instead of attribute on RedisKeyValueAdapter bean definition. Remove trailing white spaces.
Original pull request: #193.
Copy file name to clipboardExpand all lines: src/main/asciidoc/reference/redis-repositories.adoc
+48-42Lines changed: 48 additions & 42 deletions
Original file line number
Diff line number
Diff line change
@@ -26,7 +26,7 @@ public class Person {
26
26
====
27
27
28
28
We have a pretty simple domain object here. Note that it has a property named `id` annotated with `org.springframework.data.annotation.Id` and a `@RedisHash` annotation on its type.
29
-
Those two are responsible for creating the actual key used to persist the hash.
29
+
Those two are responsible for creating the actual key used to persist the hash.
30
30
31
31
NOTE: Properties annotated with `@Id` as well as those named `id` are considered as the identifier properties. Those with the annotation are favored over others.
32
32
@@ -56,7 +56,7 @@ public class ApplicationConfig {
56
56
public RedisConnectionFactory connectionFactory() {
57
57
return new JedisConnectionFactory();
58
58
}
59
-
59
+
60
60
@Bean
61
61
public RedisTemplate<?, ?> redisTemplate() {
62
62
@@ -75,17 +75,17 @@ Given the setup above we can go on and inject `PersonRepository` into our compon
<1> The `_class` attribute is included on root level as well as on any nested interface or abstract types.
115
115
<2> Simple property values are mapped by path.
116
-
<3> Properties of complex types are mapped by their dot path.
116
+
<3> Properties of complex types are mapped by their dot path.
117
117
====
118
118
119
119
[cols="1,2,3", options="header"]
@@ -163,7 +163,7 @@ Mapping behavior can be customized by registering the according `Converter` in `
163
163
.Sample byte[] Converters
164
164
====
165
165
[source,java]
166
-
----
166
+
----
167
167
@WritingConverter
168
168
public class AddressToBytesConverter implements Converter<Address, byte[]> {
169
169
@@ -183,15 +183,15 @@ public class AddressToBytesConverter implements Converter<Address, byte[]> {
183
183
184
184
@ReadingConverter
185
185
public class BytesToAddressConverter implements Converter<byte[], Address> {
186
-
186
+
187
187
private final Jackson2JsonRedisSerializer<Address> serializer;
188
-
188
+
189
189
public BytesToAddressConverter() {
190
-
190
+
191
191
serializer = new Jackson2JsonRedisSerializer<Address>(Address.class);
192
192
serializer.setObjectMapper(new ObjectMapper());
193
193
}
194
-
194
+
195
195
@Override
196
196
public Address convert(byte[] value) {
197
197
return serializer.deserialize(value);
@@ -203,10 +203,10 @@ public class BytesToAddressConverter implements Converter<byte[], Address> {
203
203
Using the above byte[] `Converter` produces eg.
204
204
====
205
205
[source,text]
206
-
----
206
+
----
207
207
_class = org.example.Person
208
208
id = e2c7dcee-b8cd-4424-883e-736ce564363e
209
-
firstname = rand
209
+
firstname = rand
210
210
lastname = al’thor
211
211
address = { city : "emond's field", country : "andor" }
212
212
----
@@ -216,7 +216,7 @@ address = { city : "emond's field", country : "andor" }
216
216
.Sample Map<String,byte[]> Converters
217
217
====
218
218
[source,java]
219
-
----
219
+
----
220
220
@WritingConverter
221
221
public class AddressToMapConverter implements Converter<Address, Map<String,byte[]>> {
222
222
@@ -228,7 +228,7 @@ public class AddressToMapConverter implements Converter<Address, Map<String,byte
228
228
229
229
@ReadingConverter
230
230
public class MapToAddressConverter implements Converter<Address, Map<String, byte[]>> {
231
-
231
+
232
232
@Override
233
233
public Address convert(Map<String,byte[]> source) {
234
234
return new Address(new String(source.get("ciudad")));
@@ -241,10 +241,10 @@ Using the above Map `Converter` produces eg.
241
241
242
242
====
243
243
[source,text]
244
-
----
244
+
----
245
245
_class = org.example.Person
246
246
id = e2c7dcee-b8cd-4424-883e-736ce564363e
247
-
firstname = rand
247
+
firstname = rand
248
248
lastname = al’thor
249
249
ciudad = "emond's field"
250
250
----
@@ -266,7 +266,7 @@ By default the prefix is set to `getClass().getName()`. This default can be alte
266
266
public class ApplicationConfig {
267
267
268
268
//... RedisConnectionFactory and RedisTemplate Bean definitions omitted
269
-
269
+
270
270
public static class MyKeyspaceConfiguration extends KeyspaceConfiguration {
271
271
272
272
@Override
@@ -287,14 +287,14 @@ public class ApplicationConfig {
287
287
public class ApplicationConfig {
288
288
289
289
//... RedisConnectionFactory and RedisTemplate Bean definitions omitted
290
-
290
+
291
291
@Bean
292
292
public RedisMappingContext keyValueMappingContext() {
293
293
return new RedisMappingContext(
294
294
new MappingConfiguration(
295
-
new MyKeyspaceConfiguration(), new IndexConfiguration()));
295
+
new MyKeyspaceConfiguration(), new IndexConfiguration()));
296
296
}
297
-
297
+
298
298
public static class MyKeyspaceConfiguration extends KeyspaceConfiguration {
299
299
300
300
@Override
@@ -310,7 +310,7 @@ public class ApplicationConfig {
310
310
== Secondary Indexes
311
311
http://redis.io/topics/indexes[Secondary indexes] are used to enable lookup operations based on native Redis structures. Values are written to the according indexes on every save and are removed when objects are deleted or <<redis.repositories.expirations,expire>>.
312
312
313
-
Given the sample `Person` entity we can create an index for _firstname_ by annotating the property with `@Indexed`.
313
+
Given the sample `Person` entity we can create an index for _firstname_ by annotating the property with `@Indexed`.
314
314
315
315
.Annotation driven indexing
316
316
====
@@ -355,7 +355,7 @@ Further more the programmatic setup allows to define indexes on map keys and lis
355
355
public class Person {
356
356
357
357
// ... other properties omitted
358
-
358
+
359
359
Map<String,String> attributes; <1>
360
360
Map<String Person> relatives; <2>
361
361
List<Address> addresses; <3>
@@ -379,7 +379,7 @@ Same as with _keyspaces_ it is possible to configure indexes without the need of
379
379
public class ApplicationConfig {
380
380
381
381
//... RedisConnectionFactory and RedisTemplate Bean definitions omitted
382
-
382
+
383
383
public static class MyIndexConfiguration extends IndexConfiguration {
384
384
385
385
@Override
@@ -400,14 +400,14 @@ public class ApplicationConfig {
400
400
public class ApplicationConfig {
401
401
402
402
//... RedisConnectionFactory and RedisTemplate Bean definitions omitted
403
-
403
+
404
404
@Bean
405
405
public RedisMappingContext keyValueMappingContext() {
406
406
return new RedisMappingContext(
407
407
new MappingConfiguration(
408
-
new KeyspaceConfiguration(), new MyIndexConfiguration()));
408
+
new KeyspaceConfiguration(), new MyIndexConfiguration()));
409
409
}
410
-
410
+
411
411
public static class MyIndexConfiguration extends IndexConfiguration {
412
412
413
413
@Override
@@ -427,24 +427,24 @@ The expiration time in seconds can be set via `@RedisHash(timeToLive=...)` as we
427
427
428
428
More flexible expiration times can be set by using the `@TimeToLive` annotation on either a numeric property or method. However do not apply `@TimeToLive` on both a method and a property within the same class.
429
429
430
-
.Expirations
430
+
.Expirations
431
431
====
432
432
[source,java]
433
433
----
434
434
public class TimeToLiveOnProperty {
435
435
436
436
@Id
437
437
private String id;
438
-
438
+
439
439
@TimeToLive
440
440
private Long expiration;
441
441
}
442
442
443
443
public class TimeToLiveOnMethod {
444
444
445
-
@Id
445
+
@Id
446
446
private String id;
447
-
447
+
448
448
@TimeToLive
449
449
public long getTimeToLive() {
450
450
return new Random().nextLong();
@@ -456,13 +456,19 @@ public class TimeToLiveOnMethod {
456
456
457
457
The repository implementation ensures subscription to http://redis.io/topics/notifications[Redis keyspace notifications] via `RedisMessageListenerContainer`.
458
458
459
-
When the expiration is set to a positive value the according `EXPIRE` command is executed.
459
+
When the expiration is set to a positive value the according `EXPIRE` command is executed.
460
460
Additionally to persisting the original, a _phantom_ copy is persisted in Redis and set to expire 5 minutes after the original one. This is done to enable the Repository support to publish `RedisKeyExpiredEvent` holding the expired value via Springs `ApplicationEventPublisher` whenever a key expires even though the original values have already been gone. Expiry events
461
461
will be received on all connected applications using Spring Data Redis repositories.
462
462
463
-
The `RedisKeyExpiredEvent` will hold a copy of the actually expired domain object as well as the key.
463
+
By default, the key expiry listener is disabled when initializing the application. The startup mode can be adjusted in `@EnableRedisRepositories` or `RedisKeyValueAdapter` to start the listener with the application or upon the first insert of an entity with a TTL. See `EnableKeyspaceEvents` for possible values.
464
+
465
+
The `RedisKeyExpiredEvent` will hold a copy of the actually expired domain object as well as the key.
466
+
467
+
NOTE: Delaying or disabling the expiry event listener startup impacts `RedisKeyExpiredEvent` publishing.
468
+
A disabled event listener will not publish expiry events. A delayed startup can cause loss of events because the delayed
469
+
listener initialization.
464
470
465
-
NOTE: The keyspace notification message listener will alter `notify-keyspace-events` settings in Redis if those are not already set. Existing settings will not be overridden, so it is left to the user to set those up correctly when not leaving them empty.
471
+
NOTE: The keyspace notification message listener will alter `notify-keyspace-events` settings in Redis if those are not already set. Existing settings will not be overridden, so it is left to the user to set those up correctly when not leaving them empty. Please note that `CONFIG` is disabled on AWS ElastiCache and enabling the listener leads to an error.
466
472
467
473
NOTE: Redis Pub/Sub messages are not persistent. If a key expires while the application is down the expiry event will not be processed which may lead to secondary indexes containing still references to the expired object.
468
474
@@ -474,29 +480,29 @@ On loading from Redis, references are resolved automatically and mapped back int
<1> Reference stores the whole key (`keyspace:id`) of the referenced object.
485
491
====
486
492
487
-
WARNING: Referenced Objects are not subject of persisting changes when saving the referencing object. Please make sure to persist changes on referenced objects separately, since only the reference will be stored.
493
+
WARNING: Referenced Objects are not subject of persisting changes when saving the referencing object. Please make sure to persist changes on referenced objects separately, since only the reference will be stored.
488
494
Indexes set on properties of referenced types will not be resolved.
489
495
490
496
[[redis.repositories.queries]]
491
497
== Queries and Query Methods
492
-
Query methods allow automatic derivation of simple finder queries from the method name.
498
+
Query methods allow automatic derivation of simple finder queries from the method name.
493
499
494
500
.Sample Repository finder Method
495
501
====
496
502
[source,java]
497
503
----
498
504
public interface PersonRepository extends CrudRepository<Person, String> {
499
-
505
+
500
506
List<Person> findByFirstname(String firstname);
501
507
}
502
508
----
@@ -552,7 +558,7 @@ Still some considerations have to be done as the default key distribution will s
552
558
|
553
559
|===============
554
560
====
555
-
561
+
556
562
Some commands like `SINTER` and `SUNION` can only be processed on the Server side when all involved keys map to the same slot. Otherwise computation has to be done on client side.
557
563
Therefore it be useful to pin keyspaces to a single slot which allows to make use of Redis serverside computation right away.
0 commit comments