diff --git a/pom.xml b/pom.xml index d2cdc888fa..7d792cb068 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-relational-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAJDBC-539-SNAPSHOT pom Spring Data Relational Parent diff --git a/spring-data-jdbc-distribution/pom.xml b/spring-data-jdbc-distribution/pom.xml index 858a5f4b4b..0591a15da5 100644 --- a/spring-data-jdbc-distribution/pom.xml +++ b/spring-data-jdbc-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-relational-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAJDBC-539-SNAPSHOT ../pom.xml diff --git a/spring-data-jdbc/pom.xml b/spring-data-jdbc/pom.xml index c172e3e683..a2e00eaf02 100644 --- a/spring-data-jdbc/pom.xml +++ b/spring-data-jdbc/pom.xml @@ -6,7 +6,7 @@ 4.0.0 spring-data-jdbc - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAJDBC-539-SNAPSHOT Spring Data JDBC Spring Data module for JDBC repositories. @@ -15,7 +15,7 @@ org.springframework.data spring-data-relational-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAJDBC-539-SNAPSHOT diff --git a/spring-data-relational/pom.xml b/spring-data-relational/pom.xml index 0a529399c3..9e8cb6e7ee 100644 --- a/spring-data-relational/pom.xml +++ b/spring-data-relational/pom.xml @@ -6,7 +6,7 @@ 4.0.0 spring-data-relational - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAJDBC-539-SNAPSHOT Spring Data Relational Spring Data Relational support @@ -14,7 +14,7 @@ org.springframework.data spring-data-relational-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAJDBC-539-SNAPSHOT diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/CriteriaFactory.java b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/CriteriaFactory.java index 00eadcd7f2..fed7dfe215 100644 --- a/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/CriteriaFactory.java +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/CriteriaFactory.java @@ -15,10 +15,14 @@ */ package org.springframework.data.relational.repository.query; +import java.util.Collection; +import java.util.Collections; + import org.springframework.data.relational.core.query.Criteria; import org.springframework.data.relational.core.sql.Expression; import org.springframework.data.repository.query.parser.Part; import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; /** * Simple factory to contain logic to create {@link Criteria}s from {@link Part}s. @@ -90,8 +94,8 @@ public Criteria createCriteria(Part part) { case IN: case NOT_IN: { ParameterMetadata paramMetadata = parameterMetadataProvider.next(part); - Criteria criteria = part.getType() == Part.Type.IN ? criteriaStep.in(paramMetadata.getValue()) - : criteriaStep.notIn(paramMetadata.getValue()); + Criteria criteria = part.getType() == Part.Type.IN ? criteriaStep.in(asCollection(paramMetadata.getValue())) + : criteriaStep.notIn(asCollection(paramMetadata.getValue())); return criteria.ignoreCase(shouldIgnoreCase(part) && checkCanUpperCase(part, part.getProperty().getType())); } case STARTING_WITH: @@ -163,4 +167,18 @@ private boolean checkCanUpperCase(Part part, Class... expressionTypes) { private boolean canUpperCase(Class expressionType) { return expressionType == String.class; } + + @SuppressWarnings("unchecked") + private static Collection asCollection(Object value) { + + if (value instanceof Collection) { + return (Collection) value; + } + + if (value.getClass().isArray()) { + return CollectionUtils.arrayToList(value); + } + + return Collections.singletonList(value); + } } diff --git a/spring-data-relational/src/test/java/org/springframework/data/relational/repository/query/CriteriaFactoryUnitTests.java b/spring-data-relational/src/test/java/org/springframework/data/relational/repository/query/CriteriaFactoryUnitTests.java new file mode 100644 index 0000000000..613485f869 --- /dev/null +++ b/spring-data-relational/src/test/java/org/springframework/data/relational/repository/query/CriteriaFactoryUnitTests.java @@ -0,0 +1,98 @@ +/* + * Copyright 2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.relational.repository.query; + +import static org.assertj.core.api.Assertions.*; + +import lombok.Data; +import lombok.SneakyThrows; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import org.springframework.data.projection.SpelAwareProxyProjectionFactory; +import org.springframework.data.relational.core.query.Criteria; +import org.springframework.data.repository.Repository; +import org.springframework.data.repository.core.support.DefaultRepositoryMetadata; +import org.springframework.data.repository.query.QueryMethod; +import org.springframework.data.repository.query.parser.Part; + +/** + * Unit tests for {@link CriteriaFactory}. + * + * @author Mark Paluch + */ +public class CriteriaFactoryUnitTests { + + @Test // DATAJDBC-539 + void shouldConsiderIterableValuesInInOperator() { + + QueryMethod queryMethod = getQueryMethod("findAllByNameIn", List.class); + RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, Arrays.asList("foo", "bar")); + ParameterMetadataProvider parameterMetadata = new ParameterMetadataProvider(accessor); + CriteriaFactory criteriaFactory = new CriteriaFactory(parameterMetadata); + + Part part = new Part("NameIn", User.class); + + Criteria criteria = criteriaFactory.createCriteria(part); + + assertThat(criteria.getValue()).isEqualTo(Arrays.asList("foo", "bar")); + } + + @Test // DATAJDBC-539 + void shouldConsiderArrayValuesInInOperator() { + + QueryMethod queryMethod = getQueryMethod("findAllByNameIn", String[].class); + + RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, + new Object[] { new String[] { "foo", "bar" } }); + ParameterMetadataProvider parameterMetadata = new ParameterMetadataProvider(accessor); + CriteriaFactory criteriaFactory = new CriteriaFactory(parameterMetadata); + + Part part = new Part("NameIn", User.class); + + Criteria criteria = criteriaFactory.createCriteria(part); + + assertThat(criteria.getValue()).isEqualTo(Arrays.asList("foo", "bar")); + } + + @SneakyThrows + private QueryMethod getQueryMethod(String methodName, Class... parameterTypes) { + Method method = UserRepository.class.getMethod(methodName, parameterTypes); + return new QueryMethod(method, new DefaultRepositoryMetadata(UserRepository.class), + new SpelAwareProxyProjectionFactory()); + } + + private RelationalParametersParameterAccessor getAccessor(QueryMethod queryMethod, Object... values) { + return new RelationalParametersParameterAccessor(queryMethod, values); + } + + interface UserRepository extends Repository { + + User findAllByNameIn(List names); + + User findAllByNameIn(String[] names); + } + + @Data + static class User { + + String name; + } +}