4646import org .springframework .data .relational .core .sql .LockMode ;
4747import org .springframework .data .relational .repository .Lock ;
4848import org .springframework .data .repository .aot .generate .AotQueryMethodGenerationContext ;
49+ import org .springframework .data .repository .query .parser .Part ;
4950import org .springframework .data .support .PageableExecutionUtils ;
5051import org .springframework .data .util .Pair ;
5152import org .springframework .javapoet .CodeBlock ;
@@ -90,6 +91,7 @@ static QueryExecutionBlockBuilder executionBuilder(AotQueryMethodGenerationConte
9091 static class QueryBlockBuilder {
9192
9293 private final AotQueryMethodGenerationContext context ;
94+ private final JdbcQueryMethod queryMethod ;
9395 private final String parameterNames ;
9496 private String queryVariableName = "undefined" ;
9597 private String parameterSourceVariableName = "undefined" ;
@@ -99,6 +101,7 @@ static class QueryBlockBuilder {
99101 private QueryBlockBuilder (AotQueryMethodGenerationContext context , JdbcQueryMethod queryMethod ) {
100102
101103 this .context = context ;
104+ this .queryMethod = queryMethod ;
102105
103106 String parameterNames = StringUtils .collectionToDelimitedString (context .getAllParameterNames (), ", " );
104107
@@ -145,7 +148,11 @@ public CodeBlock build() {
145148 queries .count () instanceof DerivedAotQuery derivedCountQuery ? derivedCountQuery : null );
146149 }
147150
148- return createStringQuery (queryVariableName , parameterSourceVariableName , queries .result ());
151+ if (queries .result () instanceof StringAotQuery stringQuery ) {
152+ return createStringQuery (queryVariableName , parameterSourceVariableName , stringQuery );
153+ }
154+
155+ throw new IllegalArgumentException ("Unsupported AOT query type: " + queries .result ());
149156 }
150157
151158 private CodeBlock createDerivedQuery (DerivedAotQuery entityQuery , @ Nullable DerivedAotQuery countQuery ) {
@@ -205,6 +212,8 @@ private CodeBlock buildQuery(boolean count, DerivedAotQuery aotQuery, CriteriaDe
205212 method = "count($T.class)" ;
206213 } else if (aotQuery .isExists ()) {
207214 method = "exists($T.class)" ;
215+ } else if (queryMethod .isSliceQuery ()) {
216+ method = "slice($T.class)" ;
208217 } else {
209218 method = "select($T.class)" ;
210219 }
@@ -221,7 +230,7 @@ private CodeBlock buildQuery(boolean count, DerivedAotQuery aotQuery, CriteriaDe
221230 }
222231
223232 if (StringUtils .hasText (context .getPageableParameterName ())) {
224- builder .addStatement ("$L.with ($L)" , selection , context .getPageableParameterName ());
233+ builder .addStatement ("$L.page ($L)" , selection , context .getPageableParameterName ());
225234 }
226235
227236 Sort sort = aotQuery .getSort ();
@@ -242,7 +251,7 @@ private CodeBlock buildQuery(boolean count, DerivedAotQuery aotQuery, CriteriaDe
242251 builder .addStatement ("$L.filter($L)" , selection , context .localVariable ("criteria" ));
243252 }
244253
245- // TODO Projections, Pagination
254+ // TODO Projections
246255
247256 builder .addStatement ("$1T $2L = new $1T()" , MapSqlParameterSource .class , rawParameterSource );
248257 builder .addStatement ("$T $L = $L.build($L)" , String .class , queryVariableName , selection , rawParameterSource );
@@ -353,8 +362,8 @@ private void appendCriteria(CriteriaDefinition current, Builder builder) {
353362 case GTE -> builder .add (".greaterThanEquals($L)" , renderPlaceholder (value ));
354363 case IS_NULL -> builder .add (".isNull()" );
355364 case IS_NOT_NULL -> builder .add (".isNotNull()" );
356- case LIKE -> builder . add ( ". like($L) " , renderPlaceholder ( value ) );
357- case NOT_LIKE -> builder . add ( ". notLike($L) " , renderPlaceholder ( value ) );
365+ case LIKE -> applyLike ( builder , " like" , value );
366+ case NOT_LIKE -> applyLike ( builder , " notLike" , value );
358367 case NOT_IN -> builder .add (".notIn($L)" , renderPlaceholder (value ));
359368 case IN -> builder .add (".in($L)" , renderPlaceholder (value ));
360369 case IS_TRUE -> builder .add (".isTrue()" );
@@ -366,6 +375,25 @@ private void appendCriteria(CriteriaDefinition current, Builder builder) {
366375 }
367376 }
368377
378+ private void applyLike (Builder builder , String method , @ Nullable Object value ) {
379+
380+ CapturingJdbcValue captured = CapturingJdbcValue .unwrap (value );
381+
382+ String likeValue = "$L" ;
383+ if (captured .getBinding () instanceof ParameterBinding .LikeParameterBinding lpb ) {
384+
385+ if (lpb .getType () == Part .Type .CONTAINING ) {
386+ likeValue = "\" %\" + escape($L) + \" %\" " ;
387+ } else if (lpb .getType () == Part .Type .STARTING_WITH ) {
388+ likeValue = "escape($L) + \" %\" " ;
389+ } else if (lpb .getType () == Part .Type .ENDING_WITH ) {
390+ likeValue = "\" %\" + escape($L)" ;
391+ }
392+ }
393+
394+ builder .add (".$L(" + likeValue + ")" , method , renderPlaceholder (value ));
395+ }
396+
369397 private @ Nullable String renderPlaceholder (@ Nullable Object value ) {
370398
371399 CapturingJdbcValue captured = CapturingJdbcValue .unwrap (value );
@@ -379,14 +407,14 @@ private void appendCriteria(CriteriaDefinition current, Builder builder) {
379407 }
380408
381409 private Object renderPlaceholder (@ Nullable Object value , int index ) {
382- return index == 0 ? ((Pair ) value ).getFirst () : ((Pair ) value ).getSecond ();
410+ return renderPlaceholder ( index == 0 ? ((Pair ) value ).getFirst () : ((Pair ) value ).getSecond () );
383411 }
384412
385- private CodeBlock createStringQuery (String queryVariableName , String parameterSourceName , AotQuery query ) {
413+ private CodeBlock createStringQuery (String queryVariableName , String parameterSourceName , StringAotQuery query ) {
386414
387415 Builder builder = CodeBlock .builder ();
388416
389- builder .add ( doCreateQuery ( queryVariableName , query ));
417+ builder .addStatement ( "$T $L = $S" , String . class , queryVariableName , query . getQueryString ( ));
390418 builder .addStatement ("$1T $2L = new $1T()" , MapSqlParameterSource .class , parameterSourceName );
391419
392420 for (ParameterBinding binding : query .getParameterBindings ()) {
@@ -398,24 +426,6 @@ private CodeBlock createStringQuery(String queryVariableName, String parameterSo
398426 return builder .build ();
399427 }
400428
401- private static boolean isArray (Class <?> parameterType ) {
402- return parameterType .isArray () && !parameterType .getComponentType ().equals (byte .class )
403- && !parameterType .getComponentType ().equals (Byte .class );
404- }
405-
406- private CodeBlock doCreateQuery (String queryVariableName , AotQuery query ) {
407-
408- Builder builder = CodeBlock .builder ();
409-
410- if (query instanceof StringAotQuery sq ) {
411-
412- builder .addStatement ("$T $L = $S" , String .class , queryVariableName , sq .getQueryString ());
413- return builder .build ();
414- }
415-
416- throw new UnsupportedOperationException ("Unsupported query type: " + query );
417- }
418-
419429 private String getParameterName (ParameterBinding .BindingIdentifier identifier ) {
420430 return identifier .hasName () ? identifier .getName () : Integer .toString (identifier .getPosition ());
421431 }
0 commit comments