3434import org .springframework .core .annotation .MergedAnnotation ;
3535import org .springframework .data .domain .SliceImpl ;
3636import org .springframework .data .domain .Sort ;
37+ import org .springframework .data .javapoet .LordOfTheStrings ;
3738import org .springframework .data .jdbc .repository .query .JdbcQueryMethod ;
3839import org .springframework .data .jdbc .repository .query .Modifying ;
3940import org .springframework .data .jdbc .repository .query .ParameterBinding ;
4445import org .springframework .data .relational .core .sql .LockMode ;
4546import org .springframework .data .relational .repository .Lock ;
4647import org .springframework .data .repository .aot .generate .AotQueryMethodGenerationContext ;
48+ import org .springframework .data .repository .aot .generate .MethodReturn ;
4749import org .springframework .data .repository .query .parser .Part ;
4850import org .springframework .data .support .PageableExecutionUtils ;
4951import org .springframework .data .util .Pair ;
50- import org .springframework .data .util .ReflectionUtils ;
5152import org .springframework .javapoet .CodeBlock ;
5253import org .springframework .javapoet .CodeBlock .Builder ;
5354import org .springframework .javapoet .TypeName ;
5859import org .springframework .jdbc .core .namedparam .MapSqlParameterSource ;
5960import org .springframework .jdbc .core .namedparam .SqlParameterSource ;
6061import org .springframework .util .Assert ;
61- import org .springframework .util .ObjectUtils ;
62+ import org .springframework .util .ClassUtils ;
6263import org .springframework .util .StringUtils ;
6364
6465/**
@@ -568,25 +569,26 @@ public CodeBlock build() {
568569
569570 Builder builder = CodeBlock .builder ();
570571
571- boolean isProjecting = !ObjectUtils .nullSafeEquals (
572- TypeName .get (context .getRepositoryInformation ().getDomainType ()), context .getActualReturnType ());
573- Type actualReturnType = isProjecting ? context .getActualReturnType ().getType ()
572+ MethodReturn methodReturn = context .getMethodReturn ();
573+ boolean isProjecting = methodReturn .isProjecting ()
574+ || StringUtils .hasText (context .getDynamicProjectionParameterName ());
575+ Type actualReturnType = isProjecting ? methodReturn .getActualReturnClass ()
574576 : context .getRepositoryInformation ().getDomainType ();
575- builder .add ("\n " );
576577
577- Class <?> returnType = context .getMethod ().getReturnType ();
578- TypeName queryResultType = TypeName .get (context .getActualReturnType ().toClass ());
578+ Class <?> returnType = context .getMethodReturn ().toClass ();
579+
580+ TypeName queryResultType = methodReturn .getActualClassName ();
579581 String result = context .localVariable ("result" );
580582 String rowMapper = context .localVariable ("rowMapper" );
581583
582584 if (modifying .isPresent ()) {
583- return update (builder , returnType );
585+ return update (returnType );
584586 } else if (aotQuery .isCount ()) {
585- return count (builder , result , returnType , queryResultType );
587+ return count (result , returnType , queryResultType );
586588 } else if (aotQuery .isExists ()) {
587- return exists (builder , queryResultType );
589+ return exists (queryResultType );
588590 } else if (aotQuery .isDelete ()) {
589- return delete (builder , rowMapper , result , queryResultType , returnType , actualReturnType );
591+ return delete (rowMapper , result , queryResultType , returnType , actualReturnType );
590592 } else {
591593
592594 String resultSetExtractor = null ;
@@ -603,7 +605,7 @@ public CodeBlock build() {
603605 if (isProjecting ) {
604606 typeToRead = context .getReturnedType ().getDomainType ();
605607 } else {
606- typeToRead = context . getActualReturnType (). getType ();
608+ typeToRead = methodReturn . getActualReturnClass ();
607609 }
608610
609611 builder .addStatement ("$T $L = getRowMapperFactory().create($T.class)" , RowMapper .class , rowMapper ,
@@ -667,63 +669,61 @@ public CodeBlock build() {
667669 }
668670
669671 builder .addStatement ("return ($T) convertMany($L, %s)" .formatted (dynamicProjection ? "$L" : "$T.class" ),
670- context . getReturnTypeName (), result , queryResultTypeRef );
672+ methodReturn . getTypeName (), result , queryResultTypeRef );
671673 } else if (queryMethod .isStreamQuery ()) {
672674
673675 builder .addStatement ("$1T $2L = getJdbcOperations().queryForStream($3L, $4L, $5L)" , Stream .class , result ,
674676 queryVariableName , parameterSourceVariableName , rowMapper );
675- builder .addStatement ("return ($T) convertMany($L, $T.class)" , context . getReturnTypeName (), result ,
677+ builder .addStatement ("return ($T) convertMany($L, $T.class)" , methodReturn . getTypeName (), result ,
676678 queryResultTypeRef );
677679 } else {
678680
679681 builder .addStatement ("$T $L = queryForObject($L, $L, $L)" , Object .class , result , queryVariableName ,
680682 parameterSourceVariableName , rowMapper );
681683
682- if (Optional . class . isAssignableFrom ( context . getReturnType (). toClass () )) {
684+ if (methodReturn . isOptional ( )) {
683685 builder .addStatement (
684686 "return ($1T) $1T.ofNullable(convertOne($2L, %s))" .formatted (dynamicProjection ? "$3L" : "$3T.class" ),
685687 Optional .class , result , queryResultTypeRef );
686688 } else {
687689 builder .addStatement ("return ($T) convertOne($L, %s)" .formatted (dynamicProjection ? "$L" : "$T.class" ),
688- context . getReturnTypeName (), result , queryResultTypeRef );
690+ methodReturn . getTypeName (), result , queryResultTypeRef );
689691 }
690692 }
691693 }
692694
693695 return builder .build ();
694696 }
695697
696- private CodeBlock update (Builder builder , Class <?> returnType ) {
698+ private CodeBlock update (Class <?> returnType ) {
697699
698700 String result = context .localVariable ("result" );
699701
700- builder .add ("$[" );
701-
702- if (!ReflectionUtils .isVoid (returnType )) {
703- builder .add ("int $L = " , result );
704- }
702+ Builder builder = CodeBlock .builder ();
705703
706- builder . add ("getJdbcOperations().update($L, $L)" , queryVariableName , parameterSourceVariableName );
707- builder . add ( "; \n $]" );
704+ LordOfTheStrings . InvocationBuilder invoke = LordOfTheStrings . invoke ("getJdbcOperations().update($L, $L)" ,
705+ queryVariableName , parameterSourceVariableName );
708706
709- if (returnType == boolean .class || returnType == Boolean .class ) {
710- builder .addStatement ("return $L != 0" , result );
711- } else if (returnType == Long .class ) {
712- builder .addStatement ("return (long) $L" , result );
713- } else if (ReflectionUtils .isVoid (returnType )) {
714- if (returnType == Void .class ) {
715- builder .addStatement ("return null" );
716- }
707+ if (context .getMethodReturn ().isVoid ()) {
708+ builder .addStatement (invoke .build ());
717709 } else {
718- builder .addStatement ("return $L" , result );
710+ builder .addStatement (invoke . assignTo ( "int $L" , result ) );
719711 }
720712
713+ builder .addStatement (LordOfTheStrings .returning (returnType ) //
714+ .whenBoolean ("$L != 0" , result ) //
715+ .whenBoxedLong ("(long) $L" , result ) //
716+ .otherwise ("$L" , result )//
717+ .build ());
718+
721719 return builder .build ();
722720 }
723721
724- private CodeBlock delete (Builder builder , String rowMapper , String result , TypeName queryResultType ,
722+ private CodeBlock delete (String rowMapper , String result , TypeName queryResultType ,
725723 Class <?> returnType , Type actualReturnType ) {
726724
725+ CodeBlock .Builder builder = CodeBlock .builder ();
726+
727727 builder .addStatement ("$T $L = getRowMapperFactory().create($T.class)" , RowMapper .class , rowMapper ,
728728 context .getRepositoryInformation ().getDomainType ());
729729
@@ -732,48 +732,37 @@ private CodeBlock delete(Builder builder, String rowMapper, String result, TypeN
732732
733733 builder .addStatement ("$L.forEach(getOperations()::delete)" , result );
734734
735- if (Collection .class .isAssignableFrom (context .getReturnType ().toClass ())) {
736- builder .addStatement ("return ($T) convertMany($L, $T.class)" , context .getReturnTypeName (), result ,
737- queryResultType );
738- } else if (returnType == context .getRepositoryInformation ().getDomainType ()) {
739- builder .addStatement ("return ($1T) ($2L.isEmpty() ? null : $2L.iterator().next())" , actualReturnType , result );
740- } else if (returnType == boolean .class || returnType == Boolean .class ) {
741- builder .addStatement ("return !$L.isEmpty()" , result );
742- } else if (returnType == Long .class ) {
743- builder .addStatement ("return (long) $L.size()" , result );
744- } else if (ReflectionUtils .isVoid (returnType )) {
745- if (returnType == Void .class ) {
746- builder .addStatement ("return null" );
747- }
748- } else {
749- builder .addStatement ("return $L.size()" , result );
750- }
735+ builder .addStatement (LordOfTheStrings .returning (returnType ) //
736+ .when (Collection .class .isAssignableFrom (context .getMethodReturn ().toClass ()),
737+ "($T) convertMany($L, $T.class)" , context .getMethodReturn ().getTypeName (), result , queryResultType ) //
738+ .when (context .getRepositoryInformation ().getDomainType (),
739+ "($1T) ($2L.isEmpty() ? null : $2L.iterator().next())" , actualReturnType , result ) //
740+ .whenBoolean ("!$L.isEmpty()" , result ) //
741+ .whenBoxedLong ("(long) $L.size()" , result ) //
742+ .otherwise ("$L.size()" , result ) //
743+ .build ());
751744
752745 return builder .build ();
753746 }
754747
755- private CodeBlock count (Builder builder , String result , Class <?> returnType , TypeName queryResultType ) {
748+ private CodeBlock count (String result , Class <?> returnType , TypeName queryResultType ) {
749+
750+ CodeBlock .Builder builder = CodeBlock .builder ();
756751
757752 builder .addStatement ("$1T $2L = queryForObject($3L, $4L, new $5T<>($1T.class))" , Number .class , result ,
758753 queryVariableName , parameterSourceVariableName , SingleColumnRowMapper .class );
759754
760- if (returnType == Long .class ) {
761- builder .addStatement ("return $1L != null ? $1L.longValue() : null" , result );
762- } else if (returnType == Integer .class ) {
763- builder .addStatement ("return $1L != null ? $1L.intValue() : null" , result );
764- } else if (returnType == Long .TYPE ) {
765- builder .addStatement ("return $1L != null ? $1L.longValue() : 0L" , result );
766- } else if (returnType == Integer .TYPE ) {
767- builder .addStatement ("return $1L != null ? $1L.intValue() : 0" , result );
768- } else {
769- builder .addStatement ("return ($T) convertOne($L, $T.class)" , context .getReturnTypeName (), result ,
770- queryResultType );
771- }
755+ builder .addStatement (LordOfTheStrings .returning (returnType ) //
756+ .number (result ) //
757+ .otherwise ("($T) convertOne($L, $T.class)" , context .getMethodReturn ().getTypeName (), result , queryResultType ) //
758+ .build ());
772759
773760 return builder .build ();
774761 }
775762
776- private CodeBlock exists (Builder builder , TypeName queryResultType ) {
763+ private CodeBlock exists (TypeName queryResultType ) {
764+
765+ CodeBlock .Builder builder = CodeBlock .builder ();
777766
778767 builder .addStatement ("return ($T) getJdbcOperations().query($L, $L, $T::next)" , queryResultType ,
779768 queryVariableName , parameterSourceVariableName , ResultSet .class );
@@ -783,8 +772,8 @@ private CodeBlock exists(Builder builder, TypeName queryResultType) {
783772
784773 public static boolean returnsModifying (Class <?> returnType ) {
785774
786- return returnType == int . class || returnType == long . class || returnType == Integer .class
787- || returnType == Long .class ;
775+ return ClassUtils . resolvePrimitiveIfNecessary ( returnType ) == Integer .class
776+ || ClassUtils . resolvePrimitiveIfNecessary ( returnType ) == Long .class ;
788777 }
789778
790779 }
0 commit comments