Skip to content

Commit bedc18b

Browse files
mp911deschauder
authored andcommitted
#105 - Move named parameter resolution to ReactiveDataAccessStrategy.
Named parameter resolution is now provided as part of ReactiveDataAccessStrategy. This allows us to hide implementation internals (bind markers). DatabaseClient allows configuration whether to use named parameter expansion. Detailed configuration of named parameter support is now moved to DefaultReactiveDataAccessStrategy. Original pull request: #105.
1 parent 7372efe commit bedc18b

14 files changed

+178
-229
lines changed

src/main/java/org/springframework/data/r2dbc/core/BindParameterSource.java

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

18+
import org.springframework.data.util.Streamable;
1819
import org.springframework.lang.Nullable;
1920

2021
/**
@@ -58,4 +59,11 @@ public interface BindParameterSource {
5859
default Class<?> getType(String paramName) {
5960
return Object.class;
6061
}
62+
63+
/**
64+
* Returns parameter names of the underlying parameter source.
65+
*
66+
* @return parameter names of the underlying parameter source.
67+
*/
68+
Streamable<String> getParameterNames();
6169
}

src/main/java/org/springframework/data/r2dbc/core/BindableOperation.java

Lines changed: 0 additions & 73 deletions
This file was deleted.

src/main/java/org/springframework/data/r2dbc/core/DatabaseClient.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,14 +157,14 @@ interface Builder {
157157
Builder dataAccessStrategy(ReactiveDataAccessStrategy accessStrategy);
158158

159159
/**
160-
* Configures {@link NamedParameterExpander}.
160+
* Configures whether to use named parameter expansion. Defaults to {@literal true}.
161161
*
162-
* @param expander must not be {@literal null}.
162+
* @param enabled {@literal true} to use named parameter expansion. {@literal false} to disable named parameter
163+
* expansion.
163164
* @return {@code this} {@link Builder}.
164-
* @see NamedParameterExpander#enabled()
165-
* @see NamedParameterExpander#disabled()
165+
* @see NamedParameterExpander
166166
*/
167-
Builder namedParameters(NamedParameterExpander expander);
167+
Builder namedParameters(boolean enabled);
168168

169169
/**
170170
* Configures a {@link Consumer} to configure this builder.

src/main/java/org/springframework/data/r2dbc/core/DefaultDatabaseClient.java

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,12 @@ class DefaultDatabaseClient implements DatabaseClient, ConnectionAccessor {
7979

8080
private final ReactiveDataAccessStrategy dataAccessStrategy;
8181

82-
private final NamedParameterExpander namedParameters;
82+
private final boolean namedParameters;
8383

8484
private final DefaultDatabaseClientBuilder builder;
8585

8686
DefaultDatabaseClient(ConnectionFactory connector, R2dbcExceptionTranslator exceptionTranslator,
87-
ReactiveDataAccessStrategy dataAccessStrategy, NamedParameterExpander namedParameters,
88-
DefaultDatabaseClientBuilder builder) {
87+
ReactiveDataAccessStrategy dataAccessStrategy, boolean namedParameters, DefaultDatabaseClientBuilder builder) {
8988

9089
this.connector = connector;
9190
this.exceptionTranslator = exceptionTranslator;
@@ -284,6 +283,18 @@ protected DefaultGenericExecuteSpec createGenericExecuteSpec(Supplier<String> sq
284283
return new DefaultGenericExecuteSpec(sqlSupplier);
285284
}
286285

286+
private static void bindByName(Statement statement, Map<String, SettableValue> byName) {
287+
288+
byName.forEach((name, o) -> {
289+
290+
if (o.getValue() != null) {
291+
statement.bind(name, o.getValue());
292+
} else {
293+
statement.bindNull(name, o.getType());
294+
}
295+
});
296+
}
297+
287298
private static void bindByIndex(Statement statement, Map<Integer, SettableValue> byIndex) {
288299

289300
byIndex.forEach((i, o) -> {
@@ -353,27 +364,28 @@ <T> FetchSpec<T> exchange(Supplier<String> sqlSupplier, BiFunction<Row, RowMetad
353364
return statement;
354365
}
355366

356-
BindableOperation operation = namedParameters.expand(sql, dataAccessStrategy.getBindMarkersFactory(),
357-
new MapBindParameterSource(this.byName));
367+
if (namedParameters) {
358368

359-
String expanded = getRequiredSql(operation);
360-
if (logger.isTraceEnabled()) {
361-
logger.trace("Expanded SQL [" + expanded + "]");
362-
}
369+
PreparedOperation<?> operation = dataAccessStrategy.processNamedParameters(sql, this.byName);
363370

364-
Statement statement = it.createStatement(expanded);
365-
BindTarget bindTarget = new StatementWrapper(statement);
371+
String expanded = getRequiredSql(operation);
372+
if (logger.isTraceEnabled()) {
373+
logger.trace("Expanded SQL [" + expanded + "]");
374+
}
366375

367-
this.byName.forEach((name, o) -> {
376+
Statement statement = it.createStatement(expanded);
377+
BindTarget bindTarget = new StatementWrapper(statement);
368378

369-
if (o.getValue() != null) {
370-
operation.bind(bindTarget, name, o.getValue());
371-
} else {
372-
operation.bindNull(bindTarget, name, o.getType());
373-
}
374-
});
379+
operation.bindTo(bindTarget);
380+
bindByIndex(statement, this.byIndex);
381+
382+
return statement;
383+
}
384+
385+
Statement statement = it.createStatement(sql);
375386

376387
bindByIndex(statement, this.byIndex);
388+
bindByName(statement, this.byName);
377389

378390
return statement;
379391
};

src/main/java/org/springframework/data/r2dbc/core/DefaultDatabaseClientBuilder.java

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,12 @@
3636
class DefaultDatabaseClientBuilder implements DatabaseClient.Builder {
3737

3838
private @Nullable ConnectionFactory connectionFactory;
39+
3940
private @Nullable R2dbcExceptionTranslator exceptionTranslator;
41+
4042
private ReactiveDataAccessStrategy accessStrategy;
41-
private NamedParameterExpander namedParameters;
43+
44+
private boolean namedParameters = true;
4245

4346
DefaultDatabaseClientBuilder() {}
4447

@@ -93,14 +96,12 @@ public Builder dataAccessStrategy(ReactiveDataAccessStrategy accessStrategy) {
9396

9497
/*
9598
* (non-Javadoc)
96-
* @see org.springframework.data.r2dbc.function.DatabaseClient.Builder#namedParameters(org.springframework.data.r2dbc.function.NamedParameterExpander)
99+
* @see org.springframework.data.r2dbc.function.DatabaseClient.Builder#namedParameters(boolean)
97100
*/
98101
@Override
99-
public Builder namedParameters(NamedParameterExpander expander) {
100-
101-
Assert.notNull(expander, "NamedParameterExpander must not be null!");
102+
public Builder namedParameters(boolean enabled) {
102103

103-
this.namedParameters = expander;
104+
this.namedParameters = enabled;
104105
return this;
105106
}
106107

@@ -125,19 +126,12 @@ public DatabaseClient build() {
125126
accessStrategy = new DefaultReactiveDataAccessStrategy(dialect);
126127
}
127128

128-
NamedParameterExpander namedParameters = this.namedParameters;
129-
130-
if (namedParameters == null) {
131-
namedParameters = NamedParameterExpander.enabled();
132-
}
133-
134129
return doBuild(this.connectionFactory, exceptionTranslator, accessStrategy, namedParameters,
135130
new DefaultDatabaseClientBuilder(this));
136131
}
137132

138133
protected DatabaseClient doBuild(ConnectionFactory connector, R2dbcExceptionTranslator exceptionTranslator,
139-
ReactiveDataAccessStrategy accessStrategy, NamedParameterExpander namedParameters,
140-
DefaultDatabaseClientBuilder builder) {
134+
ReactiveDataAccessStrategy accessStrategy, boolean namedParameters, DefaultDatabaseClientBuilder builder) {
141135
return new DefaultDatabaseClient(connector, exceptionTranslator, accessStrategy, namedParameters, builder);
142136
}
143137

src/main/java/org/springframework/data/r2dbc/core/DefaultReactiveDataAccessStrategy.java

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.Collection;
2323
import java.util.Collections;
2424
import java.util.List;
25+
import java.util.Map;
2526
import java.util.function.BiFunction;
2627

2728
import org.springframework.dao.InvalidDataAccessResourceUsageException;
@@ -31,7 +32,6 @@
3132
import org.springframework.data.r2dbc.convert.MappingR2dbcConverter;
3233
import org.springframework.data.r2dbc.convert.R2dbcConverter;
3334
import org.springframework.data.r2dbc.convert.R2dbcCustomConversions;
34-
import org.springframework.data.r2dbc.dialect.BindMarkersFactory;
3535
import org.springframework.data.r2dbc.dialect.R2dbcDialect;
3636
import org.springframework.data.r2dbc.mapping.OutboundRow;
3737
import org.springframework.data.r2dbc.mapping.SettableValue;
@@ -57,6 +57,7 @@ public class DefaultReactiveDataAccessStrategy implements ReactiveDataAccessStra
5757
private final UpdateMapper updateMapper;
5858
private final MappingContext<RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> mappingContext;
5959
private final StatementMapper statementMapper;
60+
private final NamedParameterExpander expander;
6061

6162
/**
6263
* Creates a new {@link DefaultReactiveDataAccessStrategy} given {@link R2dbcDialect} and optional
@@ -81,7 +82,7 @@ public DefaultReactiveDataAccessStrategy(R2dbcDialect dialect, Collection<?> con
8182
this(dialect, createConverter(dialect, converters));
8283
}
8384

84-
private static R2dbcConverter createConverter(R2dbcDialect dialect, Collection<?> converters) {
85+
public static R2dbcConverter createConverter(R2dbcDialect dialect, Collection<?> converters) {
8586

8687
Assert.notNull(dialect, "Dialect must not be null");
8788
Assert.notNull(converters, "Converters must not be null");
@@ -101,11 +102,24 @@ private static R2dbcConverter createConverter(R2dbcDialect dialect, Collection<?
101102
* @param dialect the {@link R2dbcDialect} to use.
102103
* @param converter must not be {@literal null}.
103104
*/
104-
@SuppressWarnings("unchecked")
105105
public DefaultReactiveDataAccessStrategy(R2dbcDialect dialect, R2dbcConverter converter) {
106+
this(dialect, converter, new NamedParameterExpander());
107+
}
108+
109+
/**
110+
* Creates a new {@link DefaultReactiveDataAccessStrategy} given {@link R2dbcDialect} and {@link R2dbcConverter}.
111+
*
112+
* @param dialect the {@link R2dbcDialect} to use.
113+
* @param converter must not be {@literal null}.
114+
* @param expander must not be {@literal null}.
115+
*/
116+
@SuppressWarnings("unchecked")
117+
public DefaultReactiveDataAccessStrategy(R2dbcDialect dialect, R2dbcConverter converter,
118+
NamedParameterExpander expander) {
106119

107120
Assert.notNull(dialect, "Dialect must not be null");
108121
Assert.notNull(converter, "RelationalConverter must not be null");
122+
Assert.notNull(expander, "NamedParameterExpander must not be null");
109123

110124
this.converter = converter;
111125
this.updateMapper = new UpdateMapper(converter);
@@ -116,6 +130,7 @@ public DefaultReactiveDataAccessStrategy(R2dbcDialect dialect, R2dbcConverter co
116130
RenderContextFactory factory = new RenderContextFactory(dialect);
117131
this.statementMapper = new DefaultStatementMapper(dialect, factory.createRenderContext(), this.updateMapper,
118132
this.mappingContext);
133+
this.expander = expander;
119134
}
120135

121136
/*
@@ -215,29 +230,29 @@ public <T> BiFunction<Row, RowMetadata, T> getRowMapper(Class<T> typeToRead) {
215230

216231
/*
217232
* (non-Javadoc)
218-
* @see org.springframework.data.r2dbc.function.ReactiveDataAccessStrategy#getTableName(java.lang.Class)
233+
* @see org.springframework.data.r2dbc.core.ReactiveDataAccessStrategy#processNamedParameters(java.lang.String, java.util.Map)
219234
*/
220235
@Override
221-
public String getTableName(Class<?> type) {
222-
return getRequiredPersistentEntity(type).getTableName();
236+
public PreparedOperation<?> processNamedParameters(String query, Map<String, SettableValue> bindings) {
237+
return this.expander.expand(query, this.dialect.getBindMarkersFactory(), new MapBindParameterSource(bindings));
223238
}
224239

225240
/*
226241
* (non-Javadoc)
227-
* @see org.springframework.data.r2dbc.function.ReactiveDataAccessStrategy#getStatementMapper()
242+
* @see org.springframework.data.r2dbc.function.ReactiveDataAccessStrategy#getTableName(java.lang.Class)
228243
*/
229244
@Override
230-
public StatementMapper getStatementMapper() {
231-
return this.statementMapper;
245+
public String getTableName(Class<?> type) {
246+
return getRequiredPersistentEntity(type).getTableName();
232247
}
233248

234249
/*
235250
* (non-Javadoc)
236-
* @see org.springframework.data.r2dbc.function.ReactiveDataAccessStrategy#getBindMarkersFactory()
251+
* @see org.springframework.data.r2dbc.function.ReactiveDataAccessStrategy#getStatementMapper()
237252
*/
238253
@Override
239-
public BindMarkersFactory getBindMarkersFactory() {
240-
return this.dialect.getBindMarkersFactory();
254+
public StatementMapper getStatementMapper() {
255+
return this.statementMapper;
241256
}
242257

243258
/*

src/main/java/org/springframework/data/r2dbc/core/DefaultTransactionalDatabaseClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
class DefaultTransactionalDatabaseClient extends DefaultDatabaseClient implements TransactionalDatabaseClient {
4040

4141
DefaultTransactionalDatabaseClient(ConnectionFactory connector, R2dbcExceptionTranslator exceptionTranslator,
42-
ReactiveDataAccessStrategy dataAccessStrategy, NamedParameterExpander namedParameters,
42+
ReactiveDataAccessStrategy dataAccessStrategy, boolean namedParameters,
4343
DefaultDatabaseClientBuilder builder) {
4444
super(connector, exceptionTranslator, dataAccessStrategy, namedParameters, builder);
4545
}

src/main/java/org/springframework/data/r2dbc/core/DefaultTransactionalDatabaseClientBuilder.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ public TransactionalDatabaseClient.Builder dataAccessStrategy(ReactiveDataAccess
7070
}
7171

7272
/* (non-Javadoc)
73-
* @see org.springframework.data.r2dbc.function.DefaultDatabaseClientBuilder#dataAccessStrategy(org.springframework.data.r2dbc.function.NamedParameterSupport)
73+
* @see org.springframework.data.r2dbc.function.DefaultDatabaseClientBuilder#dataAccessStrategy(boolean)
7474
*/
7575
@Override
76-
public TransactionalDatabaseClient.Builder namedParameters(NamedParameterExpander expander) {
77-
super.namedParameters(expander);
76+
public TransactionalDatabaseClient.Builder namedParameters(boolean enabled) {
77+
super.namedParameters(enabled);
7878
return this;
7979
}
8080

@@ -97,7 +97,7 @@ public TransactionalDatabaseClient build() {
9797

9898
@Override
9999
protected DatabaseClient doBuild(ConnectionFactory connector, R2dbcExceptionTranslator exceptionTranslator,
100-
ReactiveDataAccessStrategy accessStrategy, NamedParameterExpander namedParameters,
100+
ReactiveDataAccessStrategy accessStrategy, boolean namedParameters,
101101
DefaultDatabaseClientBuilder builder) {
102102
return new DefaultTransactionalDatabaseClient(connector, exceptionTranslator, accessStrategy, namedParameters,
103103
builder);

0 commit comments

Comments
 (0)