Skip to content

Commit 4809a1f

Browse files
committed
Apply custom converter for Collection-like values in queries.
We now apply converters only for Collection-like values and no longer to Iterable types. Closes #1452
1 parent addee83 commit 4809a1f

File tree

2 files changed

+58
-26
lines changed

2 files changed

+58
-26
lines changed

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/QueryMapper.java

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -280,19 +280,20 @@ private Condition mapCondition(CriteriaDefinition criteria, MapSqlParameterSourc
280280
Column column = table.column(propertyField.getMappedColumnName());
281281
Object mappedValue;
282282
SQLType sqlType;
283+
Comparator comparator = criteria.getComparator();
283284

284-
if (criteria.getValue() instanceof JdbcValue) {
285+
if (criteria.getValue()instanceof JdbcValue) {
285286

286287
JdbcValue settableValue = (JdbcValue) criteria.getValue();
287288

288-
mappedValue = convertValue(settableValue.getValue(), propertyField.getTypeHint());
289+
mappedValue = convertValue(comparator, settableValue.getValue(), propertyField.getTypeHint());
289290
sqlType = getTypeHint(mappedValue, actualType.getType(), settableValue);
290291
} else if (criteria.getValue() instanceof ValueFunction) {
291292

292293
ValueFunction<Object> valueFunction = (ValueFunction<Object>) criteria.getValue();
293-
Object value = valueFunction.apply(getEscaper(criteria.getComparator()));
294+
Object value = valueFunction.apply(getEscaper(comparator));
294295

295-
mappedValue = convertValue(value, propertyField.getTypeHint());
296+
mappedValue = convertValue(comparator, value, propertyField.getTypeHint());
296297
sqlType = propertyField.getSqlType();
297298

298299
} else if (propertyField instanceof MetadataBackedField //
@@ -302,17 +303,15 @@ private Condition mapCondition(CriteriaDefinition criteria, MapSqlParameterSourc
302303
RelationalPersistentProperty property = ((MetadataBackedField) propertyField).property;
303304
JdbcValue jdbcValue = convertToJdbcValue(property, criteria.getValue());
304305
mappedValue = jdbcValue.getValue();
305-
sqlType = jdbcValue.getJdbcType() != null ? jdbcValue.getJdbcType()
306-
: propertyField.getSqlType();
306+
sqlType = jdbcValue.getJdbcType() != null ? jdbcValue.getJdbcType() : propertyField.getSqlType();
307307

308308
} else {
309309

310-
mappedValue = convertValue(criteria.getValue(), propertyField.getTypeHint());
310+
mappedValue = convertValue(comparator, criteria.getValue(), propertyField.getTypeHint());
311311
sqlType = propertyField.getSqlType();
312312
}
313313

314-
return createCondition(column, mappedValue, sqlType, parameterSource, criteria.getComparator(),
315-
criteria.isIgnoreCase());
314+
return createCondition(column, mappedValue, sqlType, parameterSource, comparator, criteria.isIgnoreCase());
316315
}
317316

318317
/**
@@ -434,6 +433,24 @@ private Escaper getEscaper(Comparator comparator) {
434433
return Escaper.DEFAULT;
435434
}
436435

436+
@Nullable
437+
private Object convertValue(Comparator comparator, @Nullable Object value, TypeInformation<?> typeHint) {
438+
439+
if (Comparator.IN.equals(comparator) && value instanceof Collection<?> && !((Collection<?>) value).isEmpty()) {
440+
441+
Collection<?> collection = (Collection<?>) value;
442+
Collection<Object> mapped = new ArrayList<>(collection.size());
443+
444+
for (Object o : collection) {
445+
mapped.add(convertValue(o, typeHint));
446+
}
447+
448+
return mapped;
449+
}
450+
451+
return convertValue(value, typeHint);
452+
}
453+
437454
@Nullable
438455
protected Object convertValue(@Nullable Object value, TypeInformation<?> typeInformation) {
439456

@@ -456,19 +473,6 @@ protected Object convertValue(@Nullable Object value, TypeInformation<?> typeInf
456473
return Pair.of(first, second);
457474
}
458475

459-
if (value instanceof Iterable) {
460-
461-
List<Object> mapped = new ArrayList<>();
462-
463-
for (Object o : (Iterable<?>) value) {
464-
465-
mapped.add(convertValue(o, typeInformation.getActualType() != null ? typeInformation.getRequiredActualType()
466-
: ClassTypeInformation.OBJECT));
467-
}
468-
469-
return mapped;
470-
}
471-
472476
if (value.getClass().isArray()
473477
&& (ClassTypeInformation.OBJECT.equals(typeInformation) || typeInformation.isCollectionLike())) {
474478
return value;
@@ -482,7 +486,7 @@ protected MappingContext<? extends RelationalPersistentEntity<?>, RelationalPers
482486
}
483487

484488
private Condition createCondition(Column column, @Nullable Object mappedValue, SQLType sqlType,
485-
MapSqlParameterSource parameterSource, Comparator comparator, boolean ignoreCase) {
489+
MapSqlParameterSource parameterSource, Comparator comparator, boolean ignoreCase) {
486490

487491
if (comparator.equals(Comparator.IS_NULL)) {
488492
return column.isNull();
@@ -621,12 +625,12 @@ SQLType getTypeHint(@Nullable Object mappedValue, Class<?> propertyType, JdbcVal
621625
}
622626

623627
private Expression bind(@Nullable Object mappedValue, SQLType sqlType, MapSqlParameterSource parameterSource,
624-
String name) {
628+
String name) {
625629
return bind(mappedValue, sqlType, parameterSource, name, false);
626630
}
627631

628-
private Expression bind(@Nullable Object mappedValue, SQLType sqlType, MapSqlParameterSource parameterSource, String name,
629-
boolean ignoreCase) {
632+
private Expression bind(@Nullable Object mappedValue, SQLType sqlType, MapSqlParameterSource parameterSource,
633+
String name, boolean ignoreCase) {
630634

631635
String uniqueName = getUniqueName(parameterSource, name);
632636

spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/BasicRelationalConverter.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.springframework.data.relational.core.conversion;
1717

18+
import java.util.ArrayList;
19+
import java.util.Collection;
1820
import java.util.Collections;
1921
import java.util.List;
2022
import java.util.Optional;
@@ -196,6 +198,32 @@ public Object writeValue(@Nullable Object value, TypeInformation<?> type) {
196198
return getPotentiallyConvertedSimpleWrite(value);
197199
}
198200

201+
// TODO: We should add conversion support for arrays, however,
202+
// these should consider multi-dimensional arrays as well.
203+
if (value.getClass().isArray() && (ClassTypeInformation.OBJECT.equals(type) || type.isCollectionLike())) {
204+
return value;
205+
}
206+
207+
if (value instanceof Collection<?>) {
208+
209+
List<Object> mapped = new ArrayList<>();
210+
211+
TypeInformation<?> component = ClassTypeInformation.OBJECT;
212+
if (type.isCollectionLike() && type.getActualType() != null) {
213+
component = type.getRequiredComponentType();
214+
}
215+
216+
for (Object o : (Iterable<?>) value) {
217+
mapped.add(writeValue(o, component));
218+
}
219+
220+
if (type.getType().isInstance(mapped) || !type.isCollectionLike()) {
221+
return mapped;
222+
}
223+
224+
return conversionService.convert(mapped, type.getType());
225+
}
226+
199227
RelationalPersistentEntity<?> persistentEntity = context.getPersistentEntity(value.getClass());
200228

201229
if (persistentEntity != null) {

0 commit comments

Comments
 (0)