15
15
*/
16
16
package org .springframework .data .jdbc .repository .support ;
17
17
18
- import java .lang .reflect .Constructor ;
19
- import java .util .List ;
20
-
21
18
import org .springframework .beans .BeanUtils ;
22
19
import org .springframework .context .ApplicationEventPublisher ;
23
20
import org .springframework .dao .EmptyResultDataAccessException ;
37
34
import org .springframework .util .ClassUtils ;
38
35
import org .springframework .util .StringUtils ;
39
36
37
+ import java .lang .reflect .Constructor ;
38
+ import java .util .List ;
39
+ import java .util .Spliterator ;
40
+ import java .util .Spliterators ;
41
+ import java .util .function .Supplier ;
42
+ import java .util .stream .Stream ;
43
+ import java .util .stream .StreamSupport ;
44
+
40
45
/**
41
46
* A query to be executed based on a repository method, it's annotated SQL query and the arguments provided to the
42
47
* method.
@@ -103,9 +108,16 @@ private QueryExecutor<Object> createExecutor(JdbcQueryMethod queryMethod, @Nulla
103
108
if (queryMethod .isModifyingQuery ()) {
104
109
return createModifyingQueryExecutor (query );
105
110
}
111
+
112
+ if (queryMethod .isOpenStreamQuery ()) {
113
+ QueryExecutor <Object > innerExecutor = createRowMapperOpenQueryStreamExecutor (query , rowMapper , extractor );
114
+ return createOpenStreamQueryExecutor (innerExecutor );
115
+ }
116
+
106
117
if (queryMethod .isCollectionQuery () || queryMethod .isStreamQuery ()) {
107
118
QueryExecutor <Object > innerExecutor = extractor != null ? createResultSetExtractorQueryExecutor (query , extractor )
108
119
: createListRowMapperQueryExecutor (query , rowMapper );
120
+
109
121
return createCollectionQueryExecutor (innerExecutor );
110
122
}
111
123
@@ -170,6 +182,19 @@ private QueryExecutor<Object> createModifyingQueryExecutor(String query) {
170
182
};
171
183
}
172
184
185
+ private QueryExecutor <Object > createOpenStreamQueryExecutor (QueryExecutor <Object > executor ) {
186
+ return parameters -> {
187
+
188
+ Stream <?> result = (Stream <?>) executor .execute (parameters );
189
+
190
+ Assert .notNull (result , "A stream valued result must never be null." );
191
+
192
+ return result .peek (element -> {
193
+ publishAfterLoad (element );
194
+ });
195
+ };
196
+ }
197
+
173
198
private QueryExecutor <Object > createListRowMapperQueryExecutor (String query , RowMapper <?> rowMapper ) {
174
199
return parameters -> operations .query (query , parameters , rowMapper );
175
200
}
@@ -183,6 +208,21 @@ private QueryExecutor<Object> createResultSetExtractorQueryExecutor(String query
183
208
return parameters -> operations .query (query , parameters , resultSetExtractor );
184
209
}
185
210
211
+ private QueryExecutor <Object > createRowMapperOpenQueryStreamExecutor (String query , RowMapper rowMapper , ResultSetExtractor extractor ) {
212
+ JdbcOpenRowSetTemplate openResultSetNamedParameterJdbcTemplate =
213
+ new JdbcOpenRowSetTemplate (operations .getJdbcOperations ());
214
+ return parameters -> {
215
+ final JdbcOpenSqlRowSet rowSet =
216
+ openResultSetNamedParameterJdbcTemplate .queryForOpenCursorRowSet (query , parameters , queryMethod .getStreamQueryFetchSized ());
217
+
218
+ final Spliterator <Object > spliterator = Spliterators
219
+ .spliteratorUnknownSize (new JdbcOpenSqlRowSetIterator <Object >(rowSet , rowMapper , extractor ), Spliterator .IMMUTABLE );
220
+ final Supplier <Spliterator <Object >> supplier = () -> spliterator ;
221
+ return StreamSupport .stream (supplier , Spliterator .IMMUTABLE , false )
222
+ .onClose (rowSet ::close );
223
+ };
224
+ }
225
+
186
226
/*
187
227
* (non-Javadoc)
188
228
* @see org.springframework.data.repository.query.RepositoryQuery#getQueryMethod()
0 commit comments