DATAREDIS-909 - Fix constructor creation of entities with collection-typed properties.
We now consider the property type in value conversion for constructor arguments to provide the appropriate value type. Previously, we considered the component type which converted a Collection<T> to a single T that caused downstream ClassCastException. Original Pull Request: #378
This commit is contained in:
committed by
Christoph Strobl
parent
6d43ddf6d0
commit
e31b32eb5c
@@ -21,17 +21,8 @@ import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -253,7 +244,6 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
return (R) accessor.getBean();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
protected Object readProperty(String path, RedisData source, RedisPersistentProperty persistentProperty) {
|
||||
|
||||
@@ -466,10 +456,9 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
targetProperty = getTargetPropertyOrNullForPath(path.replaceAll("\\.\\[.*\\]", ""), update.getTarget());
|
||||
|
||||
TypeInformation<?> ti = targetProperty == null ? ClassTypeInformation.OBJECT
|
||||
: (targetProperty.isMap()
|
||||
? (targetProperty.getTypeInformation().getMapValueType() != null
|
||||
? targetProperty.getTypeInformation().getRequiredMapValueType() : ClassTypeInformation.OBJECT)
|
||||
: targetProperty.getTypeInformation().getActualType());
|
||||
: (targetProperty.isMap() ? (targetProperty.getTypeInformation().getMapValueType() != null
|
||||
? targetProperty.getTypeInformation().getRequiredMapValueType()
|
||||
: ClassTypeInformation.OBJECT) : targetProperty.getTypeInformation().getActualType());
|
||||
|
||||
writeInternal(entity.getKeySpace(), pUpdate.getPropertyPath(), pUpdate.getValue(), ti, sink);
|
||||
return;
|
||||
@@ -1055,11 +1044,11 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
|
||||
Object value = readProperty(path, source, property);
|
||||
|
||||
if (value != null && !property.getActualType().isInstance(value)) {
|
||||
return (T) conversionService.convert(value, property.getActualType());
|
||||
if (value == null || ClassUtils.isAssignableValue(property.getType(), value)) {
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
return (T) value;
|
||||
return (T) conversionService.convert(value, property.getType());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.redis.core.convert;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@@ -31,6 +32,7 @@ import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
@@ -213,4 +215,11 @@ public class ConversionTestEntities {
|
||||
Map<Double, String> decimalMapKeyMapping;
|
||||
Map<Date, String> dateMapKeyMapping;
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
static class Device {
|
||||
|
||||
final Instant now;
|
||||
final Set<String> profiles;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1472,6 +1472,18 @@ public class MappingRedisConverterUnitTests {
|
||||
assertThat(result.list.get(2), instanceOf(Date.class));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-909
|
||||
public void shouldWriteReadObjectWithConstructorConversion() {
|
||||
|
||||
Device sample = new Device(Instant.now(), Collections.singleton("foo"));
|
||||
|
||||
RedisData rd = write(sample);
|
||||
|
||||
Device result = converter.read(Device.class, rd);
|
||||
assertThat(result.now, equalTo(sample.now));
|
||||
assertThat(result.profiles, equalTo(sample.profiles));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-509
|
||||
public void writeHandlesArraysOfPrimitivesProperly() {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user