Defer PersistentEntity lookup until actual DTO conversion.
We now lazily instantiate DtoInstantiatingConverter to defer the entity lookup if needed. Closes #612
This commit is contained in:
@@ -29,6 +29,7 @@ import org.springframework.data.relational.core.sql.SqlIdentifier;
|
||||
import org.springframework.data.relational.repository.query.DtoInstantiatingConverter;
|
||||
import org.springframework.data.repository.query.ResultProcessor;
|
||||
import org.springframework.data.repository.query.ReturnedType;
|
||||
import org.springframework.data.util.Lazy;
|
||||
import org.springframework.data.util.ReflectionUtils;
|
||||
import org.springframework.r2dbc.core.FetchSpec;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -73,6 +74,7 @@ interface R2dbcQueryExecution {
|
||||
private final ResultProcessor processor;
|
||||
private final MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> mappingContext;
|
||||
private final EntityInstantiators instantiators;
|
||||
private final Lazy<DtoInstantiatingConverter> converter;
|
||||
|
||||
ResultProcessingConverter(ResultProcessor processor,
|
||||
MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> mappingContext,
|
||||
@@ -80,6 +82,8 @@ interface R2dbcQueryExecution {
|
||||
this.processor = processor;
|
||||
this.mappingContext = mappingContext;
|
||||
this.instantiators = instantiators;
|
||||
this.converter = Lazy.of(() -> new DtoInstantiatingConverter(processor.getReturnedType().getReturnedType(),
|
||||
this.mappingContext, this.instantiators));
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -109,10 +113,7 @@ interface R2dbcQueryExecution {
|
||||
}
|
||||
}
|
||||
|
||||
Converter<Object, Object> converter = new DtoInstantiatingConverter(returnedType.getReturnedType(),
|
||||
this.mappingContext, this.instantiators);
|
||||
|
||||
return this.processor.processResult(source, converter);
|
||||
return this.processor.processResult(source, it -> this.converter.get().convert(it));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,15 @@ import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import io.r2dbc.spi.test.MockColumnMetadata;
|
||||
import io.r2dbc.spi.test.MockResult;
|
||||
import io.r2dbc.spi.test.MockRow;
|
||||
import io.r2dbc.spi.test.MockRowMetadata;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.LocalDate;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -38,6 +46,7 @@ import org.springframework.data.r2dbc.core.ReactiveDataAccessStrategy;
|
||||
import org.springframework.data.r2dbc.dialect.PostgresDialect;
|
||||
import org.springframework.data.r2dbc.mapping.R2dbcMappingContext;
|
||||
import org.springframework.data.r2dbc.repository.Query;
|
||||
import org.springframework.data.r2dbc.testing.StatementRecorder;
|
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
@@ -274,6 +283,29 @@ public class StringBasedR2dbcQueryUnitTests {
|
||||
assertThat(query.resolveResultType(query.getQueryMethod().getResultProcessor())).isEqualTo(PersonDto.class);
|
||||
}
|
||||
|
||||
@Test // gh-612
|
||||
void selectsSimpleType() {
|
||||
|
||||
MockRowMetadata metadata = MockRowMetadata.builder()
|
||||
.columnMetadata(MockColumnMetadata.builder().name("date").build()).build();
|
||||
LocalDate value = LocalDate.now();
|
||||
MockResult result = MockResult.builder().rowMetadata(metadata)
|
||||
.row(MockRow.builder().identified(0, LocalDate.class, value).build()).build();
|
||||
|
||||
StatementRecorder recorder = StatementRecorder.newInstance();
|
||||
recorder.addStubbing(s -> s.equals("SELECT MAX(DATE)"), result);
|
||||
|
||||
databaseClient = DatabaseClient.builder() //
|
||||
.connectionFactory(recorder) //
|
||||
.bindMarkers(PostgresDialect.INSTANCE.getBindMarkersFactory()).build();
|
||||
|
||||
StringBasedR2dbcQuery query = getQueryMethod("findAllLocalDates");
|
||||
|
||||
Flux<Object> flux = (Flux) query.execute(new Object[0]);
|
||||
|
||||
flux.as(StepVerifier::create).expectNext(value).verifyComplete();
|
||||
}
|
||||
|
||||
private StringBasedR2dbcQuery getQueryMethod(String name, Class<?>... args) {
|
||||
|
||||
Method method = ReflectionUtils.findMethod(SampleRepository.class, name, args);
|
||||
@@ -328,6 +360,9 @@ public class StringBasedR2dbcQueryUnitTests {
|
||||
|
||||
@Query("SELECT * FROM person")
|
||||
PersonProjection findAsInterfaceProjection();
|
||||
|
||||
@Query("SELECT MAX(DATE)")
|
||||
Flux<LocalDate> findAllLocalDates();
|
||||
}
|
||||
|
||||
static class PersonDto {
|
||||
|
||||
Reference in New Issue
Block a user