Skip to content

Commit 6fb6110

Browse files
schaudermp911de
authored andcommitted
Remove dialect dependency from QueryMapper.
See #1601 Original pull request: #1617
1 parent 610bc45 commit 6fb6110

File tree

8 files changed

+103
-44
lines changed

8 files changed

+103
-44
lines changed

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

+20-19
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.List;
2424
import java.util.Map;
2525
import java.util.Objects;
26+
import java.util.function.Function;
2627

2728
import org.springframework.data.domain.Sort;
2829
import org.springframework.data.jdbc.core.mapping.JdbcValue;
@@ -60,26 +61,38 @@
6061
public class QueryMapper {
6162

6263
private final JdbcConverter converter;
63-
private final Dialect dialect;
6464
private final MappingContext<? extends RelationalPersistentEntity<?>, RelationalPersistentProperty> mappingContext;
6565

6666
/**
6767
* Creates a new {@link QueryMapper} with the given {@link JdbcConverter}.
6868
*
6969
* @param dialect must not be {@literal null}.
7070
* @param converter must not be {@literal null}.
71+
* @deprecated use {@link QueryMapper(JdbcConverter)} instead.
7172
*/
72-
@SuppressWarnings({ "unchecked", "rawtypes" })
73+
@Deprecated(since="3.2")
7374
public QueryMapper(Dialect dialect, JdbcConverter converter) {
7475

7576
Assert.notNull(dialect, "Dialect must not be null");
7677
Assert.notNull(converter, "JdbcConverter must not be null");
7778

7879
this.converter = converter;
79-
this.dialect = dialect;
8080
this.mappingContext = (MappingContext) converter.getMappingContext();
8181
}
8282

83+
/**
84+
* Creates a new {@link QueryMapper} with the given {@link JdbcConverter}.
85+
*
86+
* @param converter must not be {@literal null}.
87+
*/
88+
public QueryMapper( JdbcConverter converter) {
89+
90+
Assert.notNull(converter, "JdbcConverter must not be null");
91+
92+
this.converter = converter;
93+
this.mappingContext = converter.getMappingContext();
94+
}
95+
8396
/**
8497
* Map the {@link Sort} object to apply field name mapping using {@link RelationalPersistentEntity the type to read}.
8598
*
@@ -295,16 +308,13 @@ private Condition mapCondition(CriteriaDefinition criteria, MapSqlParameterSourc
295308

296309
mappedValue = convertValue(comparator, settableValue.getValue(), propertyField.getTypeHint());
297310
sqlType = getTypeHint(mappedValue, actualType.getType(), settableValue);
298-
} else if (criteria.getValue() instanceof ValueFunction) {
311+
} else if (criteria.getValue() instanceof ValueFunction valueFunction) {
299312

300-
ValueFunction<Object> valueFunction = (ValueFunction<Object>) criteria.getValue();
301-
Object value = valueFunction.apply(getEscaper(comparator));
302-
303-
mappedValue = convertValue(comparator, value, propertyField.getTypeHint());
313+
mappedValue = valueFunction;
304314
sqlType = propertyField.getSqlType();
305315

306-
} else if (propertyField instanceof MetadataBackedField //
307-
&& ((MetadataBackedField) propertyField).property != null //
316+
} else if (propertyField instanceof MetadataBackedField metadataBackedField //
317+
&& metadataBackedField.property != null //
308318
&& (criteria.getValue() == null || !criteria.getValue().getClass().isArray())) {
309319

310320
RelationalPersistentProperty property = ((MetadataBackedField) propertyField).property;
@@ -431,15 +441,6 @@ private Condition mapEmbeddedObjectCondition(CriteriaDefinition criteria, MapSql
431441
return Conditions.nest(condition);
432442
}
433443

434-
private Escaper getEscaper(Comparator comparator) {
435-
436-
if (comparator == Comparator.LIKE || comparator == Comparator.NOT_LIKE) {
437-
return dialect.getLikeEscaper();
438-
}
439-
440-
return Escaper.DEFAULT;
441-
}
442-
443444
@Nullable
444445
private Object convertValue(Comparator comparator, @Nullable Object value, TypeInformation<?> typeHint) {
445446

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ class SqlGenerator {
113113
this.renderContext = new RenderContextFactory(dialect).createRenderContext();
114114
this.sqlRenderer = SqlRenderer.create(renderContext);
115115
this.columns = new Columns(entity, mappingContext, converter);
116-
this.queryMapper = new QueryMapper(dialect, converter);
116+
this.queryMapper = new QueryMapper(converter);
117117
this.dialect = dialect;
118118
}
119119

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.data.jdbc.repository.query;
18+
19+
import org.springframework.data.relational.core.dialect.Escaper;
20+
import org.springframework.data.relational.core.query.ValueFunction;
21+
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
22+
23+
/**
24+
* This {@link SqlParameterSource} will apply escaping to it's values.
25+
*
26+
* @author Jens Schauder
27+
* @since 3.2
28+
*/
29+
public class EscapingParameterSource implements SqlParameterSource {
30+
private final SqlParameterSource parameterSource;
31+
private final Escaper escaper;
32+
33+
public EscapingParameterSource(SqlParameterSource parameterSource, Escaper escaper) {
34+
35+
this.parameterSource = parameterSource;
36+
this.escaper = escaper;
37+
}
38+
39+
@Override
40+
public boolean hasValue(String paramName) {
41+
return parameterSource.hasValue(paramName);
42+
}
43+
44+
@Override
45+
public Object getValue(String paramName) throws IllegalArgumentException {
46+
47+
Object value = parameterSource.getValue(paramName);
48+
if (value instanceof ValueFunction<?>) {
49+
return ((ValueFunction<?>) value).apply(escaper);
50+
}
51+
return value;
52+
}
53+
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class JdbcQueryCreator extends RelationalQueryCreator<ParametrizedQuery> {
102102
this.accessor = accessor;
103103

104104
this.entityMetadata = entityMetadata;
105-
this.queryMapper = new QueryMapper(dialect, converter);
105+
this.queryMapper = new QueryMapper(converter);
106106
this.renderContextFactory = new RenderContextFactory(dialect);
107107
this.isSliceQuery = isSliceQuery;
108108
this.returnedType = returnedType;

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

+8-4
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,15 @@
1515
*/
1616
package org.springframework.data.jdbc.repository.query;
1717

18+
import org.springframework.data.relational.core.dialect.Dialect;
19+
import org.springframework.data.relational.core.dialect.Escaper;
1820
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
1921

2022
/**
2123
* Value object encapsulating a query containing named parameters and a{@link SqlParameterSource} to bind the parameters.
2224
*
2325
* @author Mark Paluch
26+
* @author Jens Schauder
2427
* @since 2.0
2528
*/
2629
class ParametrizedQuery {
@@ -38,12 +41,13 @@ String getQuery() {
3841
return query;
3942
}
4043

41-
SqlParameterSource getParameterSource() {
42-
return parameterSource;
43-
}
44-
4544
@Override
4645
public String toString() {
4746
return this.query;
4847
}
48+
49+
public SqlParameterSource getParameterSource(Escaper escaper) {
50+
51+
return new EscapingParameterSource(parameterSource, escaper);
52+
}
4953
}

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public Object execute(Object[] values) {
126126
ParametrizedQuery query = createQuery(accessor, processor.getReturnedType());
127127
JdbcQueryExecution<?> execution = getQueryExecution(processor, accessor);
128128

129-
return execution.execute(query.getQuery(), query.getParameterSource());
129+
return execution.execute(query.getQuery(), query.getParameterSource(dialect.getLikeEscaper()));
130130
}
131131

132132
private JdbcQueryExecution<?> getQueryExecution(ResultProcessor processor,
@@ -164,7 +164,7 @@ private JdbcQueryExecution<?> getQueryExecution(ResultProcessor processor,
164164

165165
ParametrizedQuery countQuery = queryCreator.createQuery(Sort.unsorted());
166166
Object count = singleObjectQuery((rs, i) -> rs.getLong(1)).execute(countQuery.getQuery(),
167-
countQuery.getParameterSource());
167+
countQuery.getParameterSource(dialect.getLikeEscaper()));
168168

169169
return converter.getConversionService().convert(count, Long.class);
170170
});

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public class QueryMapperUnitTests {
5050
JdbcMappingContext context = new JdbcMappingContext();
5151
JdbcConverter converter = new BasicJdbcConverter(context, mock(RelationResolver.class));
5252

53-
QueryMapper mapper = new QueryMapper(PostgresDialect.INSTANCE, converter);
53+
QueryMapper mapper = new QueryMapper(converter);
5454
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
5555

5656
@Test // DATAJDBC-318

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

+17-16
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.springframework.data.jdbc.core.mapping.AggregateReference;
3737
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
3838
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
39+
import org.springframework.data.relational.core.dialect.Escaper;
3940
import org.springframework.data.relational.core.dialect.H2Dialect;
4041
import org.springframework.data.relational.core.mapping.Embedded;
4142
import org.springframework.data.relational.core.mapping.MappedCollection;
@@ -93,7 +94,7 @@ public void createQueryByAggregateReference() throws Exception {
9394
softly.assertThat(query.getQuery())
9495
.isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"HOBBY_REFERENCE\" = :hobby_reference");
9596

96-
softly.assertThat(query.getParameterSource().getValue("hobby_reference")).isEqualTo("twentythree");
97+
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("hobby_reference")).isEqualTo("twentythree");
9798
});
9899
}
99100

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

113114
softly.assertThat(query.getQuery().toUpperCase()).endsWith("FOR UPDATE");
114115

115-
softly.assertThat(query.getParameterSource().getValue("first_name")).isEqualTo(firstname);
116-
softly.assertThat(query.getParameterSource().getValue("last_name")).isEqualTo(lastname);
116+
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("first_name")).isEqualTo(firstname);
117+
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("last_name")).isEqualTo(lastname);
117118
});
118119
}
119120

@@ -133,8 +134,8 @@ void createQueryWithPessimisticReadLock() throws Exception {
133134
// this is also for update since h2 dialect does not distinguish between lockmodes
134135
softly.assertThat(query.getQuery().toUpperCase()).endsWith("FOR UPDATE");
135136

136-
softly.assertThat(query.getParameterSource().getValue("first_name")).isEqualTo(firstname);
137-
softly.assertThat(query.getParameterSource().getValue("age")).isEqualTo(age);
137+
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("first_name")).isEqualTo(firstname);
138+
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("age")).isEqualTo(age);
138139
});
139140
}
140141

@@ -165,7 +166,7 @@ public void createQueryForQueryByAggregateReference() throws Exception {
165166
softly.assertThat(query.getQuery())
166167
.isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"HOBBY_REFERENCE\" = :hobby_reference");
167168

168-
softly.assertThat(query.getParameterSource().getValue("hobby_reference")).isEqualTo("twentythree");
169+
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("hobby_reference")).isEqualTo("twentythree");
169170
});
170171
}
171172

@@ -182,7 +183,7 @@ public void createQueryForQueryByAggregateReferenceId() throws Exception {
182183
softly.assertThat(query.getQuery())
183184
.isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"HOBBY_REFERENCE\" = :hobby_reference");
184185

185-
softly.assertThat(query.getParameterSource().getValue("hobby_reference")).isEqualTo("twentythree");
186+
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("hobby_reference")).isEqualTo("twentythree");
186187
});
187188
}
188189

@@ -270,8 +271,8 @@ public void createsQueryToFindAllEntitiesByDateAttributeBetween() throws Excepti
270271
softly.assertThat(query.getQuery())
271272
.isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"DATE_OF_BIRTH\" BETWEEN :date_of_birth AND :date_of_birth1");
272273

273-
softly.assertThat(query.getParameterSource().getValue("date_of_birth")).isEqualTo(from);
274-
softly.assertThat(query.getParameterSource().getValue("date_of_birth1")).isEqualTo(to);
274+
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("date_of_birth")).isEqualTo(from);
275+
softly.assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("date_of_birth1")).isEqualTo(to);
275276
});
276277
}
277278

@@ -405,7 +406,7 @@ public void appendsLikeOperatorParameterWithPercentSymbolForStartingWithQuery()
405406
ParametrizedQuery query = jdbcQuery.createQuery(accessor, returnedType);
406407

407408
assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
408-
assertThat(query.getParameterSource().getValue("first_name")).isEqualTo("Jo%");
409+
assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("first_name")).isEqualTo("Jo%");
409410
}
410411

411412
@Test // DATAJDBC-318
@@ -428,7 +429,7 @@ public void prependsLikeOperatorParameterWithPercentSymbolForEndingWithQuery() t
428429
ParametrizedQuery query = jdbcQuery.createQuery(accessor, returnedType);
429430

430431
assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
431-
assertThat(query.getParameterSource().getValue("first_name")).isEqualTo("%hn");
432+
assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("first_name")).isEqualTo("%hn");
432433
}
433434

434435
@Test // DATAJDBC-318
@@ -451,7 +452,7 @@ public void wrapsLikeOperatorParameterWithPercentSymbolsForContainingQuery() thr
451452
ParametrizedQuery query = jdbcQuery.createQuery(accessor, returnedType);
452453

453454
assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
454-
assertThat(query.getParameterSource().getValue("first_name")).isEqualTo("%oh%");
455+
assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("first_name")).isEqualTo("%oh%");
455456
}
456457

457458
@Test // DATAJDBC-318
@@ -474,7 +475,7 @@ public void wrapsLikeOperatorParameterWithPercentSymbolsForNotContainingQuery()
474475
ParametrizedQuery query = jdbcQuery.createQuery(accessor, returnedType);
475476

476477
assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" NOT LIKE :first_name");
477-
assertThat(query.getParameterSource().getValue("first_name")).isEqualTo("%oh%");
478+
assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("first_name")).isEqualTo("%oh%");
478479
}
479480

480481
@Test // DATAJDBC-318
@@ -638,8 +639,8 @@ public void createsQueryByEmbeddedObject() throws Exception {
638639
.contains(TABLE + ".\"USER_STREET\" = :user_street", //
639640
" AND ", //
640641
TABLE + ".\"USER_CITY\" = :user_city");
641-
assertThat(query.getParameterSource().getValue("user_street")).isEqualTo("Hello");
642-
assertThat(query.getParameterSource().getValue("user_city")).isEqualTo("World");
642+
assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("user_street")).isEqualTo("Hello");
643+
assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("user_city")).isEqualTo("World");
643644
}
644645

645646
@Test // DATAJDBC-318
@@ -653,7 +654,7 @@ public void createsQueryByEmbeddedProperty() throws Exception {
653654
String expectedSql = BASE_SELECT + " WHERE " + TABLE + ".\"USER_STREET\" = :user_street";
654655

655656
assertThat(query.getQuery()).isEqualTo(expectedSql);
656-
assertThat(query.getParameterSource().getValue("user_street")).isEqualTo("Hello");
657+
assertThat(query.getParameterSource(Escaper.DEFAULT).getValue("user_street")).isEqualTo("Hello");
657658
}
658659

659660
@Test // DATAJDBC-534

0 commit comments

Comments
 (0)