diff --git a/src/main/java/org/springframework/data/repository/query/ResultProcessor.java b/src/main/java/org/springframework/data/repository/query/ResultProcessor.java index 2414a278b..073f0d43a 100644 --- a/src/main/java/org/springframework/data/repository/query/ResultProcessor.java +++ b/src/main/java/org/springframework/data/repository/query/ResultProcessor.java @@ -127,7 +127,7 @@ public class ResultProcessor { Assert.notNull(preparingConverter, "Preparing converter must not be null!"); - ChainingConverter converter = ChainingConverter.of(preparingConverter).and(this.converter); + ChainingConverter converter = ChainingConverter.of(type.getReturnedType(), preparingConverter).and(this.converter); if (source instanceof Page && method.isPageQuery()) { return (T) ((Page) source).map(converter); @@ -151,6 +151,7 @@ public class ResultProcessor { @RequiredArgsConstructor(staticName = "of") private static class ChainingConverter implements Converter { + private final @NonNull Class targetType; private final @NonNull Converter delegate; /** @@ -164,11 +165,13 @@ public class ResultProcessor { Assert.notNull(converter, "Converter must not be null!"); - return new ChainingConverter(new Converter() { + return new ChainingConverter(targetType, new Converter() { @Override public Object convert(Object source) { - return converter.convert(ChainingConverter.this.convert(source)); + + Object intermediate = ChainingConverter.this.convert(source); + return targetType.isInstance(intermediate) ? intermediate : converter.convert(intermediate); } }); } diff --git a/src/test/java/org/springframework/data/repository/query/ResultProcessorUnitTests.java b/src/test/java/org/springframework/data/repository/query/ResultProcessorUnitTests.java index 8e046b38d..265d29f86 100644 --- a/src/test/java/org/springframework/data/repository/query/ResultProcessorUnitTests.java +++ b/src/test/java/org/springframework/data/repository/query/ResultProcessorUnitTests.java @@ -28,6 +28,7 @@ import java.util.Map; import org.junit.Test; import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.convert.converter.Converter; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; @@ -61,7 +62,7 @@ public class ResultProcessorUnitTests { @Test public void createsProjectionFromProperties() throws Exception { - ResultProcessor information = getFactory("findOneProjection"); + ResultProcessor information = getProcessor("findOneProjection"); SampleProjection result = information.processResult(Arrays.asList("Matthews")); @@ -75,7 +76,7 @@ public class ResultProcessorUnitTests { @SuppressWarnings("unchecked") public void createsListOfProjectionsFormNestedLists() throws Exception { - ResultProcessor information = getFactory("findAllProjection"); + ResultProcessor information = getProcessor("findAllProjection"); List columns = Arrays.asList("Matthews"); List> source = new ArrayList>(Arrays.asList(columns)); @@ -93,7 +94,7 @@ public class ResultProcessorUnitTests { @SuppressWarnings("unchecked") public void createsListOfProjectionsFromMaps() throws Exception { - ResultProcessor information = getFactory("findAllProjection"); + ResultProcessor information = getProcessor("findAllProjection"); List> source = new ArrayList>( Arrays.asList(Collections. singletonMap("lastname", "Matthews"))); @@ -110,7 +111,7 @@ public class ResultProcessorUnitTests { @Test public void createsListOfProjectionsFromEntity() throws Exception { - ResultProcessor information = getFactory("findAllProjection"); + ResultProcessor information = getProcessor("findAllProjection"); List source = new ArrayList(Arrays.asList(new Sample("Dave", "Matthews"))); List result = information.processResult(source); @@ -125,7 +126,7 @@ public class ResultProcessorUnitTests { @Test public void createsPageOfProjectionsFromEntity() throws Exception { - ResultProcessor information = getFactory("findPageProjection", Pageable.class); + ResultProcessor information = getProcessor("findPageProjection", Pageable.class); Page source = new PageImpl(Arrays.asList(new Sample("Dave", "Matthews"))); Page result = information.processResult(source); @@ -140,7 +141,7 @@ public class ResultProcessorUnitTests { @Test public void createsDynamicProjectionFromEntity() throws Exception { - ResultProcessor information = getFactory("findOneOpenProjection"); + ResultProcessor information = getProcessor("findOneOpenProjection"); OpenProjection result = information.processResult(new Sample("Dave", "Matthews")); @@ -156,7 +157,7 @@ public class ResultProcessorUnitTests { ParameterAccessor accessor = mock(ParameterAccessor.class); - ResultProcessor factory = getFactory("findOneDynamic", Class.class); + ResultProcessor factory = getProcessor("findOneDynamic", Class.class); assertThat(factory.withDynamicProjection(null), is(factory)); assertThat(factory.withDynamicProjection(accessor), is(factory)); @@ -166,7 +167,26 @@ public class ResultProcessorUnitTests { assertThat(processor.getReturnedType().getReturnedType(), is(typeCompatibleWith(SampleProjection.class))); } - private static ResultProcessor getFactory(String methodName, Class... parameters) throws Exception { + /** + * @see DATACMNS-89 + */ + @Test + public void refrainsFromProjectingIfThePreparingConverterReturnsACompatibleInstance() throws Exception { + + ResultProcessor processor = getProcessor("findAllDtos"); + + Object result = processor.processResult(new Sample("Dave", "Matthews"), new Converter() { + + @Override + public Object convert(Object source) { + return new SampleDTO(); + } + }); + + assertThat(result, is(instanceOf(SampleDTO.class))); + } + + private static ResultProcessor getProcessor(String methodName, Class... parameters) throws Exception { return getQueryMethod(methodName, parameters).getResultProcessor(); }