Skip to content

Commit d88d992

Browse files
committed
DATAREDIS-471 - Polishing.
Update reference documentation. Enhance JavaDoc. Remove destroy of managed bean. Refactor property update of writePartialUpdate into own method. Remove trailing whitespaces in JavaDoc. Original pull request: #191.
1 parent 76229c1 commit d88d992

16 files changed

+130
-128
lines changed

src/main/asciidoc/reference/redis-repositories.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ Indexes set on properties of referenced types will not be resolved.
496496
[[redis.repositories.partial-updates]]
497497
== Persisting Partial Updates
498498
In some cases it is not necessary to load and rewrite the entire entity just to set a new value within it. A session timestamp for last active time might be such a scenario where you just want to alter one property.
499-
`PartialUpdate` allows to define `set`, `delete` actions on existing objects while taking care of updating potential expiration times of the entity itself as well as index structures.
499+
`PartialUpdate` allows to define `set` and `delete` actions on existing objects while taking care of updating potential expiration times of the entity itself as well as index structures.
500500

501501
.Sample Partial Update
502502
====
@@ -521,7 +521,7 @@ update = new PartialUpdate<Person>("e2c7dcee", Person.class)
521521
522522
template.update(update);
523523
----
524-
<1> Set the simple property _firstname_ to _mat_
524+
<1> Set the simple property _firstname_ to _mat_.
525525
<2> Set the simple property _address.city_ to _emond's field_ without having to pass in the entire object. This does not work when a custom conversion is registered.
526526
<3> Remove the property _age_.
527527
<4> Set complex property _address_.

src/main/java/org/springframework/data/redis/core/IndexWriter.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ private void removeKeyFromExistingIndexes(byte[] key, Iterable<IndexedData> inde
150150
protected void removeKeyFromExistingIndexes(byte[] key, IndexedData indexedData) {
151151

152152
Assert.notNull(indexedData, "IndexedData must not be null!");
153+
153154
Set<byte[]> existingKeys = connection
154155
.keys(toBytes(indexedData.getKeyspace() + ":" + indexedData.getIndexName() + ":*"));
155156

@@ -217,7 +218,8 @@ private byte[] toBytes(Object source) {
217218
}
218219

219220
throw new InvalidDataAccessApiUsageException(String.format(
220-
"Cannot convert %s to binary representation for index key generation. Are you missing a Converter? Did you register a non PathBasedRedisIndexDefinition that might apply to a complex type?",
221+
"Cannot convert %s to binary representation for index key generation. "
222+
+ "Are you missing a Converter? Did you register a non PathBasedRedisIndexDefinition that might apply to a complex type?",
221223
source.getClass()));
222224
}
223225

src/main/java/org/springframework/data/redis/core/PartialUpdate.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ public PartialUpdate<T> set(String path, Object value) {
114114
PartialUpdate<T> update = new PartialUpdate<T>(this.id, this.target, this.value, this.refreshTtl,
115115
this.propertyUpdates);
116116
update.propertyUpdates.add(new PropertyUpdate(UpdateCommand.SET, path, value));
117+
117118
return update;
118119
}
119120

@@ -130,6 +131,7 @@ public PartialUpdate<T> del(String path) {
130131
PartialUpdate<T> update = new PartialUpdate<T>(this.id, this.target, this.value, this.refreshTtl,
131132
this.propertyUpdates);
132133
update.propertyUpdates.add(new PropertyUpdate(UpdateCommand.DEL, path));
134+
133135
return update;
134136
}
135137

src/main/java/org/springframework/data/redis/core/RedisKeyValueTemplate.java

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -140,29 +140,6 @@ public void update(Object objectToUpdate) {
140140
super.update(objectToUpdate);
141141
}
142142

143-
/*
144-
* (non-Javadoc)
145-
* @see org.springframework.data.keyvalue.core.KeyValueTemplate#destroy()
146-
*/
147-
@Override
148-
public void destroy() throws Exception {
149-
150-
execute(new RedisKeyValueCallback<Void>() {
151-
152-
@Override
153-
public Void doInRedis(RedisKeyValueAdapter adapter) {
154-
155-
try {
156-
adapter.destroy();
157-
} catch (Exception e) {
158-
throw new RedisSystemException(e.getMessage(), e);
159-
}
160-
return null;
161-
}
162-
});
163-
164-
}
165-
166143
protected void doPartialUpdate(final PartialUpdate<?> update) {
167144

168145
execute(new RedisKeyValueCallback<Void>() {

src/main/java/org/springframework/data/redis/core/convert/CompositeIndexResolver.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ public Set<IndexedData> resolveIndexesFor(TypeInformation<?> typeInformation, Ob
7272
return data;
7373
}
7474

75+
/* (non-Javadoc)
76+
* @see org.springframework.data.redis.core.convert.IndexResolver#resolveIndexesFor(java.lang.String, java.lang.String, org.springframework.data.util.TypeInformation, java.lang.Object)
77+
*/
7578
@Override
7679
public Set<IndexedData> resolveIndexesFor(String keyspace, String path, TypeInformation<?> typeInformation,
7780
Object value) {

src/main/java/org/springframework/data/redis/core/convert/IndexResolver.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,30 @@
2323
/**
2424
* {@link IndexResolver} extracts secondary index structures to be applied on a given path, {@link PersistentProperty}
2525
* and value.
26-
*
26+
*
2727
* @author Christoph Strobl
2828
* @since 1.7
2929
*/
3030
public interface IndexResolver {
3131

3232
/**
3333
* Resolves all indexes for given type information / value combination.
34-
*
34+
*
3535
* @param typeInformation must not be {@literal null}.
3636
* @param value the actual value. Can be {@literal null}.
3737
* @return never {@literal null}.
3838
*/
3939
Set<IndexedData> resolveIndexesFor(TypeInformation<?> typeInformation, Object value);
4040

41+
/**
42+
* Resolves all indexes for given type information / value combination.
43+
*
44+
* @param keyspace must not be {@literal null}.
45+
* @param path must not be {@literal null}.
46+
* @param typeInformation must not be {@literal null}.
47+
* @param value the actual value. Can be {@literal null}.
48+
* @return never {@literal null}.
49+
*/
4150
Set<IndexedData> resolveIndexesFor(String keyspace, String path, TypeInformation<?> typeInformation, Object value);
4251

4352
}

src/main/java/org/springframework/data/redis/core/convert/MappingRedisConverter.java

Lines changed: 81 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -72,18 +72,18 @@
7272
* <br />
7373
* <strong>NOTE</strong> {@link MappingRedisConverter} is an {@link InitializingBean} and requires
7474
* {@link MappingRedisConverter#afterPropertiesSet()} to be called.
75-
*
75+
*
7676
* <pre>
7777
* <code>
7878
* &#64;RedisHash("persons")
7979
* class Person {
80-
*
80+
*
8181
* &#64;Id String id;
8282
* String firstname;
83-
*
83+
*
8484
* List<String> nicknames;
8585
* List<Person> coworkers;
86-
*
86+
*
8787
* Address address;
8888
* &#64;Reference Country nationality;
8989
* }
@@ -105,9 +105,10 @@
105105
* nationality=nationality:andora
106106
* </code>
107107
* </pre>
108-
*
108+
*
109109
* @author Christoph Strobl
110110
* @author Greg Turnquist
111+
* @author Mark Paluch
111112
* @since 1.7
112113
*/
113114
public class MappingRedisConverter implements RedisConverter, InitializingBean {
@@ -128,7 +129,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
128129

129130
/**
130131
* Creates new {@link MappingRedisConverter}.
131-
*
132+
*
132133
* @param context can be {@literal null}.
133134
*/
134135
MappingRedisConverter(RedisMappingContext context) {
@@ -137,7 +138,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
137138

138139
/**
139140
* Creates new {@link MappingRedisConverter} and defaults {@link RedisMappingContext} when {@literal null}.
140-
*
141+
*
141142
* @param mappingContext can be {@literal null}.
142143
* @param indexResolver can be {@literal null}.
143144
* @param referenceResolver must not be {@literal null}.
@@ -394,8 +395,8 @@ protected void writePartialUpdate(PartialUpdate<?> update, RedisData sink) {
394395
RedisPersistentEntity<?> entity = mappingContext.getPersistentEntity(update.getTarget());
395396

396397
write(update.getValue(), sink);
397-
if (sink.getBucket().keySet().contains("_class")) {
398-
sink.getBucket().put("_class", null); // overwrite stuff in here
398+
if (sink.getBucket().keySet().contains(TYPE_HINT_ALIAS)) {
399+
sink.getBucket().put(TYPE_HINT_ALIAS, null); // overwrite stuff in here
399400
}
400401

401402
if (update.isRefreshTtl() && !update.getPropertyUpdates().isEmpty()) {
@@ -411,86 +412,95 @@ protected void writePartialUpdate(PartialUpdate<?> update, RedisData sink) {
411412
String path = pUpdate.getPropertyPath();
412413

413414
if (UpdateCommand.SET.equals(pUpdate.getCmd())) {
415+
writePartialPropertyUpdate(update, pUpdate, sink, entity, path);
416+
}
417+
}
418+
}
414419

415-
KeyValuePersistentProperty targetProperty = getTargetPropertyOrNullForPath(path, update.getTarget());
420+
/**
421+
* @param update
422+
* @param pUpdate
423+
* @param sink
424+
* @param entity
425+
* @param path
426+
*/
427+
private void writePartialPropertyUpdate(PartialUpdate<?> update, PropertyUpdate pUpdate, RedisData sink,
428+
RedisPersistentEntity<?> entity, String path) {
416429

417-
if (targetProperty == null) {
430+
KeyValuePersistentProperty targetProperty = getTargetPropertyOrNullForPath(path, update.getTarget());
418431

419-
targetProperty = getTargetPropertyOrNullForPath(path.replaceAll("\\.\\[.*\\]", ""), update.getTarget());
432+
if (targetProperty == null) {
420433

421-
TypeInformation<?> ti = targetProperty == null ? ClassTypeInformation.OBJECT
422-
: (targetProperty.isMap()
423-
? (targetProperty.getTypeInformation().getMapValueType() != null
424-
? targetProperty.getTypeInformation().getMapValueType() : ClassTypeInformation.OBJECT)
425-
: targetProperty.getTypeInformation().getActualType());
434+
targetProperty = getTargetPropertyOrNullForPath(path.replaceAll("\\.\\[.*\\]", ""), update.getTarget());
426435

427-
writeInternal(entity.getKeySpace(), pUpdate.getPropertyPath(), pUpdate.getValue(), ti, sink);
428-
continue;
429-
}
436+
TypeInformation<?> ti = targetProperty == null ? ClassTypeInformation.OBJECT
437+
: (targetProperty.isMap()
438+
? (targetProperty.getTypeInformation().getMapValueType() != null
439+
? targetProperty.getTypeInformation().getMapValueType() : ClassTypeInformation.OBJECT)
440+
: targetProperty.getTypeInformation().getActualType());
430441

431-
if (targetProperty.isAssociation()) {
442+
writeInternal(entity.getKeySpace(), pUpdate.getPropertyPath(), pUpdate.getValue(), ti, sink);
443+
return;
444+
}
432445

433-
if (targetProperty.isCollectionLike()) {
446+
if (targetProperty.isAssociation()) {
434447

435-
KeyValuePersistentEntity<?> ref = mappingContext.getPersistentEntity(
436-
targetProperty.getAssociation().getInverse().getTypeInformation().getComponentType().getActualType());
448+
if (targetProperty.isCollectionLike()) {
437449

438-
int i = 0;
439-
for (Object o : (Collection<?>) pUpdate.getValue()) {
450+
KeyValuePersistentEntity<?> ref = mappingContext.getPersistentEntity(
451+
targetProperty.getAssociation().getInverse().getTypeInformation().getComponentType().getActualType());
440452

441-
Object refId = ref.getPropertyAccessor(o).getProperty(ref.getIdProperty());
442-
sink.getBucket().put(pUpdate.getPropertyPath() + ".[" + i + "]",
443-
toBytes(ref.getKeySpace() + ":" + refId));
444-
i++;
445-
}
446-
} else {
447-
448-
KeyValuePersistentEntity<?> ref = mappingContext
449-
.getPersistentEntity(targetProperty.getAssociation().getInverse().getTypeInformation());
453+
int i = 0;
454+
for (Object o : (Collection<?>) pUpdate.getValue()) {
450455

451-
Object refId = ref.getPropertyAccessor(pUpdate.getValue()).getProperty(ref.getIdProperty());
452-
sink.getBucket().put(pUpdate.getPropertyPath(), toBytes(ref.getKeySpace() + ":" + refId));
453-
}
456+
Object refId = ref.getPropertyAccessor(o).getProperty(ref.getIdProperty());
457+
sink.getBucket().put(pUpdate.getPropertyPath() + ".[" + i + "]", toBytes(ref.getKeySpace() + ":" + refId));
458+
i++;
454459
}
460+
} else {
455461

456-
else if (targetProperty.isCollectionLike()) {
462+
KeyValuePersistentEntity<?> ref = mappingContext
463+
.getPersistentEntity(targetProperty.getAssociation().getInverse().getTypeInformation());
457464

458-
Collection<?> collection = pUpdate.getValue() instanceof Collection ? (Collection<?>) pUpdate.getValue()
459-
: Collections.<Object> singleton(pUpdate.getValue());
460-
writeCollection(entity.getKeySpace(), pUpdate.getPropertyPath(), collection,
461-
targetProperty.getTypeInformation().getActualType(), sink);
462-
} else if (targetProperty.isMap()) {
465+
Object refId = ref.getPropertyAccessor(pUpdate.getValue()).getProperty(ref.getIdProperty());
466+
sink.getBucket().put(pUpdate.getPropertyPath(), toBytes(ref.getKeySpace() + ":" + refId));
467+
}
468+
} else if (targetProperty.isCollectionLike()) {
463469

464-
Map<Object, Object> map = new HashMap<Object, Object>();
470+
Collection<?> collection = pUpdate.getValue() instanceof Collection ? (Collection<?>) pUpdate.getValue()
471+
: Collections.<Object> singleton(pUpdate.getValue());
472+
writeCollection(entity.getKeySpace(), pUpdate.getPropertyPath(), collection,
473+
targetProperty.getTypeInformation().getActualType(), sink);
474+
} else if (targetProperty.isMap()) {
465475

466-
if (pUpdate.getValue() instanceof Map) {
467-
map.putAll((Map<?, ?>) pUpdate.getValue());
468-
} else if (pUpdate.getValue() instanceof Map.Entry) {
469-
map.put(((Map.Entry<?, ?>) pUpdate.getValue()).getKey(), ((Map.Entry<?, ?>) pUpdate.getValue()).getValue());
470-
} else {
471-
throw new MappingException(
472-
String.format("Cannot set update value for map property '%s' to '%s'. Please use a Map or Map.Entry.",
473-
pUpdate.getPropertyPath(), pUpdate.getValue()));
474-
}
476+
Map<Object, Object> map = new HashMap<Object, Object>();
475477

476-
writeMap(entity.getKeySpace(), pUpdate.getPropertyPath(), targetProperty.getMapValueType(), map, sink);
477-
} else {
478+
if (pUpdate.getValue() instanceof Map) {
479+
map.putAll((Map<?, ?>) pUpdate.getValue());
480+
} else if (pUpdate.getValue() instanceof Entry) {
481+
map.put(((Entry<?, ?>) pUpdate.getValue()).getKey(), ((Entry<?, ?>) pUpdate.getValue()).getValue());
482+
} else {
483+
throw new MappingException(
484+
String.format("Cannot set update value for map property '%s' to '%s'. Please use a Map or Map.Entry.",
485+
pUpdate.getPropertyPath(), pUpdate.getValue()));
486+
}
478487

479-
writeInternal(entity.getKeySpace(), pUpdate.getPropertyPath(), pUpdate.getValue(),
480-
targetProperty.getTypeInformation(), sink);
488+
writeMap(entity.getKeySpace(), pUpdate.getPropertyPath(), targetProperty.getMapValueType(), map, sink);
489+
} else {
481490

482-
Set<IndexedData> data = indexResolver.resolveIndexesFor(entity.getKeySpace(), pUpdate.getPropertyPath(),
483-
targetProperty.getTypeInformation(), pUpdate.getValue());
491+
writeInternal(entity.getKeySpace(), pUpdate.getPropertyPath(), pUpdate.getValue(),
492+
targetProperty.getTypeInformation(), sink);
484493

485-
if (data.isEmpty()) {
494+
Set<IndexedData> data = indexResolver.resolveIndexesFor(entity.getKeySpace(), pUpdate.getPropertyPath(),
495+
targetProperty.getTypeInformation(), pUpdate.getValue());
486496

487-
data = indexResolver.resolveIndexesFor(entity.getKeySpace(), pUpdate.getPropertyPath(),
488-
targetProperty.getOwner().getTypeInformation(), pUpdate.getValue());
497+
if (data.isEmpty()) {
498+
499+
data = indexResolver.resolveIndexesFor(entity.getKeySpace(), pUpdate.getPropertyPath(),
500+
targetProperty.getOwner().getTypeInformation(), pUpdate.getValue());
489501

490-
}
491-
sink.addIndexedData(data);
492-
}
493502
}
503+
sink.addIndexedData(data);
494504
}
495505
}
496506

@@ -589,10 +599,10 @@ public void doWithPersistentProperty(KeyValuePersistentProperty persistentProper
589599
}
590600
});
591601

592-
writeAssiciation(keyspace, path, entity, value, sink);
602+
writeAssociation(path, entity, value, sink);
593603
}
594604

595-
private void writeAssiciation(final String keyspace, final String path, final KeyValuePersistentEntity<?> entity,
605+
private void writeAssociation(final String path, final KeyValuePersistentEntity<?> entity,
596606
final Object value, final RedisData sink) {
597607

598608
if (value == null) {
@@ -878,7 +888,7 @@ private Class<?> getTypeHint(String path, Bucket bucket, Class<?> fallback) {
878888

879889
/**
880890
* Convert given source to binary representation using the underlying {@link ConversionService}.
881-
*
891+
*
882892
* @param source
883893
* @return
884894
* @throws ConverterNotFoundException
@@ -894,7 +904,7 @@ public byte[] toBytes(Object source) {
894904

895905
/**
896906
* Convert given binary representation to desired target type using the underlying {@link ConversionService}.
897-
*
907+
*
898908
* @param source
899909
* @param type
900910
* @return
@@ -934,7 +944,7 @@ private Object toArray(Collection<Object> source, Class<?> arrayType, Class<?> v
934944

935945
/**
936946
* Set {@link CustomConversions} to be applied.
937-
*
947+
*
938948
* @param customConversions
939949
*/
940950
public void setCustomConversions(CustomConversions customConversions) {

0 commit comments

Comments
 (0)