diff --git a/src/main/java/org/springframework/data/repository/query/Parameter.java b/src/main/java/org/springframework/data/repository/query/Parameter.java index 2c26d7cdd..89205e16e 100644 --- a/src/main/java/org/springframework/data/repository/query/Parameter.java +++ b/src/main/java/org/springframework/data/repository/query/Parameter.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Optional; import org.springframework.core.MethodParameter; +import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.ResolvableType; import org.springframework.data.domain.Limit; import org.springframework.data.domain.Pageable; @@ -59,7 +60,8 @@ public class Parameter { static { - List> types = new ArrayList<>(Arrays.asList(ScrollPosition.class, Pageable.class, Sort.class, Limit.class)); + List> types = new ArrayList<>( + Arrays.asList(ScrollPosition.class, Pageable.class, Sort.class, Limit.class)); // consider Kotlin Coroutines Continuation a special parameter. That parameter is synthetic and should not get // bound to any query. @@ -153,23 +155,39 @@ public class Parameter { } /** - * Returns whether the parameter is annotated with {@link Param}. + * Returns whether the parameter is annotated with {@link Param} or has a method parameter name. * * @return + * @see Param + * @see ParameterNameDiscoverer */ public boolean isNamedParameter() { return !isSpecialParameter() && getName().isPresent(); } /** - * Returns the name of the parameter (through {@link Param} annotation). + * Returns the name of the parameter (through {@link Param} annotation or method parameter naming). * - * @return + * @return the optional name of the parameter. */ public Optional getName() { return this.name.get(); } + /** + * Returns the required name of the parameter (through {@link Param} annotation or method parameter naming) or throws + * {@link IllegalStateException} if the parameter has no name. + * + * @return the required parameter name. + * @throws IllegalStateException if the parameter has no name. + * @since 3.4 + */ + public String getRequiredName() { + + return getName().orElseThrow(() -> new IllegalStateException("Parameter " + parameter + + " is not named. For queries with named parameters you need to provide names for method parameters; Use @Param for query method parameters, or use the javac flag -parameters.")); + } + /** * Returns the type of the {@link Parameter}. * diff --git a/src/test/java/org/springframework/data/repository/query/ParametersUnitTests.java b/src/test/java/org/springframework/data/repository/query/ParametersUnitTests.java index d827f65b0..edda88c45 100755 --- a/src/test/java/org/springframework/data/repository/query/ParametersUnitTests.java +++ b/src/test/java/org/springframework/data/repository/query/ParametersUnitTests.java @@ -128,12 +128,13 @@ class ParametersUnitTests { getParametersFor("validWithPageableFirst", Pageable.class, String.class); } - @Test // DATACMNS-731 + @Test // DATACMNS-731, GH-3124 void detectsExplicitlyNamedParameter() throws Exception { var parameter = getParametersFor("valid", String.class).getBindableParameter(0); - assertThat(parameter.getName()).isNotNull(); + assertThat(parameter.getName()).isNotEmpty(); + assertThat(parameter.getRequiredName()).isNotNull(); assertThat(parameter.isExplicitlyNamed()).isTrue(); } @@ -145,7 +146,7 @@ class ParametersUnitTests { var methodParameter = ReflectionTestUtils.getField(parameter, "parameter"); ReflectionTestUtils.setField(methodParameter, "parameterName", "name"); - assertThat(parameter.getName()).isNotNull(); + assertThat(parameter.getName()).isNotEmpty(); assertThat(parameter.isExplicitlyNamed()).isFalse(); }