Skip to content

Commit 902b1cb

Browse files
committed
Add support for streamed query results.
Use queryForStream for streamed query results. ResultSetExtractor is ignored because it cannot be used together with streams. Original pull request spring-projects#176 Closes spring-projects#356
1 parent ba65318 commit 902b1cb

File tree

3 files changed

+46
-3
lines changed

3 files changed

+46
-3
lines changed

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/AbstractJdbcQuery.java

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020 the original author or authors.
2+
* Copyright 2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
1616
package org.springframework.data.jdbc.repository.query;
1717

1818
import java.util.List;
19+
import java.util.stream.Stream;
1920

2021
import org.springframework.dao.EmptyResultDataAccessException;
2122
import org.springframework.data.repository.query.RepositoryQuery;
@@ -35,6 +36,7 @@
3536
* @author Oliver Gierke
3637
* @author Maciej Walkowiak
3738
* @author Mark Paluch
39+
* @author Dennis Effing
3840
* @since 2.0
3941
*/
4042
public abstract class AbstractJdbcQuery implements RepositoryQuery {
@@ -89,10 +91,14 @@ protected JdbcQueryExecution<?> getQueryExecution(JdbcQueryMethod queryMethod,
8991
return createModifyingQueryExecutor();
9092
}
9193

92-
if (queryMethod.isCollectionQuery() || queryMethod.isStreamQuery()) {
94+
if (queryMethod.isCollectionQuery()) {
9395
return extractor != null ? getQueryExecution(extractor) : collectionQuery(rowMapper);
9496
}
9597

98+
if (queryMethod.isStreamQuery()) {
99+
return streamQuery(rowMapper);
100+
}
101+
96102
return extractor != null ? getQueryExecution(extractor) : singleObjectQuery(rowMapper);
97103
}
98104

@@ -123,6 +129,10 @@ private <T> JdbcQueryExecution<List<T>> collectionQuery(RowMapper<T> rowMapper)
123129
return getQueryExecution(new RowMapperResultSetExtractor<>(rowMapper));
124130
}
125131

132+
private <T> JdbcQueryExecution<Stream<T>> streamQuery(RowMapper<T> rowMapper) {
133+
return (query, parameters) -> operations.queryForStream(query, parameters, rowMapper);
134+
}
135+
126136
private <T> JdbcQueryExecution<T> getQueryExecution(ResultSetExtractor<T> resultSetExtractor) {
127137
return (query, parameters) -> operations.query(query, parameters, resultSetExtractor);
128138
}

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/QueryAnnotationHsqlIntegrationTests.java

+20
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
* @author Jens Schauder
5050
* @author Kazuki Shimizu
5151
* @author Mark Paluch
52+
* @author Dennis Effing
5253
*/
5354
@Transactional
5455
@ActiveProfiles("hsql")
@@ -170,6 +171,21 @@ public void executeCustomQueryWithReturnTypeIsStream() {
170171
.containsExactlyInAnyOrder("a", "b");
171172
}
172173

174+
@Test // DATAJDBC-356
175+
public void executeCustomQueryWithNamedParameterAndReturnTypeIsStream() {
176+
177+
repository.save(dummyEntity("a"));
178+
repository.save(dummyEntity("b"));
179+
repository.save(dummyEntity("c"));
180+
181+
Stream<DummyEntity> entities = repository.findByNamedRangeWithNamedParameterAndReturnTypeIsStream("a", "c");
182+
183+
assertThat(entities) //
184+
.extracting(e -> e.name) //
185+
.containsExactlyInAnyOrder("b");
186+
187+
}
188+
173189
@Test // DATAJDBC-175
174190
public void executeCustomQueryWithReturnTypeIsNumber() {
175191

@@ -289,6 +305,10 @@ private interface DummyEntityRepository extends CrudRepository<DummyEntity, Long
289305
@Query("SELECT * FROM DUMMY_ENTITY")
290306
Stream<DummyEntity> findAllWithReturnTypeIsStream();
291307

308+
@Query("SELECT * FROM DUMMY_ENTITY WHERE name < :upper and name > :lower")
309+
Stream<DummyEntity> findByNamedRangeWithNamedParameterAndReturnTypeIsStream(@Param("lower") String lower,
310+
@Param("upper") String upper);
311+
292312
// DATAJDBC-175
293313
@Query("SELECT count(*) FROM DUMMY_ENTITY WHERE name like concat('%', :name, '%')")
294314
int countByNameContaining(@Param("name") String name);

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQueryUnitTests.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020 the original author or authors.
2+
* Copyright 2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
3535
import org.springframework.jdbc.core.ResultSetExtractor;
3636
import org.springframework.jdbc.core.RowMapper;
3737
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
38+
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
3839

3940
/**
4041
* Unit tests for {@link StringBasedJdbcQuery}.
@@ -44,6 +45,7 @@
4445
* @author Maciej Walkowiak
4546
* @author Evgeni Dimitrov
4647
* @author Mark Paluch
48+
* @author Dennis Effing
4749
*/
4850
public class StringBasedJdbcQueryUnitTests {
4951

@@ -151,6 +153,17 @@ public void customResultSetExtractorAndRowMapperGetCombined() {
151153
"RowMapper is not expected to be custom");
152154
}
153155

156+
@Test // DATAJDBC-356
157+
void streamQueryCallsQueryForStreamOnOperations() {
158+
doReturn(true).when(queryMethod).isStreamQuery();
159+
doReturn("some sql statement").when(queryMethod).getDeclaredQuery();
160+
161+
StringBasedJdbcQuery subject = createQuery();
162+
subject.execute(new Object[] {});
163+
164+
verify(operations).queryForStream(eq("some sql statement"), any(SqlParameterSource.class), eq(defaultRowMapper));
165+
}
166+
154167
/**
155168
* The whole purpose of this method is to easily generate a {@link DefaultParameters} instance during test setup.
156169
*/

0 commit comments

Comments
 (0)