Skip to content

Commit 32b231f

Browse files
committed
support slice/page query in StringBasedJdbcQuery
1 parent 51cd894 commit 32b231f

File tree

1 file changed

+36
-15
lines changed

1 file changed

+36
-15
lines changed

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

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.springframework.beans.BeanUtils;
2727
import org.springframework.beans.factory.BeanFactory;
2828
import org.springframework.core.convert.converter.Converter;
29+
import org.springframework.data.domain.Pageable;
2930
import org.springframework.data.jdbc.core.convert.JdbcColumnTypes;
3031
import org.springframework.data.jdbc.core.convert.JdbcConverter;
3132
import org.springframework.data.jdbc.core.mapping.JdbcValue;
@@ -109,16 +110,6 @@ public StringBasedJdbcQuery(JdbcQueryMethod queryMethod, NamedParameterJdbcOpera
109110
this.converter = converter;
110111
this.rowMapperFactory = rowMapperFactory;
111112
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-
}
122113
}
123114

124115
@Override
@@ -132,10 +123,9 @@ public Object execute(Object[] objects) {
132123
RowMapper<Object> rowMapper = determineRowMapper(rowMapperFactory.create(resolveTypeToRead(processor)), converter,
133124
accessor.findDynamicProjection() != null);
134125

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);
139129

140130
MapSqlParameterSource parameterMap = this.bindParameters(accessor);
141131

@@ -145,9 +135,33 @@ public Object execute(Object[] objects) {
145135
throw new IllegalStateException(String.format("No query specified on %s", queryMethod.getName()));
146136
}
147137

138+
if (queryMethod.isSliceQuery() || queryMethod.isPageQuery()) {
139+
queryExecution = wrapPageableQueryExecution(accessor, parameterMap, queryExecution);
140+
}
141+
148142
return queryExecution.execute(processSpelExpressions(objects, parameterMap, query), parameterMap);
149143
}
150144

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+
151165
private String processSpelExpressions(Object[] objects, MapSqlParameterSource parameterMap, String query) {
152166

153167
SpelQueryContext.EvaluatingSpelQueryContext queryContext = SpelQueryContext
@@ -225,10 +239,17 @@ private String determineQuery() {
225239
if (ObjectUtils.isEmpty(query)) {
226240
throw new IllegalStateException(String.format("No query specified on %s", queryMethod.getName()));
227241
}
228-
242+
if (queryMethod.isPageQuery() || queryMethod.isSliceQuery()) {
243+
return enhancePageQuery(query);
244+
}
229245
return query;
230246
}
231247

248+
private String enhancePageQuery(String query) {
249+
String original = query.trim().replace(";", "");
250+
return String.format("%s limit :limit offset :offset", original);
251+
}
252+
232253
@Nullable
233254
@SuppressWarnings({ "rawtypes", "unchecked" })
234255
ResultSetExtractor<Object> determineResultSetExtractor(@Nullable RowMapper<Object> rowMapper) {

0 commit comments

Comments
 (0)