18
18
19
19
import java .util .List ;
20
20
import java .util .Map ;
21
+ import java .util .function .BiFunction ;
22
+ import java .util .stream .Stream ;
21
23
22
24
import javax .sql .DataSource ;
23
25
24
26
import org .jspecify .annotations .Nullable ;
25
27
26
28
import org .springframework .dao .DataAccessException ;
27
29
import org .springframework .dao .support .DataAccessUtils ;
30
+ import org .springframework .jdbc .core .PreparedStatementCreator ;
28
31
import org .springframework .jdbc .core .RowMapper ;
29
32
import org .springframework .jdbc .core .namedparam .MapSqlParameterSource ;
30
33
import org .springframework .jdbc .core .namedparam .NamedParameterUtils ;
52
55
* @author Rod Johnson
53
56
* @author Juergen Hoeller
54
57
* @author Thomas Risberg
58
+ * @author Yanming Zhou
55
59
* @param <T> the result type
56
60
* @see SqlUpdate
57
61
*/
@@ -94,6 +98,23 @@ public List<T> execute(Object @Nullable [] params, @Nullable Map<?, ?> context)
94
98
return getJdbcTemplate ().query (newPreparedStatementCreator (params ), rowMapper );
95
99
}
96
100
101
+ /**
102
+ * Central stream method. All un-named parameter execution goes through this method.
103
+ * @param params parameters, similar to JDO query parameters.
104
+ * Primitive parameters must be represented by their Object wrapper type.
105
+ * The ordering of parameters is significant.
106
+ * @param context the contextual information passed to the {@code mapRow}
107
+ * callback method. The JDBC operation itself doesn't rely on this parameter,
108
+ * but it can be useful for creating the objects of the result list.
109
+ * @return a result Stream of objects, one per row of the ResultSet. Normally all these
110
+ * will be of the same class, although it is possible to use different types.
111
+ */
112
+ public Stream <T > stream (Object @ Nullable [] params , @ Nullable Map <?, ?> context ) throws DataAccessException {
113
+ validateParameters (params );
114
+ RowMapper <T > rowMapper = newRowMapper (params , context );
115
+ return getJdbcTemplate ().queryForStream (newPreparedStatementCreator (params ), rowMapper );
116
+ }
117
+
97
118
/**
98
119
* Convenient method to execute without context.
99
120
* @param params parameters for the query. Primitive parameters must
@@ -104,6 +125,16 @@ public List<T> execute(Object... params) throws DataAccessException {
104
125
return execute (params , null );
105
126
}
106
127
128
+ /**
129
+ * Convenient method to stream without context.
130
+ * @param params parameters for the query. Primitive parameters must
131
+ * be represented by their Object wrapper type. The ordering of parameters is
132
+ * significant.
133
+ */
134
+ public Stream <T > stream (Object ... params ) throws DataAccessException {
135
+ return stream (params , null );
136
+ }
137
+
107
138
/**
108
139
* Convenient method to execute without parameters.
109
140
* @param context the contextual information for object creation
@@ -112,13 +143,28 @@ public List<T> execute(Map<?, ?> context) throws DataAccessException {
112
143
return execute ((Object []) null , context );
113
144
}
114
145
146
+ /**
147
+ * Convenient method to stream without parameters.
148
+ * @param context the contextual information for object creation
149
+ */
150
+ public Stream <T > stream (Map <?, ?> context ) throws DataAccessException {
151
+ return stream (null , context );
152
+ }
153
+
115
154
/**
116
155
* Convenient method to execute without parameters nor context.
117
156
*/
118
157
public List <T > execute () throws DataAccessException {
119
158
return execute ((Object []) null , null );
120
159
}
121
160
161
+ /**
162
+ * Convenient method to stream without parameters nor context.
163
+ */
164
+ public Stream <T > stream () throws DataAccessException {
165
+ return stream (null , null );
166
+ }
167
+
122
168
/**
123
169
* Convenient method to execute with a single int parameter and context.
124
170
* @param p1 single int parameter
@@ -202,13 +248,23 @@ public List<T> execute(String p1) throws DataAccessException {
202
248
* will be of the same class, although it is possible to use different types.
203
249
*/
204
250
public List <T > executeByNamedParam (Map <String , ?> paramMap , @ Nullable Map <?, ?> context ) throws DataAccessException {
205
- validateNamedParameters (paramMap );
206
- ParsedSql parsedSql = getParsedSql ();
207
- MapSqlParameterSource paramSource = new MapSqlParameterSource (paramMap );
208
- String sqlToUse = NamedParameterUtils .substituteNamedParameters (parsedSql , paramSource );
209
- @ Nullable Object [] params = NamedParameterUtils .buildValueArray (parsedSql , paramSource , getDeclaredParameters ());
210
- RowMapper <T > rowMapper = newRowMapper (params , context );
211
- return getJdbcTemplate ().query (newPreparedStatementCreator (sqlToUse , params ), rowMapper );
251
+ return queryByNamedParam (paramMap , context , getJdbcTemplate ()::query );
252
+ }
253
+
254
+ /**
255
+ * Central stream method. All named parameter execution goes through this method.
256
+ * @param paramMap parameters associated with the name specified while declaring
257
+ * the SqlParameters. Primitive parameters must be represented by their Object wrapper
258
+ * type. The ordering of parameters is not significant since they are supplied in a
259
+ * SqlParameterMap which is an implementation of the Map interface.
260
+ * @param context the contextual information passed to the {@code mapRow}
261
+ * callback method. The JDBC operation itself doesn't rely on this parameter,
262
+ * but it can be useful for creating the objects of the result list.
263
+ * @return a Stream of objects, one per row of the ResultSet. Normally all these
264
+ * will be of the same class, although it is possible to use different types.
265
+ */
266
+ public Stream <T > streamByNamedParam (Map <String , ?> paramMap , @ Nullable Map <?, ?> context ) throws DataAccessException {
267
+ return queryByNamedParam (paramMap , context , getJdbcTemplate ()::queryForStream );
212
268
}
213
269
214
270
/**
@@ -221,6 +277,15 @@ public List<T> executeByNamedParam(Map<String, ? extends @Nullable Object> param
221
277
return executeByNamedParam (paramMap , null );
222
278
}
223
279
280
+ /**
281
+ * Convenient method to stream without context.
282
+ * @param paramMap parameters associated with the name specified while declaring
283
+ * the SqlParameters. Primitive parameters must be represented by their Object wrapper
284
+ * type. The ordering of parameters is not significant.
285
+ */
286
+ public Stream <T > streamByNamedParam (Map <String , ? extends @ Nullable Object > paramMap ) throws DataAccessException {
287
+ return streamByNamedParam (paramMap , null );
288
+ }
224
289
225
290
/**
226
291
* Generic object finder method, used by all other {@code findObject} methods.
@@ -342,4 +407,14 @@ public List<T> executeByNamedParam(Map<String, ? extends @Nullable Object> param
342
407
*/
343
408
protected abstract RowMapper <T > newRowMapper (@ Nullable Object @ Nullable [] parameters , @ Nullable Map <?, ?> context );
344
409
410
+ private <R > R queryByNamedParam (Map <String , ?> paramMap , @ Nullable Map <?, ?> context , BiFunction <PreparedStatementCreator , RowMapper <T >, R > queryFunction ) {
411
+ validateNamedParameters (paramMap );
412
+ ParsedSql parsedSql = getParsedSql ();
413
+ MapSqlParameterSource paramSource = new MapSqlParameterSource (paramMap );
414
+ String sqlToUse = NamedParameterUtils .substituteNamedParameters (parsedSql , paramSource );
415
+ @ Nullable Object [] params = NamedParameterUtils .buildValueArray (parsedSql , paramSource , getDeclaredParameters ());
416
+ RowMapper <T > rowMapper = newRowMapper (params , context );
417
+ return queryFunction .apply (newPreparedStatementCreator (sqlToUse , params ), rowMapper );
418
+ }
419
+
345
420
}
0 commit comments