diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/QueryMapper.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/QueryMapper.java index 3ab54cc5..b79d6b1d 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/QueryMapper.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/QueryMapper.java @@ -53,6 +53,7 @@ import org.springframework.util.ClassUtils; * * @author Mark Paluch * @author Jens Schauder + * @author Yan Qiang * @since 3.0 */ public class QueryMapper { diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/QueryMapperUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/QueryMapperUnitTests.java index 1ef5a739..b8d83c7b 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/QueryMapperUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/QueryMapperUnitTests.java @@ -19,6 +19,8 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; import static org.springframework.data.domain.Sort.Order.*; +import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -26,6 +28,7 @@ import java.util.Objects; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.core.convert.converter.Converter; import org.springframework.data.domain.Sort; import org.springframework.data.jdbc.core.mapping.JdbcMappingContext; import org.springframework.data.relational.core.mapping.Column; @@ -52,6 +55,16 @@ public class QueryMapperUnitTests { QueryMapper mapper = new QueryMapper(converter); MapSqlParameterSource parameterSource = new MapSqlParameterSource(); + QueryMapper createMapper(Converter... converters) { + + JdbcCustomConversions conversions = new JdbcCustomConversions(Arrays.asList(converters)); + + JdbcConverter converter = new MappingJdbcConverter(context, mock(RelationResolver.class), conversions, + mock(JdbcTypeFactory.class)); + + return new QueryMapper(converter); + } + @Test // DATAJDBC-318 public void shouldNotMapEmptyCriteria() { @@ -308,6 +321,18 @@ public class QueryMapperUnitTests { assertThat(condition).hasToString("person.\"NAME\" NOT IN (?[:name], ?[:name1], ?[:name2])"); } + @Test + void shouldMapIsNotInWithCollectionToStringConverter() { + + mapper = createMapper(CollectionToStringConverter.INSTANCE); + + Criteria criteria = Criteria.where("name").notIn("a", "b", "c"); + + Condition bindings = map(criteria); + + assertThat(bindings).hasToString("person.\"NAME\" NOT IN (?[:name], ?[:name1], ?[:name2])"); + } + @Test // DATAJDBC-318 public void shouldMapIsGt() { @@ -415,7 +440,7 @@ public class QueryMapperUnitTests { assertThatThrownBy( () -> mapper.getMappedSort(Table.create("tbl"), sort, context.getRequiredPersistentEntity(Person.class))) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @Test // GH-1507 @@ -429,7 +454,7 @@ public class QueryMapperUnitTests { assertThat(fields) // .extracting(Objects::toString) // - .containsExactly( unsafeExpression + " ASC"); + .containsExactly(unsafeExpression + " ASC"); } private Condition map(Criteria criteria) { @@ -443,4 +468,13 @@ public class QueryMapperUnitTests { String name; @Column("another_name") String alternative; } + + enum CollectionToStringConverter implements Converter, String> { + INSTANCE; + + @Override + public String convert(Collection source) { + return source.toString(); + } + } } diff --git a/spring-data-r2dbc/src/main/java/org/springframework/data/r2dbc/query/QueryMapper.java b/spring-data-r2dbc/src/main/java/org/springframework/data/r2dbc/query/QueryMapper.java index ffc3dbb4..583281c7 100644 --- a/spring-data-r2dbc/src/main/java/org/springframework/data/r2dbc/query/QueryMapper.java +++ b/spring-data-r2dbc/src/main/java/org/springframework/data/r2dbc/query/QueryMapper.java @@ -58,6 +58,7 @@ import org.springframework.util.ClassUtils; * @author Roman Chigvintsev * @author Manousos Mathioudakis * @author Jens Schauder + * @author Yan Qiang */ public class QueryMapper { @@ -142,15 +143,13 @@ public class QueryMapper { SqlSort.validate(order); OrderByField simpleOrderByField = createSimpleOrderByField(table, entity, order); - OrderByField orderBy = simpleOrderByField - .withNullHandling(order.getNullHandling()); + OrderByField orderBy = simpleOrderByField.withNullHandling(order.getNullHandling()); mappedOrder.add(order.isAscending() ? orderBy.asc() : orderBy.desc()); } return mappedOrder; } - private OrderByField createSimpleOrderByField(Table table, RelationalPersistentEntity entity, Sort.Order order) { if (order instanceof SqlSort.SqlOrder sqlOrder && sqlOrder.isUnsafe()) { @@ -364,7 +363,7 @@ public class QueryMapper { Class typeHint; Comparator comparator = criteria.getComparator(); - if (criteria.getValue()instanceof Parameter parameter) { + if (criteria.getValue() instanceof Parameter parameter) { mappedValue = convertValue(comparator, parameter.getValue(), propertyField.getTypeHint()); typeHint = getTypeHint(mappedValue, actualType.getType(), parameter); @@ -411,7 +410,8 @@ public class QueryMapper { @Nullable private Object convertValue(Comparator comparator, @Nullable Object value, TypeInformation typeHint) { - if ((Comparator.IN.equals(comparator) || Comparator.NOT_IN.equals(comparator)) && value instanceof Collection collection && !collection.isEmpty()) { + if ((Comparator.IN.equals(comparator) || Comparator.NOT_IN.equals(comparator)) + && value instanceof Collection collection && !collection.isEmpty()) { Collection mapped = new ArrayList<>(collection.size()); diff --git a/spring-data-r2dbc/src/test/java/org/springframework/data/r2dbc/query/QueryMapperUnitTests.java b/spring-data-r2dbc/src/test/java/org/springframework/data/r2dbc/query/QueryMapperUnitTests.java index c9ac48e0..fb591eea 100644 --- a/spring-data-r2dbc/src/test/java/org/springframework/data/r2dbc/query/QueryMapperUnitTests.java +++ b/spring-data-r2dbc/src/test/java/org/springframework/data/r2dbc/query/QueryMapperUnitTests.java @@ -19,7 +19,11 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; import static org.springframework.data.domain.Sort.Order.*; -import java.util.*; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; import org.junit.jupiter.api.Test; import org.springframework.core.convert.converter.Converter; @@ -50,6 +54,7 @@ import org.testcontainers.shaded.com.fasterxml.jackson.databind.node.TextNode; * @author Mark Paluch * @author Mingyuan Wu * @author Jens Schauder + * @author Yan Qiang */ class QueryMapperUnitTests { @@ -61,6 +66,7 @@ class QueryMapperUnitTests { } QueryMapper createMapper(R2dbcDialect dialect, Converter... converters) { + R2dbcCustomConversions conversions = R2dbcCustomConversions.of(dialect, Arrays.asList(converters)); R2dbcMappingContext context = new R2dbcMappingContext(); @@ -359,9 +365,10 @@ class QueryMapperUnitTests { } @Test - void sholdMapIsNotInWithCollectionToStringConverter() { + void shouldMapIsNotInWithCollectionToStringConverter() { - mapper = createMapper(PostgresDialect.INSTANCE, JsonNodeToStringConverter.INSTANCE, StringToJsonNodeConverter.INSTANCE, CollectionToStringConverter.INSTANCE); + mapper = createMapper(PostgresDialect.INSTANCE, JsonNodeToStringConverter.INSTANCE, + StringToJsonNodeConverter.INSTANCE, CollectionToStringConverter.INSTANCE); Criteria criteria = Criteria.where("name").notIn("a", "b", "c"); @@ -479,14 +486,14 @@ class QueryMapperUnitTests { .containsExactly("tbl.x(._)x DESC"); } - @Test // GH-1507 public void shouldNotMapSortWithIllegalExpression() { Sort sort = Sort.by(desc("unknown Field")); assertThatThrownBy(() -> mapper.getMappedSort(Table.create("tbl"), sort, - mapper.getMappingContext().getRequiredPersistentEntity(Person.class))).isInstanceOf(IllegalArgumentException.class); + mapper.getMappingContext().getRequiredPersistentEntity(Person.class))) + .isInstanceOf(IllegalArgumentException.class); } @Test // gh-369 @@ -588,13 +595,13 @@ class QueryMapperUnitTests { enum CollectionToStringConverter implements Converter, String> { INSTANCE; + @Override public String convert(Collection source) { return source.toString(); } } - enum StringToJsonNodeConverter implements Converter { INSTANCE;