diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/QueryMapper.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/QueryMapper.java index 9c217b9e..485851e2 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/QueryMapper.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/QueryMapper.java @@ -280,19 +280,20 @@ class QueryMapper { Column column = table.column(propertyField.getMappedColumnName()); Object mappedValue; SQLType sqlType; + Comparator comparator = criteria.getComparator(); - if (criteria.getValue() instanceof JdbcValue) { + if (criteria.getValue()instanceof JdbcValue) { JdbcValue settableValue = (JdbcValue) criteria.getValue(); - mappedValue = convertValue(settableValue.getValue(), propertyField.getTypeHint()); + mappedValue = convertValue(comparator, settableValue.getValue(), propertyField.getTypeHint()); sqlType = getTypeHint(mappedValue, actualType.getType(), settableValue); } else if (criteria.getValue() instanceof ValueFunction) { ValueFunction valueFunction = (ValueFunction) criteria.getValue(); - Object value = valueFunction.apply(getEscaper(criteria.getComparator())); + Object value = valueFunction.apply(getEscaper(comparator)); - mappedValue = convertValue(value, propertyField.getTypeHint()); + mappedValue = convertValue(comparator, value, propertyField.getTypeHint()); sqlType = propertyField.getSqlType(); } else if (propertyField instanceof MetadataBackedField // @@ -302,17 +303,15 @@ class QueryMapper { RelationalPersistentProperty property = ((MetadataBackedField) propertyField).property; JdbcValue jdbcValue = convertToJdbcValue(property, criteria.getValue()); mappedValue = jdbcValue.getValue(); - sqlType = jdbcValue.getJdbcType() != null ? jdbcValue.getJdbcType() - : propertyField.getSqlType(); + sqlType = jdbcValue.getJdbcType() != null ? jdbcValue.getJdbcType() : propertyField.getSqlType(); } else { - mappedValue = convertValue(criteria.getValue(), propertyField.getTypeHint()); + mappedValue = convertValue(comparator, criteria.getValue(), propertyField.getTypeHint()); sqlType = propertyField.getSqlType(); } - return createCondition(column, mappedValue, sqlType, parameterSource, criteria.getComparator(), - criteria.isIgnoreCase()); + return createCondition(column, mappedValue, sqlType, parameterSource, comparator, criteria.isIgnoreCase()); } /** @@ -434,6 +433,24 @@ class QueryMapper { return Escaper.DEFAULT; } + @Nullable + private Object convertValue(Comparator comparator, @Nullable Object value, TypeInformation typeHint) { + + if (Comparator.IN.equals(comparator) && value instanceof Collection && !((Collection) value).isEmpty()) { + + Collection collection = (Collection) value; + Collection mapped = new ArrayList<>(collection.size()); + + for (Object o : collection) { + mapped.add(convertValue(o, typeHint)); + } + + return mapped; + } + + return convertValue(value, typeHint); + } + @Nullable protected Object convertValue(@Nullable Object value, TypeInformation typeInformation) { @@ -456,19 +473,6 @@ class QueryMapper { return Pair.of(first, second); } - if (value instanceof Iterable) { - - List mapped = new ArrayList<>(); - - for (Object o : (Iterable) value) { - - mapped.add(convertValue(o, typeInformation.getActualType() != null ? typeInformation.getRequiredActualType() - : ClassTypeInformation.OBJECT)); - } - - return mapped; - } - if (value.getClass().isArray() && (ClassTypeInformation.OBJECT.equals(typeInformation) || typeInformation.isCollectionLike())) { return value; @@ -482,7 +486,7 @@ class QueryMapper { } private Condition createCondition(Column column, @Nullable Object mappedValue, SQLType sqlType, - MapSqlParameterSource parameterSource, Comparator comparator, boolean ignoreCase) { + MapSqlParameterSource parameterSource, Comparator comparator, boolean ignoreCase) { if (comparator.equals(Comparator.IS_NULL)) { return column.isNull(); @@ -621,12 +625,12 @@ class QueryMapper { } private Expression bind(@Nullable Object mappedValue, SQLType sqlType, MapSqlParameterSource parameterSource, - String name) { + String name) { return bind(mappedValue, sqlType, parameterSource, name, false); } - private Expression bind(@Nullable Object mappedValue, SQLType sqlType, MapSqlParameterSource parameterSource, String name, - boolean ignoreCase) { + private Expression bind(@Nullable Object mappedValue, SQLType sqlType, MapSqlParameterSource parameterSource, + String name, boolean ignoreCase) { String uniqueName = getUniqueName(parameterSource, name); diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/BasicRelationalConverter.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/BasicRelationalConverter.java index 664ced8f..40898248 100644 --- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/BasicRelationalConverter.java +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/BasicRelationalConverter.java @@ -15,6 +15,8 @@ */ package org.springframework.data.relational.core.conversion; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -196,6 +198,32 @@ public class BasicRelationalConverter implements RelationalConverter { return getPotentiallyConvertedSimpleWrite(value); } + // TODO: We should add conversion support for arrays, however, + // these should consider multi-dimensional arrays as well. + if (value.getClass().isArray() && (ClassTypeInformation.OBJECT.equals(type) || type.isCollectionLike())) { + return value; + } + + if (value instanceof Collection) { + + List mapped = new ArrayList<>(); + + TypeInformation component = ClassTypeInformation.OBJECT; + if (type.isCollectionLike() && type.getActualType() != null) { + component = type.getRequiredComponentType(); + } + + for (Object o : (Iterable) value) { + mapped.add(writeValue(o, component)); + } + + if (type.getType().isInstance(mapped) || !type.isCollectionLike()) { + return mapped; + } + + return conversionService.convert(mapped, type.getType()); + } + RelationalPersistentEntity persistentEntity = context.getPersistentEntity(value.getClass()); if (persistentEntity != null) {