Skip to content

Commit

Permalink
Remove dialect dependency from QueryMapper.
Browse files Browse the repository at this point in the history
See #1601
Original pull request: #1617
  • Loading branch information
schauder authored and mp911de committed Sep 26, 2023
1 parent 610bc45 commit 6fb6110
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
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;
Expand Down Expand Up @@ -60,26 +61,38 @@
public class QueryMapper {

private final JdbcConverter converter;
private final Dialect dialect;
private final MappingContext<? extends RelationalPersistentEntity<?>, RelationalPersistentProperty> mappingContext;

/**
* Creates a new {@link QueryMapper} with the given {@link JdbcConverter}.
*
* @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}.
*
Expand Down Expand Up @@ -295,16 +308,13 @@ private Condition mapCondition(CriteriaDefinition criteria, MapSqlParameterSourc

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;
Expand Down Expand Up @@ -431,15 +441,6 @@ private Condition mapEmbeddedObjectCondition(CriteriaDefinition criteria, MapSql
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) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -38,12 +41,13 @@ String getQuery() {
return query;
}

SqlParameterSource getParameterSource() {
return parameterSource;
}

@Override
public String toString() {
return this.query;
}

public SqlParameterSource getParameterSource(Escaper escaper) {

return new EscapingParameterSource(parameterSource, escaper);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public Object execute(Object[] values) {
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,
Expand Down Expand Up @@ -164,7 +164,7 @@ private JdbcQueryExecution<?> getQueryExecution(ResultProcessor processor,

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);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
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;
Expand Down Expand Up @@ -93,7 +94,7 @@ public void createQueryByAggregateReference() throws Exception {
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");
});
}

Expand All @@ -112,8 +113,8 @@ void createQueryWithPessimisticWriteLock() throws Exception {

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);
});
}

Expand All @@ -133,8 +134,8 @@ void createQueryWithPessimisticReadLock() throws Exception {
// 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);
});
}

Expand Down Expand Up @@ -165,7 +166,7 @@ public void createQueryForQueryByAggregateReference() throws Exception {
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");
});
}

Expand All @@ -182,7 +183,7 @@ public void createQueryForQueryByAggregateReferenceId() throws Exception {
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");
});
}

Expand Down Expand Up @@ -270,8 +271,8 @@ public void createsQueryToFindAllEntitiesByDateAttributeBetween() throws Excepti
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);
});
}

Expand Down Expand Up @@ -405,7 +406,7 @@ public void appendsLikeOperatorParameterWithPercentSymbolForStartingWithQuery()
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
Expand All @@ -428,7 +429,7 @@ public void prependsLikeOperatorParameterWithPercentSymbolForEndingWithQuery() t
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
Expand All @@ -451,7 +452,7 @@ public void wrapsLikeOperatorParameterWithPercentSymbolsForContainingQuery() thr
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
Expand All @@ -474,7 +475,7 @@ public void wrapsLikeOperatorParameterWithPercentSymbolsForNotContainingQuery()
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
Expand Down Expand Up @@ -638,8 +639,8 @@ public void createsQueryByEmbeddedObject() throws Exception {
.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
Expand All @@ -653,7 +654,7 @@ public void createsQueryByEmbeddedProperty() throws Exception {
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
Expand Down

0 comments on commit 6fb6110

Please sign in to comment.