Skip to content

Commit e7c3541

Browse files
gregturnodrotbohm
authored andcommitted
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.
1 parent 503d158 commit e7c3541

File tree

2 files changed

+38
-5
lines changed

2 files changed

+38
-5
lines changed

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
* @author Oliver Gierke
4343
* @author Mark Paluch
4444
* @author Jens Schauder
45+
* @author Greg Turnquist
4546
*/
4647
public class Parameter {
4748

@@ -79,7 +80,7 @@ protected Parameter(MethodParameter parameter) {
7980
this.parameter = parameter;
8081
this.parameterType = potentiallyUnwrapParameterType(parameter);
8182
this.isDynamicProjectionParameter = isDynamicProjectionParameter(parameter);
82-
this.name = TYPES.contains(parameter.getParameterType()) ? Lazy.of(Optional.empty()) : Lazy.of(() -> {
83+
this.name = isSpecialParameterType(parameter.getParameterType()) ? Lazy.of(Optional.empty()) : Lazy.of(() -> {
8384
Param annotation = parameter.getParameterAnnotation(Param.class);
8485
return Optional.ofNullable(annotation == null ? parameter.getParameterName() : annotation.value());
8586
});
@@ -92,7 +93,7 @@ protected Parameter(MethodParameter parameter) {
9293
* @see #TYPES
9394
*/
9495
public boolean isSpecialParameter() {
95-
return isDynamicProjectionParameter || TYPES.contains(parameter.getParameterType());
96+
return isDynamicProjectionParameter || isSpecialParameterType(parameter.getParameterType());
9697
}
9798

9899
/**
@@ -269,4 +270,22 @@ private static Class<?> potentiallyUnwrapParameterType(MethodParameter parameter
269270

270271
return originalType;
271272
}
273+
274+
/**
275+
* Identify is a given {@link Class} is either part of {@code TYPES} or an instanceof of one of its members. For
276+
* example, {@code PageRequest} is an instance of {@code Pageable} (a member of {@code TYPES}).
277+
*
278+
* @param parameterType must not be {@literal null}.
279+
* @return boolean
280+
*/
281+
private static boolean isSpecialParameterType(Class<?> parameterType) {
282+
283+
for (Class<?> specialParameterType : TYPES) {
284+
if (specialParameterType.isAssignableFrom(parameterType)) {
285+
return true;
286+
}
287+
}
288+
289+
return false;
290+
}
272291
}

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@
1919

2020
import org.junit.jupiter.api.BeforeEach;
2121
import org.junit.jupiter.api.Test;
22-
2322
import org.springframework.data.domain.PageRequest;
2423
import org.springframework.data.domain.Pageable;
2524

2625
/**
2726
* Unit tests for {@link ParametersParameterAccessor}.
2827
*
2928
* @author Oliver Gierke
29+
* @author Greg Turnquist
3030
*/
3131
class ParametersParameterAccessorUnitTests {
3232

@@ -69,16 +69,30 @@ void iteratesonlyOverBindableValues() throws Exception {
6969
var method = Sample.class.getMethod("method", Pageable.class, String.class);
7070
var parameters = new DefaultParameters(method);
7171

72-
var accessor = new ParametersParameterAccessor(parameters,
73-
new Object[] { PageRequest.of(0, 10), "Foo" });
72+
var accessor = new ParametersParameterAccessor(parameters, new Object[] { PageRequest.of(0, 10), "Foo" });
7473

7574
assertThat(accessor).hasSize(1);
75+
assertThat(accessor.getBindableValue(0)).isEqualTo("Foo");
76+
}
77+
78+
@Test // #2626
79+
void handlesPageRequestAsAParameterType() throws NoSuchMethodException {
80+
81+
var method = Sample.class.getMethod("methodWithPageRequest", PageRequest.class, String.class);
82+
var parameters = new DefaultParameters(method);
83+
84+
var accessor = new ParametersParameterAccessor(parameters, new Object[] { PageRequest.of(0, 10), "Foo" });
85+
86+
assertThat(accessor).hasSize(1);
87+
assertThat(accessor.getBindableValue(0)).isEqualTo("Foo");
7688
}
7789

7890
interface Sample {
7991

8092
void method(String string, int integer);
8193

8294
void method(Pageable pageable, String string);
95+
96+
void methodWithPageRequest(PageRequest pageRequest, String string);
8397
}
8498
}

0 commit comments

Comments
 (0)