Browse Source

Remove dialect dependency from QueryMapper.

See #1601
Original pull request: #1617
pull/1622/head
Jens Schauder 2 years ago committed by Mark Paluch
parent
commit
6fb6110ca0
No known key found for this signature in database
GPG Key ID: 4406B84C1661DCD1
  1. 39
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/QueryMapper.java
  2. 2
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlGenerator.java
  3. 53
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/EscapingParameterSource.java
  4. 2
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/JdbcQueryCreator.java
  5. 12
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/ParametrizedQuery.java
  6. 4
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/PartTreeJdbcQuery.java
  7. 2
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/QueryMapperUnitTests.java
  8. 33
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/PartTreeJdbcQueryUnitTests.java

39
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/QueryMapper.java

@ -23,6 +23,7 @@ import java.util.HashMap; @@ -23,6 +23,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import org.springframework.data.domain.Sort;
import org.springframework.data.jdbc.core.mapping.JdbcValue;
@ -60,7 +61,6 @@ import org.springframework.util.ClassUtils; @@ -60,7 +61,6 @@ import org.springframework.util.ClassUtils;
public class QueryMapper {
private final JdbcConverter converter;
private final Dialect dialect;
private final MappingContext<? extends RelationalPersistentEntity<?>, RelationalPersistentProperty> mappingContext;
/**
@ -68,18 +68,31 @@ public class QueryMapper { @@ -68,18 +68,31 @@ public class QueryMapper {
*
* @param dialect must not be {@literal null}.
* @param converter must not be {@literal null}.
* @deprecated use {@link QueryMapper(JdbcConverter)} instead.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Deprecated(since="3.2")
public QueryMapper(Dialect dialect, JdbcConverter converter) {
Assert.notNull(dialect, "Dialect must not be null");
Assert.notNull(converter, "JdbcConverter must not be null");
this.converter = converter;
this.dialect = dialect;
this.mappingContext = (MappingContext) converter.getMappingContext();
}
/**
* Creates a new {@link QueryMapper} with the given {@link JdbcConverter}.
*
* @param converter must not be {@literal null}.
*/
public QueryMapper( JdbcConverter converter) {
Assert.notNull(converter, "JdbcConverter must not be null");
this.converter = converter;
this.mappingContext = converter.getMappingContext();
}
/**
* Map the {@link Sort} object to apply field name mapping using {@link RelationalPersistentEntity the type to read}.
*
@ -295,16 +308,13 @@ public class QueryMapper { @@ -295,16 +308,13 @@ public class QueryMapper {
mappedValue = convertValue(comparator, settableValue.getValue(), propertyField.getTypeHint());
sqlType = getTypeHint(mappedValue, actualType.getType(), settableValue);
} else if (criteria.getValue() instanceof ValueFunction) {
} else if (criteria.getValue() instanceof ValueFunction valueFunction) {
ValueFunction<Object> valueFunction = (ValueFunction<Object>) criteria.getValue();
Object value = valueFunction.apply(getEscaper(comparator));
mappedValue = convertValue(comparator, value, propertyField.getTypeHint());
mappedValue = valueFunction;
sqlType = propertyField.getSqlType();
} else if (propertyField instanceof MetadataBackedField //
&& ((MetadataBackedField) propertyField).property != null //
} else if (propertyField instanceof MetadataBackedField metadataBackedField //
&& metadataBackedField.property != null //
&& (criteria.getValue() == null || !criteria.getValue().getClass().isArray())) {
RelationalPersistentProperty property = ((MetadataBackedField) propertyField).property;
@ -431,15 +441,6 @@ public class QueryMapper { @@ -431,15 +441,6 @@ public class QueryMapper {
return Conditions.nest(condition);
}
private Escaper getEscaper(Comparator comparator) {
if (comparator == Comparator.LIKE || comparator == Comparator.NOT_LIKE) {
return dialect.getLikeEscaper();
}
return Escaper.DEFAULT;
}
@Nullable
private Object convertValue(Comparator comparator, @Nullable Object value, TypeInformation<?> typeHint) {

2
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlGenerator.java

@ -113,7 +113,7 @@ class SqlGenerator { @@ -113,7 +113,7 @@ class SqlGenerator {
this.renderContext = new RenderContextFactory(dialect).createRenderContext();
this.sqlRenderer = SqlRenderer.create(renderContext);
this.columns = new Columns(entity, mappingContext, converter);
this.queryMapper = new QueryMapper(dialect, converter);
this.queryMapper = new QueryMapper(converter);
this.dialect = dialect;
}

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

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
/*
* Copyright 2023 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.jdbc.repository.query;
import org.springframework.data.relational.core.dialect.Escaper;
import org.springframework.data.relational.core.query.ValueFunction;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
/**
* This {@link SqlParameterSource} will apply escaping to it's values.
*
* @author Jens Schauder
* @since 3.2
*/
public class EscapingParameterSource implements SqlParameterSource {
private final SqlParameterSource parameterSource;
private final Escaper escaper;
public EscapingParameterSource(SqlParameterSource parameterSource, Escaper escaper) {
this.parameterSource = parameterSource;
this.escaper = escaper;
}
@Override
public boolean hasValue(String paramName) {
return parameterSource.hasValue(paramName);
}
@Override
public Object getValue(String paramName) throws IllegalArgumentException {
Object value = parameterSource.getValue(paramName);
if (value instanceof ValueFunction<?>) {
return ((ValueFunction<?>) value).apply(escaper);
}
return value;
}
}

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

@ -102,7 +102,7 @@ class JdbcQueryCreator extends RelationalQueryCreator<ParametrizedQuery> { @@ -102,7 +102,7 @@ class JdbcQueryCreator extends RelationalQueryCreator<ParametrizedQuery> {
this.accessor = accessor;
this.entityMetadata = entityMetadata;
this.queryMapper = new QueryMapper(dialect, converter);
this.queryMapper = new QueryMapper(converter);
this.renderContextFactory = new RenderContextFactory(dialect);
this.isSliceQuery = isSliceQuery;
this.returnedType = returnedType;

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

@ -15,12 +15,15 @@ @@ -15,12 +15,15 @@
*/
package org.springframework.data.jdbc.repository.query;
import org.springframework.data.relational.core.dialect.Dialect;
import org.springframework.data.relational.core.dialect.Escaper;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
/**
* Value object encapsulating a query containing named parameters and a{@link SqlParameterSource} to bind the parameters.
*
* @author Mark Paluch
* @author Jens Schauder
* @since 2.0
*/
class ParametrizedQuery {
@ -38,12 +41,13 @@ class ParametrizedQuery { @@ -38,12 +41,13 @@ class ParametrizedQuery {
return query;
}
SqlParameterSource getParameterSource() {
return parameterSource;
}
@Override
public String toString() {
return this.query;
}
public SqlParameterSource getParameterSource(Escaper escaper) {
return new EscapingParameterSource(parameterSource, escaper);
}
}

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

@ -126,7 +126,7 @@ public class PartTreeJdbcQuery extends AbstractJdbcQuery { @@ -126,7 +126,7 @@ public class PartTreeJdbcQuery extends AbstractJdbcQuery {
ParametrizedQuery query = createQuery(accessor, processor.getReturnedType());
JdbcQueryExecution<?> execution = getQueryExecution(processor, accessor);
return execution.execute(query.getQuery(), query.getParameterSource());
return execution.execute(query.getQuery(), query.getParameterSource(dialect.getLikeEscaper()));
}
private JdbcQueryExecution<?> getQueryExecution(ResultProcessor processor,
@ -164,7 +164,7 @@ public class PartTreeJdbcQuery extends AbstractJdbcQuery { @@ -164,7 +164,7 @@ public class PartTreeJdbcQuery extends AbstractJdbcQuery {
ParametrizedQuery countQuery = queryCreator.createQuery(Sort.unsorted());
Object count = singleObjectQuery((rs, i) -> rs.getLong(1)).execute(countQuery.getQuery(),
countQuery.getParameterSource());
countQuery.getParameterSource(dialect.getLikeEscaper()));
return converter.getConversionService().convert(count, Long.class);
});

2
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/QueryMapperUnitTests.java

@ -50,7 +50,7 @@ public class QueryMapperUnitTests { @@ -50,7 +50,7 @@ public class QueryMapperUnitTests {
JdbcMappingContext context = new JdbcMappingContext();
JdbcConverter converter = new BasicJdbcConverter(context, mock(RelationResolver.class));
QueryMapper mapper = new QueryMapper(PostgresDialect.INSTANCE, converter);
QueryMapper mapper = new QueryMapper(converter);
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
@Test // DATAJDBC-318

33
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/PartTreeJdbcQueryUnitTests.java

@ -36,6 +36,7 @@ import org.springframework.data.jdbc.core.convert.RelationResolver; @@ -36,6 +36,7 @@ import org.springframework.data.jdbc.core.convert.RelationResolver;
import org.springframework.data.jdbc.core.mapping.AggregateReference;
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.data.relational.core.dialect.Escaper;
import org.springframework.data.relational.core.dialect.H2Dialect;
import org.springframework.data.relational.core.mapping.Embedded;
import org.springframework.data.relational.core.mapping.MappedCollection;
@ -93,7 +94,7 @@ public class PartTreeJdbcQueryUnitTests { @@ -93,7 +94,7 @@ public class PartTreeJdbcQueryUnitTests {
softly.assertThat(query.getQuery())
.isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"HOBBY_REFERENCE\" = :hobby_reference");
softly.assertThat(query.getParameterSource().getValue("hobby_reference")).isEqualTo("twentythree");
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("hobby_reference")).isEqualTo("twentythree");
});
}
@ -112,8 +113,8 @@ public class PartTreeJdbcQueryUnitTests { @@ -112,8 +113,8 @@ public class PartTreeJdbcQueryUnitTests {
softly.assertThat(query.getQuery().toUpperCase()).endsWith("FOR UPDATE");
softly.assertThat(query.getParameterSource().getValue("first_name")).isEqualTo(firstname);
softly.assertThat(query.getParameterSource().getValue("last_name")).isEqualTo(lastname);
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("first_name")).isEqualTo(firstname);
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("last_name")).isEqualTo(lastname);
});
}
@ -133,8 +134,8 @@ public class PartTreeJdbcQueryUnitTests { @@ -133,8 +134,8 @@ public class PartTreeJdbcQueryUnitTests {
// this is also for update since h2 dialect does not distinguish between lockmodes
softly.assertThat(query.getQuery().toUpperCase()).endsWith("FOR UPDATE");
softly.assertThat(query.getParameterSource().getValue("first_name")).isEqualTo(firstname);
softly.assertThat(query.getParameterSource().getValue("age")).isEqualTo(age);
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("first_name")).isEqualTo(firstname);
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("age")).isEqualTo(age);
});
}
@ -165,7 +166,7 @@ public class PartTreeJdbcQueryUnitTests { @@ -165,7 +166,7 @@ public class PartTreeJdbcQueryUnitTests {
softly.assertThat(query.getQuery())
.isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"HOBBY_REFERENCE\" = :hobby_reference");
softly.assertThat(query.getParameterSource().getValue("hobby_reference")).isEqualTo("twentythree");
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("hobby_reference")).isEqualTo("twentythree");
});
}
@ -182,7 +183,7 @@ public class PartTreeJdbcQueryUnitTests { @@ -182,7 +183,7 @@ public class PartTreeJdbcQueryUnitTests {
softly.assertThat(query.getQuery())
.isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"HOBBY_REFERENCE\" = :hobby_reference");
softly.assertThat(query.getParameterSource().getValue("hobby_reference")).isEqualTo("twentythree");
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("hobby_reference")).isEqualTo("twentythree");
});
}
@ -270,8 +271,8 @@ public class PartTreeJdbcQueryUnitTests { @@ -270,8 +271,8 @@ public class PartTreeJdbcQueryUnitTests {
softly.assertThat(query.getQuery())
.isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"DATE_OF_BIRTH\" BETWEEN :date_of_birth AND :date_of_birth1");
softly.assertThat(query.getParameterSource().getValue("date_of_birth")).isEqualTo(from);
softly.assertThat(query.getParameterSource().getValue("date_of_birth1")).isEqualTo(to);
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("date_of_birth")).isEqualTo(from);
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("date_of_birth1")).isEqualTo(to);
});
}
@ -405,7 +406,7 @@ public class PartTreeJdbcQueryUnitTests { @@ -405,7 +406,7 @@ public class PartTreeJdbcQueryUnitTests {
ParametrizedQuery query = jdbcQuery.createQuery(accessor, returnedType);
assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
assertThat(query.getParameterSource().getValue("first_name")).isEqualTo("Jo%");
assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("first_name")).isEqualTo("Jo%");
}
@Test // DATAJDBC-318
@ -428,7 +429,7 @@ public class PartTreeJdbcQueryUnitTests { @@ -428,7 +429,7 @@ public class PartTreeJdbcQueryUnitTests {
ParametrizedQuery query = jdbcQuery.createQuery(accessor, returnedType);
assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
assertThat(query.getParameterSource().getValue("first_name")).isEqualTo("%hn");
assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("first_name")).isEqualTo("%hn");
}
@Test // DATAJDBC-318
@ -451,7 +452,7 @@ public class PartTreeJdbcQueryUnitTests { @@ -451,7 +452,7 @@ public class PartTreeJdbcQueryUnitTests {
ParametrizedQuery query = jdbcQuery.createQuery(accessor, returnedType);
assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
assertThat(query.getParameterSource().getValue("first_name")).isEqualTo("%oh%");
assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("first_name")).isEqualTo("%oh%");
}
@Test // DATAJDBC-318
@ -474,7 +475,7 @@ public class PartTreeJdbcQueryUnitTests { @@ -474,7 +475,7 @@ public class PartTreeJdbcQueryUnitTests {
ParametrizedQuery query = jdbcQuery.createQuery(accessor, returnedType);
assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" NOT LIKE :first_name");
assertThat(query.getParameterSource().getValue("first_name")).isEqualTo("%oh%");
assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("first_name")).isEqualTo("%oh%");
}
@Test // DATAJDBC-318
@ -638,8 +639,8 @@ public class PartTreeJdbcQueryUnitTests { @@ -638,8 +639,8 @@ public class PartTreeJdbcQueryUnitTests {
.contains(TABLE + ".\"USER_STREET\" = :user_street", //
" AND ", //
TABLE + ".\"USER_CITY\" = :user_city");
assertThat(query.getParameterSource().getValue("user_street")).isEqualTo("Hello");
assertThat(query.getParameterSource().getValue("user_city")).isEqualTo("World");
assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("user_street")).isEqualTo("Hello");
assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("user_city")).isEqualTo("World");
}
@Test // DATAJDBC-318
@ -653,7 +654,7 @@ public class PartTreeJdbcQueryUnitTests { @@ -653,7 +654,7 @@ public class PartTreeJdbcQueryUnitTests {
String expectedSql = BASE_SELECT + " WHERE " + TABLE + ".\"USER_STREET\" = :user_street";
assertThat(query.getQuery()).isEqualTo(expectedSql);
assertThat(query.getParameterSource().getValue("user_street")).isEqualTo("Hello");
assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("user_street")).isEqualTo("Hello");
}
@Test // DATAJDBC-534

Loading…
Cancel
Save