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}
@@ -185,17 +182,11 @@ public StringBasedJdbcQuery(String query, JdbcQueryMethod queryMethod, NamedPara
185182 this .cachedResultSetExtractorFactory = new CachedResultSetExtractorFactory (
186183 this .cachedRowMapperFactory ::getRowMapper );
187184
188- this .parameterBindings = new ArrayList <>();
189-
190- ValueExpressionQueryRewriter rewriter = ValueExpressionQueryRewriter .of (delegate , (counter , expression ) -> {
191- String newName = String .format ("__$synthetic$__%d" , counter + 1 );
192- parameterBindings .add (new AbstractMap .SimpleEntry <>(newName , expression ));
193- return newName ;
194- }, String ::concat );
185+ ValueExpressionQueryRewriter rewriter = ValueExpressionQueryRewriter .of (delegate ,
186+ (counter , expression ) -> String .format ("__$synthetic$__%d" , counter + 1 ), String ::concat );
195187
196188 this .query = query ;
197189 this .parsedQuery = rewriter .parse (this .query );
198- this .containsSpelExpressions = !this .parsedQuery .getQueryString ().equals (this .query );
199190 this .delegate = delegate ;
200191 }
201192
@@ -216,9 +207,10 @@ public StringBasedJdbcQuery(String query, JdbcQueryMethod queryMethod, NamedPara
216207 public StringBasedJdbcQuery (String query , JdbcQueryMethod queryMethod , NamedParameterJdbcOperations operations ,
217208 RowMapperFactory rowMapperFactory , JdbcConverter converter ,
218209 QueryMethodEvaluationContextProvider evaluationContextProvider ) {
219- this (query , queryMethod , operations , rowMapperFactory , converter , new CachingValueExpressionDelegate (new QueryMethodValueEvaluationContextAccessor (null ,
220- rootObject -> evaluationContextProvider .getEvaluationContext (queryMethod .getParameters (), new Object [] { rootObject })), ValueExpressionParser .create (
221- SpelExpressionParser ::new )));
210+ this (query , queryMethod , operations , rowMapperFactory , converter , new CachingValueExpressionDelegate (
211+ new QueryMethodValueEvaluationContextAccessor (new StandardEnvironment (), rootObject -> evaluationContextProvider
212+ .getEvaluationContext (queryMethod .getParameters (), new Object [] { rootObject })),
213+ ValueExpressionParser .create ()));
222214 }
223215
224216 @ Override
@@ -230,18 +222,22 @@ public Object execute(Object[] objects) {
230222 JdbcQueryExecution <?> queryExecution = createJdbcQueryExecution (accessor , processor );
231223 MapSqlParameterSource parameterMap = this .bindParameters (accessor );
232224
233- return queryExecution .execute (processSpelExpressions (objects , accessor .getBindableParameters (), parameterMap ), parameterMap );
225+ return queryExecution .execute (evaluateExpressions (objects , accessor .getBindableParameters (), parameterMap ),
226+ parameterMap );
234227 }
235228
236- private String processSpelExpressions (Object [] objects , Parameters <?, ?> bindableParameters , MapSqlParameterSource parameterMap ) {
229+ private String evaluateExpressions (Object [] objects , Parameters <?, ?> bindableParameters ,
230+ MapSqlParameterSource parameterMap ) {
231+
232+ if (parsedQuery .hasParameterBindings ()) {
237233
238- if (containsSpelExpressions ) {
239234 ValueEvaluationContext evaluationContext = delegate .createValueContextProvider (bindableParameters )
240235 .getEvaluationContext (objects );
241- for (Map .Entry <String , String > entry : parameterBindings ) {
242- parameterMap .addValue (
243- entry .getKey (), delegate .parse (entry .getValue ()).evaluate (evaluationContext ));
244- }
236+
237+ parsedQuery .getParameterMap ().forEach ((paramName , valueExpression ) -> {
238+ parameterMap .addValue (paramName , valueExpression .evaluate (evaluationContext ));
239+ });
240+
245241 return parsedQuery .getQueryString ();
246242 }
247243
@@ -253,13 +249,12 @@ private JdbcQueryExecution<?> createJdbcQueryExecution(RelationalParameterAccess
253249
254250 if (getQueryMethod ().isModifyingQuery ()) {
255251 return createModifyingQueryExecutor ();
256- } else {
252+ }
257253
258- Supplier <RowMapper <?>> rowMapper = () -> determineRowMapper (processor , accessor .findDynamicProjection () != null );
259- ResultSetExtractor <Object > resultSetExtractor = determineResultSetExtractor (rowMapper );
254+ Supplier <RowMapper <?>> rowMapper = () -> determineRowMapper (processor , accessor .findDynamicProjection () != null );
255+ ResultSetExtractor <Object > resultSetExtractor = determineResultSetExtractor (rowMapper );
260256
261- return createReadingQueryExecution (resultSetExtractor , rowMapper );
262- }
257+ return createReadingQueryExecution (resultSetExtractor , rowMapper );
263258 }
264259
265260 private MapSqlParameterSource bindParameters (RelationalParameterAccessor accessor ) {
0 commit comments