2020import java .lang .reflect .Array ;
2121import java .lang .reflect .Constructor ;
2222import java .sql .SQLType ;
23- import java .util .AbstractMap ;
2423import java .util .ArrayList ;
2524import java .util .Collection ;
2625import java .util .LinkedHashMap ;
2726import java .util .List ;
28- import java .util .Map ;
2927import java .util .function .Function ;
3028import java .util .function .Supplier ;
3129
3230import org .springframework .beans .BeanInstantiationException ;
3331import org .springframework .beans .BeanUtils ;
3432import org .springframework .beans .factory .BeanFactory ;
33+ import org .springframework .core .env .StandardEnvironment ;
3534import org .springframework .data .expression .ValueEvaluationContext ;
3635import org .springframework .data .expression .ValueExpressionParser ;
3736import org .springframework .data .jdbc .core .convert .JdbcColumnTypes ;
5150import org .springframework .data .repository .query .ValueExpressionQueryRewriter ;
5251import org .springframework .data .util .Lazy ;
5352import org .springframework .data .util .TypeInformation ;
54- import org .springframework .expression .spel .standard .SpelExpressionParser ;
5553import org .springframework .jdbc .core .ResultSetExtractor ;
5654import org .springframework .jdbc .core .RowMapper ;
5755import org .springframework .jdbc .core .namedparam .MapSqlParameterSource ;
7472 * @author Chirag Tailor
7573 * @author Christopher Klein
7674 * @author Mikhail Polivakha
75+ * @author Marcin Grzejszczak
7776 * @since 2.0
7877 */
7978public class StringBasedJdbcQuery extends AbstractJdbcQuery {
@@ -82,13 +81,11 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery {
8281 private final JdbcConverter converter ;
8382 private final RowMapperFactory rowMapperFactory ;
8483 private final ValueExpressionQueryRewriter .ParsedQuery parsedQuery ;
85- private final boolean containsSpelExpressions ;
8684 private final String query ;
8785
8886 private final CachedRowMapperFactory cachedRowMapperFactory ;
8987 private final CachedResultSetExtractorFactory cachedResultSetExtractorFactory ;
9088 private final ValueExpressionDelegate delegate ;
91- private final List <Map .Entry <String , String >> parameterBindings ;
9289
9390 /**
9491 * Creates a new {@link StringBasedJdbcQuery} for the given {@link JdbcQueryMethod}, {@link RelationalMappingContext}
@@ -186,17 +183,11 @@ public StringBasedJdbcQuery(String query, JdbcQueryMethod queryMethod, NamedPara
186183 this .cachedResultSetExtractorFactory = new CachedResultSetExtractorFactory (
187184 this .cachedRowMapperFactory ::getRowMapper );
188185
189- this .parameterBindings = new ArrayList <>();
190-
191- ValueExpressionQueryRewriter rewriter = ValueExpressionQueryRewriter .of (delegate , (counter , expression ) -> {
192- String newName = String .format ("__$synthetic$__%d" , counter + 1 );
193- parameterBindings .add (new AbstractMap .SimpleEntry <>(newName , expression ));
194- return newName ;
195- }, String ::concat );
186+ ValueExpressionQueryRewriter rewriter = ValueExpressionQueryRewriter .of (delegate ,
187+ (counter , expression ) -> String .format ("__$synthetic$__%d" , counter + 1 ), String ::concat );
196188
197189 this .query = query ;
198190 this .parsedQuery = rewriter .parse (this .query );
199- this .containsSpelExpressions = !this .parsedQuery .getQueryString ().equals (this .query );
200191 this .delegate = delegate ;
201192 }
202193
@@ -217,9 +208,10 @@ public StringBasedJdbcQuery(String query, JdbcQueryMethod queryMethod, NamedPara
217208 public StringBasedJdbcQuery (String query , JdbcQueryMethod queryMethod , NamedParameterJdbcOperations operations ,
218209 RowMapperFactory rowMapperFactory , JdbcConverter converter ,
219210 QueryMethodEvaluationContextProvider evaluationContextProvider ) {
220- this (query , queryMethod , operations , rowMapperFactory , converter , new CachingValueExpressionDelegate (new QueryMethodValueEvaluationContextAccessor (null ,
221- rootObject -> evaluationContextProvider .getEvaluationContext (queryMethod .getParameters (), new Object [] { rootObject })), ValueExpressionParser .create (
222- SpelExpressionParser ::new )));
211+ this (query , queryMethod , operations , rowMapperFactory , converter , new CachingValueExpressionDelegate (
212+ new QueryMethodValueEvaluationContextAccessor (new StandardEnvironment (), rootObject -> evaluationContextProvider
213+ .getEvaluationContext (queryMethod .getParameters (), new Object [] { rootObject })),
214+ ValueExpressionParser .create ()));
223215 }
224216
225217 @ Override
@@ -231,18 +223,22 @@ public Object execute(Object[] objects) {
231223 JdbcQueryExecution <?> queryExecution = createJdbcQueryExecution (accessor , processor );
232224 MapSqlParameterSource parameterMap = this .bindParameters (accessor );
233225
234- return queryExecution .execute (processSpelExpressions (objects , accessor .getBindableParameters (), parameterMap ), parameterMap );
226+ return queryExecution .execute (evaluateExpressions (objects , accessor .getBindableParameters (), parameterMap ),
227+ parameterMap );
235228 }
236229
237- private String processSpelExpressions (Object [] objects , Parameters <?, ?> bindableParameters , MapSqlParameterSource parameterMap ) {
230+ private String evaluateExpressions (Object [] objects , Parameters <?, ?> bindableParameters ,
231+ MapSqlParameterSource parameterMap ) {
232+
233+ if (parsedQuery .hasParameterBindings ()) {
238234
239- if (containsSpelExpressions ) {
240235 ValueEvaluationContext evaluationContext = delegate .createValueContextProvider (bindableParameters )
241236 .getEvaluationContext (objects );
242- for (Map .Entry <String , String > entry : parameterBindings ) {
243- parameterMap .addValue (
244- entry .getKey (), delegate .parse (entry .getValue ()).evaluate (evaluationContext ));
245- }
237+
238+ parsedQuery .getParameterMap ().forEach ((paramName , valueExpression ) -> {
239+ parameterMap .addValue (paramName , valueExpression .evaluate (evaluationContext ));
240+ });
241+
246242 return parsedQuery .getQueryString ();
247243 }
248244
@@ -254,13 +250,12 @@ private JdbcQueryExecution<?> createJdbcQueryExecution(RelationalParameterAccess
254250
255251 if (getQueryMethod ().isModifyingQuery ()) {
256252 return createModifyingQueryExecutor ();
257- } else {
253+ }
258254
259- Supplier <RowMapper <?>> rowMapper = () -> determineRowMapper (processor , accessor .findDynamicProjection () != null );
260- ResultSetExtractor <Object > resultSetExtractor = determineResultSetExtractor (rowMapper );
255+ Supplier <RowMapper <?>> rowMapper = () -> determineRowMapper (processor , accessor .findDynamicProjection () != null );
256+ ResultSetExtractor <Object > resultSetExtractor = determineResultSetExtractor (rowMapper );
261257
262- return createReadingQueryExecution (resultSetExtractor , rowMapper );
263- }
258+ return createReadingQueryExecution (resultSetExtractor , rowMapper );
264259 }
265260
266261 private MapSqlParameterSource bindParameters (RelationalParameterAccessor accessor ) {
0 commit comments