Skip to content

Commit f6fcbd4

Browse files
committed
Apply converters on simple value reads.
We now apply converters for simple value reads ensuring that e.g. Enum converters are applied. Closes #1689
1 parent 61a1451 commit f6fcbd4

File tree

2 files changed

+49
-8
lines changed

2 files changed

+49
-8
lines changed

spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/MappingRelationalConverter.java

+12-8
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ protected <S> S read(TypeInformation<S> type, RowDocument source) {
307307
* @return the converted object, will never be {@literal null}.
308308
*/
309309
protected <S> S readAggregate(ConversionContext context, RowDocument document,
310-
TypeInformation<? extends S> typeHint) {
310+
TypeInformation<? extends S> typeHint) {
311311
return readAggregate(context, new RowDocumentAccessor(document), typeHint);
312312
}
313313

@@ -321,7 +321,7 @@ protected <S> S readAggregate(ConversionContext context, RowDocument document,
321321
*/
322322
@SuppressWarnings("unchecked")
323323
protected <S> S readAggregate(ConversionContext context, RowDocumentAccessor documentAccessor,
324-
TypeInformation<? extends S> typeHint) {
324+
TypeInformation<? extends S> typeHint) {
325325

326326
Class<? extends S> rawType = typeHint.getType();
327327

@@ -430,8 +430,7 @@ private <T> T doConvert(Object value, Class<? extends T> target) {
430430
}
431431

432432
@SuppressWarnings("ConstantConditions")
433-
private <T> T doConvert(Object value, Class<? extends T> target,
434-
@Nullable Class<? extends T> fallback) {
433+
private <T> T doConvert(Object value, Class<? extends T> target, @Nullable Class<? extends T> fallback) {
435434

436435
if (getConversionService().canConvert(value.getClass(), target) || fallback == null) {
437436
return getConversionService().convert(value, target);
@@ -504,7 +503,7 @@ public RelationalPropertyValueProvider withContext(ConversionContext context) {
504503
entity, contextualizing, context.getPath().getCurrentObject());
505504

506505
return new ConverterAwareSpELExpressionParameterValueProvider(context, evaluator, getConversionService(),
507-
new ConvertingParameterValueProvider<>( parameterProvider::getParameterValue));
506+
new ConvertingParameterValueProvider<>(parameterProvider::getParameterValue));
508507
}
509508

510509
private <S> S populateProperties(ConversionContext context, RelationalPersistentEntity<S> entity,
@@ -641,6 +640,11 @@ private Object getPotentiallyConvertedSimpleWrite(Object value) {
641640
protected Object getPotentiallyConvertedSimpleRead(Object value, TypeInformation<?> type) {
642641

643642
Class<?> target = type.getType();
643+
644+
if (getConversions().hasCustomReadTarget(value.getClass(), target)) {
645+
return getConversionService().convert(value, TypeDescriptor.forObject(value), createTypeDescriptor(type));
646+
}
647+
644648
if (ClassUtils.isAssignableValue(target, value)) {
645649
return value;
646650
}
@@ -787,8 +791,7 @@ protected DefaultConversionContext(RelationalConverter sourceConverter,
787791

788792
@SuppressWarnings("unchecked")
789793
@Override
790-
public <S> S convert(Object source, TypeInformation<? extends S> typeHint,
791-
ConversionContext context) {
794+
public <S> S convert(Object source, TypeInformation<? extends S> typeHint, ConversionContext context) {
792795

793796
Assert.notNull(source, "Source must not be null");
794797
Assert.notNull(typeHint, "TypeInformation must not be null");
@@ -1196,7 +1199,8 @@ protected <T> T potentiallyConvertSpelValue(Object object, Parameter<T, Relation
11961199
}
11971200
}
11981201

1199-
private record PropertyTranslatingPropertyAccessor<T> (PersistentPropertyAccessor<T> delegate,
1202+
private record PropertyTranslatingPropertyAccessor<T>(
1203+
PersistentPropertyAccessor<T> delegate,
12001204
PersistentPropertyTranslator propertyTranslator) implements PersistentPropertyAccessor<T> {
12011205

12021206
static <T> PersistentPropertyAccessor<T> create(PersistentPropertyAccessor<T> delegate,

spring-data-relational/src/test/java/org/springframework/data/relational/core/conversion/MappingRelationalConverterUnitTests.java

+37
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import static org.assertj.core.api.Assertions.*;
1919

20+
import java.util.Arrays;
2021
import java.util.Collections;
2122
import java.util.Date;
2223
import java.util.EnumSet;
@@ -26,13 +27,16 @@
2627
import java.util.Set;
2728

2829
import org.junit.jupiter.api.Test;
30+
2931
import org.springframework.beans.factory.annotation.Value;
32+
import org.springframework.core.convert.converter.Converter;
3033
import org.springframework.data.annotation.Id;
3134
import org.springframework.data.annotation.PersistenceCreator;
3235
import org.springframework.data.convert.ConverterBuilder;
3336
import org.springframework.data.convert.ConverterBuilder.ConverterAware;
3437
import org.springframework.data.convert.CustomConversions;
3538
import org.springframework.data.convert.CustomConversions.StoreConversions;
39+
import org.springframework.data.convert.ReadingConverter;
3640
import org.springframework.data.mapping.model.SimpleTypeHolder;
3741
import org.springframework.data.projection.EntityProjection;
3842
import org.springframework.data.relational.core.mapping.Column;
@@ -83,6 +87,20 @@ void shouldEvaluateExpression() {
8387
assertThat(result.name).isEqualTo("bar");
8488
}
8589

90+
@Test
91+
// GH-1689
92+
void shouldApplySimpleTypeConverterSimpleType() {
93+
94+
converter = new MappingRelationalConverter(converter.getMappingContext(),
95+
new CustomConversions(StoreConversions.NONE, List.of(MyEnumConverter.INSTANCE)));
96+
97+
RowDocument document = new RowDocument().append("my_enum", "one");
98+
99+
WithMyEnum result = converter.read(WithMyEnum.class, document);
100+
101+
assertThat(result.myEnum).isEqualTo(MyEnum.ONE);
102+
}
103+
86104
@Test // GH-1586
87105
void shouldReadNonstaticInner() {
88106

@@ -328,4 +346,23 @@ interface AddressProjection {
328346
String getStreet();
329347
}
330348

349+
record WithMyEnum(MyEnum myEnum) {
350+
}
351+
352+
enum MyEnum {
353+
ONE, TWO,
354+
}
355+
356+
@ReadingConverter
357+
enum MyEnumConverter implements Converter<String, MyEnum> {
358+
359+
INSTANCE;
360+
361+
@Override
362+
public MyEnum convert(String source) {
363+
return MyEnum.valueOf(source.toUpperCase());
364+
}
365+
366+
}
367+
331368
}

0 commit comments

Comments
 (0)