diff --git a/src/main/java/org/springframework/data/repository/support/ReflectionRepositoryInvoker.java b/src/main/java/org/springframework/data/repository/support/ReflectionRepositoryInvoker.java index 8d3458347..efd1890ad 100644 --- a/src/main/java/org/springframework/data/repository/support/ReflectionRepositoryInvoker.java +++ b/src/main/java/org/springframework/data/repository/support/ReflectionRepositoryInvoker.java @@ -20,6 +20,7 @@ import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import org.springframework.core.MethodParameter; import org.springframework.core.convert.ConversionService; @@ -30,6 +31,8 @@ import org.springframework.data.repository.core.CrudMethods; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.query.Param; import org.springframework.util.Assert; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; @@ -164,12 +167,32 @@ class ReflectionRepositoryInvoker implements RepositoryInvoker { } } + /* + * (non-Javadoc) + * @see org.springframework.data.repository.support.RepositoryInvoker#invokeQueryMethod(java.lang.reflect.Method, java.util.Map, org.springframework.data.domain.Pageable, org.springframework.data.domain.Sort) + */ + @Override + public Object invokeQueryMethod(Method method, Map parameters, Pageable pageable, Sort sort) { + + Assert.notNull(method, "Method must not be null!"); + Assert.notNull(parameters, "Parameters must not be null!"); + + MultiValueMap forward = new LinkedMultiValueMap(parameters.size()); + + for (Entry entry : parameters.entrySet()) { + forward.put(entry.getKey(), Arrays.asList(entry.getValue())); + } + + return invokeQueryMethod(method, forward, pageable, sort); + } + /* * (non-Javadoc) * @see org.springframework.data.rest.core.invoke.RepositoryInvoker#invokeQueryMethod(java.lang.reflect.Method, java.util.Map, org.springframework.data.domain.Pageable, org.springframework.data.domain.Sort) */ @Override - public Object invokeQueryMethod(Method method, Map parameters, Pageable pageable, Sort sort) { + public Object invokeQueryMethod(Method method, MultiValueMap parameters, Pageable pageable, + Sort sort) { Assert.notNull(method, "Method must not be null!"); Assert.notNull(parameters, "Parameters must not be null!"); @@ -179,7 +202,8 @@ class ReflectionRepositoryInvoker implements RepositoryInvoker { return invoke(method, prepareParameters(method, parameters, pageable, sort)); } - private Object[] prepareParameters(Method method, Map rawParameters, Pageable pageable, Sort sort) { + private Object[] prepareParameters(Method method, MultiValueMap rawParameters, + Pageable pageable, Sort sort) { List parameters = new MethodParameters(method, PARAM_ANNOTATION).getParameters(); @@ -208,10 +232,10 @@ class ReflectionRepositoryInvoker implements RepositoryInvoker { + " for parameter " + parameterName); } - String[] parameterValue = rawParameters.get(parameterName); - Object value = parameterValue == null ? null : parameterValue.length == 1 ? parameterValue[0] : parameterValue; + Object value = unwrapSingleElement(rawParameters.get(parameterName)); - result[i] = conversionService.convert(value, TypeDescriptor.forObject(value), new TypeDescriptor(param)); + result[i] = targetType.isInstance(value) ? value : conversionService.convert(value, + TypeDescriptor.forObject(value), new TypeDescriptor(param)); } } @@ -275,4 +299,14 @@ class ReflectionRepositoryInvoker implements RepositoryInvoker { return invoke(method, sort); } + + /** + * Unwraps the first item if the given source has exactly one element. + * + * @param source can be {@literal null}. + * @return + */ + private static Object unwrapSingleElement(List source) { + return source == null ? null : source.size() == 1 ? source.get(0) : source; + } } diff --git a/src/main/java/org/springframework/data/repository/support/RepositoryInvoker.java b/src/main/java/org/springframework/data/repository/support/RepositoryInvoker.java index c779575cc..f29e1780a 100644 --- a/src/main/java/org/springframework/data/repository/support/RepositoryInvoker.java +++ b/src/main/java/org/springframework/data/repository/support/RepositoryInvoker.java @@ -21,6 +21,7 @@ import java.util.Map; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; +import org.springframework.util.MultiValueMap; /** * API to invoke (CRUD) methods on Spring Data repository instances independently of the base interface they expose. @@ -96,6 +97,22 @@ public interface RepositoryInvoker extends RepositoryInvocationInformation { * @param pageable can be {@literal null}. * @param sort can be {@literal null}. * @return the result of the invoked query method. + * @deprecated use {@link #invokeQueryMethod(Method, MultiValueMap, Pageable, Sort)} instead. */ + @Deprecated Object invokeQueryMethod(Method method, Map parameters, Pageable pageable, Sort sort); + + /** + * Invokes the query method backed by the given {@link Method} using the given parameters, {@link Pageable} and + * {@link Sort}. + * + * @param method must not be {@literal null}. + * @param parameters must not be {@literal null}. + * @param pageable can be {@literal null}. + * @param sort can be {@literal null}. + * @return the result of the invoked query method. + * @since 1.11 + */ + Object invokeQueryMethod(Method method, MultiValueMap parameters, Pageable pageable, + Sort sort); }