Skip to content

Commit 9b12bce

Browse files
committed
Defer PersistentEntity lookup until actual DTO conversion.
We now lazily instantiate DtoInstantiatingConverter to defer the entity lookup if needed. Closes #612
1 parent 60fd842 commit 9b12bce

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

src/main/java/org/springframework/data/r2dbc/repository/query/R2dbcQueryExecution.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.springframework.data.relational.repository.query.DtoInstantiatingConverter;
2929
import org.springframework.data.repository.query.ResultProcessor;
3030
import org.springframework.data.repository.query.ReturnedType;
31+
import org.springframework.data.util.Lazy;
3132
import org.springframework.data.util.ReflectionUtils;
3233
import org.springframework.r2dbc.core.RowsFetchSpec;
3334
import org.springframework.util.ClassUtils;
@@ -72,13 +73,16 @@ final class ResultProcessingConverter implements Converter<Object, Object> {
7273
private final ResultProcessor processor;
7374
private final MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> mappingContext;
7475
private final EntityInstantiators instantiators;
76+
private final Lazy<DtoInstantiatingConverter> converter;
7577

7678
ResultProcessingConverter(ResultProcessor processor,
7779
MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> mappingContext,
7880
EntityInstantiators instantiators) {
7981
this.processor = processor;
8082
this.mappingContext = mappingContext;
8183
this.instantiators = instantiators;
84+
this.converter = Lazy.of(() -> new DtoInstantiatingConverter(processor.getReturnedType().getReturnedType(),
85+
this.mappingContext, this.instantiators));
8286
}
8387

8488
/* (non-Javadoc)
@@ -108,10 +112,7 @@ public Object convert(Object source) {
108112
}
109113
}
110114

111-
Converter<Object, Object> converter = new DtoInstantiatingConverter(returnedType.getReturnedType(),
112-
this.mappingContext, this.instantiators);
113-
114-
return this.processor.processResult(source, converter);
115+
return this.processor.processResult(source, it -> this.converter.get().convert(it));
115116
}
116117
}
117118
}

src/test/java/org/springframework/data/r2dbc/repository/query/StringBasedR2dbcQueryUnitTests.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,15 @@
1818
import static org.assertj.core.api.Assertions.*;
1919
import static org.mockito.Mockito.*;
2020

21+
import io.r2dbc.spi.test.MockColumnMetadata;
22+
import io.r2dbc.spi.test.MockResult;
23+
import io.r2dbc.spi.test.MockRow;
24+
import io.r2dbc.spi.test.MockRowMetadata;
25+
import reactor.core.publisher.Flux;
26+
import reactor.test.StepVerifier;
27+
2128
import java.lang.reflect.Method;
29+
import java.time.LocalDate;
2230

2331
import org.junit.jupiter.api.BeforeEach;
2432
import org.junit.jupiter.api.Test;
@@ -38,6 +46,7 @@
3846
import org.springframework.data.r2dbc.dialect.PostgresDialect;
3947
import org.springframework.data.r2dbc.mapping.R2dbcMappingContext;
4048
import org.springframework.data.r2dbc.repository.Query;
49+
import org.springframework.data.r2dbc.testing.StatementRecorder;
4150
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
4251
import org.springframework.data.repository.Repository;
4352
import org.springframework.data.repository.core.RepositoryMetadata;
@@ -275,6 +284,29 @@ void usesDtoTypeForDtoResultMapping() {
275284
assertThat(query.resolveResultType(query.getQueryMethod().getResultProcessor())).isEqualTo(PersonDto.class);
276285
}
277286

287+
@Test // gh-475
288+
void selectsSimpleType() {
289+
290+
MockRowMetadata metadata = MockRowMetadata.builder()
291+
.columnMetadata(MockColumnMetadata.builder().name("date").build()).build();
292+
LocalDate value = LocalDate.now();
293+
MockResult result = MockResult.builder().rowMetadata(metadata)
294+
.row(MockRow.builder().identified(0, LocalDate.class, value).build()).build();
295+
296+
StatementRecorder recorder = StatementRecorder.newInstance();
297+
recorder.addStubbing(s -> s.equals("SELECT MAX(DATE)"), result);
298+
299+
databaseClient = DatabaseClient.builder() //
300+
.connectionFactory(recorder) //
301+
.bindMarkers(PostgresDialect.INSTANCE.getBindMarkersFactory()).build();
302+
303+
StringBasedR2dbcQuery query = getQueryMethod("findAllLocalDates");
304+
305+
Flux<Object> flux = (Flux) query.execute(new Object[0]);
306+
307+
flux.as(StepVerifier::create).expectNext(value).verifyComplete();
308+
}
309+
278310
private StringBasedR2dbcQuery getQueryMethod(String name, Class<?>... args) {
279311

280312
Method method = ReflectionUtils.findMethod(SampleRepository.class, name, args);
@@ -329,6 +361,9 @@ private interface SampleRepository extends Repository<Person, String> {
329361

330362
@Query("SELECT * FROM person")
331363
PersonProjection findAsInterfaceProjection();
364+
365+
@Query("SELECT MAX(DATE)")
366+
Flux<LocalDate> findAllLocalDates();
332367
}
333368

334369
static class PersonDto {

0 commit comments

Comments
 (0)