Browse Source

Extend query method special parameter types to any subclasses.

Spring Data Commons has a hard-coded list of special types than can be included in query methods including Pageable and Sort.

A custom finder with PageRequest, even though it extends Pageable, will fail when it would work fine with a narrowed input. This extends the list using an assignability check.

Related: spring-projects/spring-data-jpa#2013
See #2626.
pull/2772/head
Greg L. Turnquist 4 years ago committed by Oliver Drotbohm
parent
commit
1c42faf813
No known key found for this signature in database
GPG Key ID: C25FBFA0DA493A1D
  1. 23
      src/main/java/org/springframework/data/repository/query/Parameter.java
  2. 16
      src/test/java/org/springframework/data/repository/query/ParametersParameterAccessorUnitTests.java

23
src/main/java/org/springframework/data/repository/query/Parameter.java

@ -42,6 +42,7 @@ import org.springframework.util.Assert;
* @author Oliver Gierke * @author Oliver Gierke
* @author Mark Paluch * @author Mark Paluch
* @author Jens Schauder * @author Jens Schauder
* @author Greg Turnquist
*/ */
public class Parameter { public class Parameter {
@ -79,7 +80,7 @@ public class Parameter {
this.parameter = parameter; this.parameter = parameter;
this.parameterType = potentiallyUnwrapParameterType(parameter); this.parameterType = potentiallyUnwrapParameterType(parameter);
this.isDynamicProjectionParameter = isDynamicProjectionParameter(parameter); this.isDynamicProjectionParameter = isDynamicProjectionParameter(parameter);
this.name = TYPES.contains(parameter.getParameterType()) ? Lazy.of(Optional.empty()) : Lazy.of(() -> { this.name = isSpecialParameterType(parameter.getParameterType()) ? Lazy.of(Optional.empty()) : Lazy.of(() -> {
Param annotation = parameter.getParameterAnnotation(Param.class); Param annotation = parameter.getParameterAnnotation(Param.class);
return Optional.ofNullable(annotation == null ? parameter.getParameterName() : annotation.value()); return Optional.ofNullable(annotation == null ? parameter.getParameterName() : annotation.value());
}); });
@ -92,7 +93,7 @@ public class Parameter {
* @see #TYPES * @see #TYPES
*/ */
public boolean isSpecialParameter() { public boolean isSpecialParameter() {
return isDynamicProjectionParameter || TYPES.contains(parameter.getParameterType()); return isDynamicProjectionParameter || isSpecialParameterType(parameter.getParameterType());
} }
/** /**
@ -273,4 +274,22 @@ public class Parameter {
return originalType; return originalType;
} }
/**
* Identify is a given {@link Class} is either part of {@code TYPES} or an instanceof of one of its members. For
* example, {@code PageRequest} is an instance of {@code Pageable} (a member of {@code TYPES}).
*
* @param parameterType must not be {@literal null}.
* @return boolean
*/
private static boolean isSpecialParameterType(Class<?> parameterType) {
for (Class<?> specialParameterType : TYPES) {
if (specialParameterType.isAssignableFrom(parameterType)) {
return true;
}
}
return false;
}
} }

16
src/test/java/org/springframework/data/repository/query/ParametersParameterAccessorUnitTests.java

@ -29,6 +29,7 @@ import org.springframework.data.domain.Pageable;
* Unit tests for {@link ParametersParameterAccessor}. * Unit tests for {@link ParametersParameterAccessor}.
* *
* @author Oliver Gierke * @author Oliver Gierke
* @author Greg Turnquist
*/ */
class ParametersParameterAccessorUnitTests { class ParametersParameterAccessorUnitTests {
@ -75,6 +76,19 @@ class ParametersParameterAccessorUnitTests {
new Object[] { PageRequest.of(0, 10), "Foo" }); new Object[] { PageRequest.of(0, 10), "Foo" });
assertThat(accessor).hasSize(1); assertThat(accessor).hasSize(1);
assertThat(accessor.getBindableValue(0)).isEqualTo("Foo");
}
@Test // #2626
void handlesPageRequestAsAParameterType() throws NoSuchMethodException {
Method method = Sample.class.getMethod("methodWithPageRequest", PageRequest.class, String.class);
DefaultParameters parameters = new DefaultParameters(method);
ParameterAccessor accessor = new ParametersParameterAccessor(parameters, new Object[] { PageRequest.of(0, 10), "Foo" });
assertThat(accessor).hasSize(1);
assertThat(accessor.getBindableValue(0)).isEqualTo("Foo");
} }
interface Sample { interface Sample {
@ -82,5 +96,7 @@ class ParametersParameterAccessorUnitTests {
void method(String string, int integer); void method(String string, int integer);
void method(Pageable pageable, String string); void method(Pageable pageable, String string);
void methodWithPageRequest(PageRequest pageRequest, String string);
} }
} }

Loading…
Cancel
Save