Simpler check to avoid primitive conversion in ConvertingPropertyAccessor.
We now use Spring's ClassUtils.isAssignable(…) directly. Unit tests to verify that conversion is skipped for primitive / boxed scenarios. See #2546.
This commit is contained in:
@@ -116,7 +116,7 @@ public class ConvertingPropertyAccessor<T> extends SimplePersistentPropertyPathA
|
||||
|
||||
return (S) (source == null //
|
||||
? null //
|
||||
: ClassUtils.resolvePrimitiveIfNecessary(type).isAssignableFrom(source.getClass()) //
|
||||
: ClassUtils.isAssignable(type, source.getClass())
|
||||
? source //
|
||||
: conversionService.convert(source, type));
|
||||
}
|
||||
|
||||
@@ -16,15 +16,23 @@
|
||||
package org.springframework.data.mapping.model;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.DynamicTest;
|
||||
import org.junit.jupiter.api.Named;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.mapping.PersistentPropertyPath;
|
||||
import org.springframework.data.mapping.context.SampleMappingContext;
|
||||
@@ -133,6 +141,40 @@ public class ConvertingPropertyAccessorUnitTests {
|
||||
assertThat(convertingAccessor.getBean().getCustomer().getFirstname()).isEqualTo("2");
|
||||
}
|
||||
|
||||
@TestFactory // #2546
|
||||
Stream<DynamicTest> doesNotInvokeConversionForMatchingPrimitives() {
|
||||
|
||||
IntegerWrapper wrapper = new IntegerWrapper();
|
||||
wrapper.primitive = 42;
|
||||
wrapper.boxed = 42;
|
||||
|
||||
SampleMappingContext context = new SampleMappingContext();
|
||||
PersistentEntity<Object, SamplePersistentProperty> entity = context
|
||||
.getRequiredPersistentEntity(IntegerWrapper.class);
|
||||
|
||||
SamplePersistentProperty primitiveProperty = entity.getRequiredPersistentProperty("primitive");
|
||||
SamplePersistentProperty boxedProperty = entity.getRequiredPersistentProperty("boxed");
|
||||
|
||||
PersistentPropertyAccessor<IntegerWrapper> accessor = entity.getPropertyAccessor(wrapper);
|
||||
ConversionService conversionService = mock(ConversionService.class);
|
||||
|
||||
ConvertingPropertyAccessor<IntegerWrapper> convertingAccessor = new ConvertingPropertyAccessor<>(accessor,
|
||||
conversionService);
|
||||
|
||||
Stream<PrimitiveFixture> fixtures = Stream.of(
|
||||
PrimitiveFixture.$(boxedProperty, int.class),
|
||||
PrimitiveFixture.$(boxedProperty, Integer.class),
|
||||
PrimitiveFixture.$(primitiveProperty, int.class),
|
||||
PrimitiveFixture.$(primitiveProperty, Integer.class));
|
||||
|
||||
return DynamicTest.stream(fixtures, it -> {
|
||||
|
||||
convertingAccessor.getProperty(it.property, it.type);
|
||||
|
||||
verify(conversionService, never()).convert(any(), eq(it.type));
|
||||
});
|
||||
}
|
||||
|
||||
private static ConvertingPropertyAccessor getAccessor(Object entity, ConversionService conversionService) {
|
||||
|
||||
PersistentPropertyAccessor wrapper = new BeanWrapper<>(entity);
|
||||
@@ -161,4 +203,26 @@ public class ConvertingPropertyAccessorUnitTests {
|
||||
static class Customer {
|
||||
String firstname;
|
||||
}
|
||||
|
||||
static class IntegerWrapper {
|
||||
int primitive;
|
||||
Integer boxed;
|
||||
}
|
||||
|
||||
@Value(staticConstructor = "$")
|
||||
static class PrimitiveFixture implements Named<PrimitiveFixture> {
|
||||
|
||||
PersistentProperty<?> property;
|
||||
Class<?> type;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return String.format("Accessing %s as %s does not cause conversion.", property, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrimitiveFixture getPayload() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user