Browse Source

Back-off in ResultProcessor if the result object is an instance of the target type.

We now do not attempt to convert the object if it is an instance of the declared target type.

Closes #2347.
pull/2367/head
Mark Paluch 5 years ago
parent
commit
d27ac79771
No known key found for this signature in database
GPG Key ID: 4406B84C1661DCD1
  1. 4
      src/main/java/org/springframework/data/repository/query/ResultProcessor.java
  2. 56
      src/test/java/org/springframework/data/repository/query/ResultProcessorUnitTests.java

4
src/main/java/org/springframework/data/repository/query/ResultProcessor.java

@ -219,6 +219,10 @@ public class ResultProcessor { @@ -219,6 +219,10 @@ public class ResultProcessor {
return new ChainingConverter(targetType, source -> {
if (source == null || targetType.isInstance(source)) {
return source;
}
Object intermediate = ChainingConverter.this.convert(source);
return intermediate == null || targetType.isInstance(intermediate) ? intermediate

56
src/test/java/org/springframework/data/repository/query/ResultProcessorUnitTests.java

@ -19,8 +19,10 @@ import static org.assertj.core.api.Assertions.*; @@ -19,8 +19,10 @@ import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import io.reactivex.Flowable;
import lombok.Getter;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import rx.Observable;
import rx.Single;
@ -308,6 +310,37 @@ class ResultProcessorUnitTests { @@ -308,6 +310,37 @@ class ResultProcessorUnitTests {
assertThat(content.get(0)).isInstanceOf(SampleProjection.class);
}
@Test // GH-2347
void findByListSkipsConversionIfTypeAlreadyMatches() throws Exception {
List<AbstractDto> result = getProcessor("findAllAbstractDtos")
.processResult(Collections.singletonList(new ConcreteDto("Walter", "White")));
assertThat(result.get(0)).isInstanceOf(ConcreteDto.class);
}
@Test // GH-2347
void streamBySkipsConversionIfTypeAlreadyMatches() throws Exception {
Stream<AbstractDto> result = getProcessor("streamAllAbstractDtos")
.processResult(Stream.of(new ConcreteDto("Walter", "White")));
assertThat(result.findFirst().get()).isInstanceOf(ConcreteDto.class);
}
@Test // GH-2347
void findFluxSkipsConversionIfTypeAlreadyMatches() throws Exception {
Flux<AbstractDto> result = getProcessor("findFluxOfAbstractDtos")
.processResult(Flux.just(new ConcreteDto("Walter", "White")));
result.as(StepVerifier::create) //
.consumeNextWith(actual -> {
assertThat(actual).isInstanceOf(ConcreteDto.class);
}).verifyComplete();
}
private static ResultProcessor getProcessor(String methodName, Class<?>... parameters) throws Exception {
return getQueryMethod(methodName, parameters).getResultProcessor();
}
@ -356,6 +389,12 @@ class ResultProcessorUnitTests { @@ -356,6 +389,12 @@ class ResultProcessorUnitTests {
Observable<SampleProjection> findObservableProjection();
Flowable<SampleProjection> findFlowableProjection();
List<AbstractDto> findAllAbstractDtos();
Stream<AbstractDto> streamAllAbstractDtos();
Flux<AbstractDto> findFluxOfAbstractDtos();
}
static class Sample {
@ -367,6 +406,23 @@ class ResultProcessorUnitTests { @@ -367,6 +406,23 @@ class ResultProcessorUnitTests {
}
}
@Getter
static abstract class AbstractDto {
final String firstname, lastname;
public AbstractDto(String firstname, String lastname) {
this.firstname = firstname;
this.lastname = lastname;
}
}
static class ConcreteDto extends AbstractDto {
public ConcreteDto(String firstname, String lastname) {
super(firstname, lastname);
}
}
static class SampleDto {}
@lombok.Value

Loading…
Cancel
Save