26
26
import org .springframework .beans .BeanUtils ;
27
27
import org .springframework .beans .factory .BeanFactory ;
28
28
import org .springframework .core .convert .converter .Converter ;
29
+ import org .springframework .data .domain .Pageable ;
29
30
import org .springframework .data .jdbc .core .convert .JdbcColumnTypes ;
30
31
import org .springframework .data .jdbc .core .convert .JdbcConverter ;
31
32
import org .springframework .data .jdbc .core .mapping .JdbcValue ;
@@ -109,16 +110,6 @@ public StringBasedJdbcQuery(JdbcQueryMethod queryMethod, NamedParameterJdbcOpera
109
110
this .converter = converter ;
110
111
this .rowMapperFactory = rowMapperFactory ;
111
112
this .evaluationContextProvider = evaluationContextProvider ;
112
-
113
- if (queryMethod .isSliceQuery ()) {
114
- throw new UnsupportedOperationException (
115
- "Slice queries are not supported using string-based queries; Offending method: " + queryMethod );
116
- }
117
-
118
- if (queryMethod .isPageQuery ()) {
119
- throw new UnsupportedOperationException (
120
- "Page queries are not supported using string-based queries; Offending method: " + queryMethod );
121
- }
122
113
}
123
114
124
115
@ Override
@@ -132,10 +123,9 @@ public Object execute(Object[] objects) {
132
123
RowMapper <Object > rowMapper = determineRowMapper (rowMapperFactory .create (resolveTypeToRead (processor )), converter ,
133
124
accessor .findDynamicProjection () != null );
134
125
135
- JdbcQueryExecution <?> queryExecution = getQueryExecution (//
136
- queryMethod , //
137
- determineResultSetExtractor (rowMapper ), //
138
- rowMapper );
126
+ JdbcQueryExecution <?> queryExecution = queryMethod .isPageQuery () || queryMethod .isSliceQuery ()
127
+ ? collectionQuery (rowMapper )
128
+ : getQueryExecution (queryMethod , determineResultSetExtractor (rowMapper ), rowMapper );
139
129
140
130
MapSqlParameterSource parameterMap = this .bindParameters (accessor );
141
131
@@ -145,9 +135,33 @@ public Object execute(Object[] objects) {
145
135
throw new IllegalStateException (String .format ("No query specified on %s" , queryMethod .getName ()));
146
136
}
147
137
138
+ if (queryMethod .isSliceQuery () || queryMethod .isPageQuery ()) {
139
+ queryExecution = wrapPageableQueryExecution (accessor , parameterMap , queryExecution );
140
+ }
141
+
148
142
return queryExecution .execute (processSpelExpressions (objects , parameterMap , query ), parameterMap );
149
143
}
150
144
145
+ private JdbcQueryExecution <?> wrapPageableQueryExecution (RelationalParameterAccessor accessor , MapSqlParameterSource parameterMap , JdbcQueryExecution <?> queryExecution ) {
146
+ Pageable pageable = accessor .getPageable ();
147
+ parameterMap .addValue ("offset" , pageable .getOffset ());
148
+ if (queryMethod .isSliceQuery ()) {
149
+ parameterMap .addValue ("limit" , pageable .getPageSize () + 1 );
150
+ queryExecution = new PartTreeJdbcQuery .SliceQueryExecution <>((JdbcQueryExecution <Collection <Object >>) queryExecution , pageable );
151
+ }else if (queryMethod .isPageQuery ()) {
152
+ parameterMap .addValue ("limit" , pageable .getPageSize ());
153
+ queryExecution = new PartTreeJdbcQuery .PageQueryExecution <>((JdbcQueryExecution <Collection <Object >>) queryExecution , pageable ,
154
+ () -> {
155
+ String querySql = getQueryMethod ().getDeclaredQuery ();
156
+ String countQuerySql = querySql .replaceFirst ("(?i)select .*? from" , "select count(*) from" )
157
+ .replaceFirst ("(?i) order by .*" , "" );
158
+ Object count = singleObjectQuery ((rs , i ) -> rs .getLong (1 )).execute (countQuerySql , parameterMap );
159
+ return this .converter .getConversionService ().convert (count , Long .class );
160
+ });
161
+ }
162
+ return queryExecution ;
163
+ }
164
+
151
165
private String processSpelExpressions (Object [] objects , MapSqlParameterSource parameterMap , String query ) {
152
166
153
167
SpelQueryContext .EvaluatingSpelQueryContext queryContext = SpelQueryContext
@@ -225,10 +239,17 @@ private String determineQuery() {
225
239
if (ObjectUtils .isEmpty (query )) {
226
240
throw new IllegalStateException (String .format ("No query specified on %s" , queryMethod .getName ()));
227
241
}
228
-
242
+ if (queryMethod .isPageQuery () || queryMethod .isSliceQuery ()) {
243
+ return enhancePageQuery (query );
244
+ }
229
245
return query ;
230
246
}
231
247
248
+ private String enhancePageQuery (String query ) {
249
+ String original = query .trim ().replace (";" , "" );
250
+ return String .format ("%s limit :limit offset :offset" , original );
251
+ }
252
+
232
253
@ Nullable
233
254
@ SuppressWarnings ({ "rawtypes" , "unchecked" })
234
255
ResultSetExtractor <Object > determineResultSetExtractor (@ Nullable RowMapper <Object > rowMapper ) {
0 commit comments