Skip to content

Commit d0127fe

Browse files
committed
Support for R2DBC.
Doesn't work yet, because Dialect is not available as a bean.
1 parent 3755822 commit d0127fe

File tree

4 files changed

+65
-17
lines changed

4 files changed

+65
-17
lines changed

spring-data-r2dbc/src/main/java/org/springframework/data/r2dbc/repository/support/R2dbcRepositoryFactory.java

+51-13
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,14 @@
2828
import org.springframework.data.r2dbc.repository.query.PartTreeR2dbcQuery;
2929
import org.springframework.data.r2dbc.repository.query.R2dbcQueryMethod;
3030
import org.springframework.data.r2dbc.repository.query.StringBasedR2dbcQuery;
31+
import org.springframework.data.relational.core.dialect.AnsiDialect;
32+
import org.springframework.data.relational.core.dialect.Dialect;
3133
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
3234
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
35+
import org.springframework.data.relational.core.sql.SqlIdentifier;
36+
import org.springframework.data.relational.repository.query.QueryPreprocessor;
3337
import org.springframework.data.relational.repository.query.RelationalEntityInformation;
38+
import org.springframework.data.relational.repository.query.TableNameQueryPreprocessor;
3439
import org.springframework.data.relational.repository.support.MappingRelationalEntityInformation;
3540
import org.springframework.data.repository.core.NamedQueries;
3641
import org.springframework.data.repository.core.RepositoryInformation;
@@ -61,6 +66,7 @@ public class R2dbcRepositoryFactory extends ReactiveRepositoryFactorySupport {
6166
private final MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> mappingContext;
6267
private final R2dbcConverter converter;
6368
private final R2dbcEntityOperations operations;
69+
private final Dialect dialect;
6470

6571
/**
6672
* Creates a new {@link R2dbcRepositoryFactory} given {@link DatabaseClient} and {@link MappingContext}.
@@ -69,6 +75,17 @@ public class R2dbcRepositoryFactory extends ReactiveRepositoryFactorySupport {
6975
* @param dataAccessStrategy must not be {@literal null}.
7076
*/
7177
public R2dbcRepositoryFactory(DatabaseClient databaseClient, ReactiveDataAccessStrategy dataAccessStrategy) {
78+
this(databaseClient, dataAccessStrategy, AnsiDialect.INSTANCE);
79+
}
80+
81+
/**
82+
* Creates a new {@link R2dbcRepositoryFactory} given {@link DatabaseClient} and {@link MappingContext}.
83+
*
84+
* @param databaseClient must not be {@literal null}.
85+
* @param dataAccessStrategy must not be {@literal null}.
86+
*/
87+
public R2dbcRepositoryFactory(DatabaseClient databaseClient, ReactiveDataAccessStrategy dataAccessStrategy,
88+
Dialect dialect) {
7289

7390
Assert.notNull(databaseClient, "DatabaseClient must not be null");
7491
Assert.notNull(dataAccessStrategy, "ReactiveDataAccessStrategy must not be null");
@@ -78,6 +95,7 @@ public R2dbcRepositoryFactory(DatabaseClient databaseClient, ReactiveDataAccessS
7895
this.converter = dataAccessStrategy.getConverter();
7996
this.mappingContext = this.converter.getMappingContext();
8097
this.operations = new R2dbcEntityTemplate(this.databaseClient, this.dataAccessStrategy);
98+
this.dialect = dialect;
8199
setEvaluationContextProvider(ReactiveQueryMethodEvaluationContextProvider.DEFAULT);
82100
}
83101

@@ -88,6 +106,16 @@ public R2dbcRepositoryFactory(DatabaseClient databaseClient, ReactiveDataAccessS
88106
* @since 1.1.3
89107
*/
90108
public R2dbcRepositoryFactory(R2dbcEntityOperations operations) {
109+
this(operations, AnsiDialect.INSTANCE);
110+
}
111+
112+
/**
113+
* Creates a new {@link R2dbcRepositoryFactory} given {@link R2dbcEntityOperations}.
114+
*
115+
* @param operations must not be {@literal null}.
116+
* @since 1.1.3
117+
*/
118+
public R2dbcRepositoryFactory(R2dbcEntityOperations operations, Dialect dialect) {
91119

92120
Assert.notNull(operations, "R2dbcEntityOperations must not be null");
93121

@@ -96,6 +124,7 @@ public R2dbcRepositoryFactory(R2dbcEntityOperations operations) {
96124
this.converter = dataAccessStrategy.getConverter();
97125
this.mappingContext = this.converter.getMappingContext();
98126
this.operations = operations;
127+
this.dialect = dialect;
99128
setEvaluationContextProvider(ReactiveQueryMethodEvaluationContextProvider.DEFAULT);
100129
}
101130

@@ -110,16 +139,15 @@ protected Object getTargetRepository(RepositoryInformation information) {
110139
RelationalEntityInformation<?, ?> entityInformation = getEntityInformation(information.getDomainType(),
111140
information);
112141

113-
return getTargetRepositoryViaReflection(information, entityInformation,
114-
operations, this.converter);
142+
return getTargetRepositoryViaReflection(information, entityInformation, operations, this.converter);
115143
}
116144

117145
@Override
118146
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(@Nullable Key key,
119147
QueryMethodEvaluationContextProvider evaluationContextProvider) {
120148
return Optional.of(new R2dbcQueryLookupStrategy(this.operations,
121149
(ReactiveQueryMethodEvaluationContextProvider) evaluationContextProvider, this.converter,
122-
this.dataAccessStrategy));
150+
this.dataAccessStrategy, this.dialect));
123151
}
124152

125153
public <T, ID> RelationalEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
@@ -146,35 +174,45 @@ private static class R2dbcQueryLookupStrategy implements QueryLookupStrategy {
146174
private final ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider;
147175
private final R2dbcConverter converter;
148176
private final ReactiveDataAccessStrategy dataAccessStrategy;
177+
private final Dialect dialect;
149178
private final ExpressionParser parser = new CachingExpressionParser(EXPRESSION_PARSER);
150179

151180
R2dbcQueryLookupStrategy(R2dbcEntityOperations entityOperations,
152181
ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider, R2dbcConverter converter,
153-
ReactiveDataAccessStrategy dataAccessStrategy) {
182+
ReactiveDataAccessStrategy dataAccessStrategy, Dialect dialect) {
183+
154184
this.entityOperations = entityOperations;
155185
this.evaluationContextProvider = evaluationContextProvider;
156186
this.converter = converter;
157187
this.dataAccessStrategy = dataAccessStrategy;
158-
188+
this.dialect = dialect;
159189
}
160190

161191
@Override
162192
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
163193
NamedQueries namedQueries) {
164194

195+
MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> mappingContext = this.converter.getMappingContext();
165196
R2dbcQueryMethod queryMethod = new R2dbcQueryMethod(method, metadata, factory,
166-
this.converter.getMappingContext());
197+
mappingContext);
167198
String namedQueryName = queryMethod.getNamedQueryName();
168199

169-
if (namedQueries.hasQuery(namedQueryName)) {
170-
String namedQuery = namedQueries.getQuery(namedQueryName);
171-
return new StringBasedR2dbcQuery(namedQuery, queryMethod, this.entityOperations, this.converter,
200+
Class<?> domainType = metadata.getDomainType();
201+
RelationalPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(domainType);
202+
SqlIdentifier tableName = entity.getTableName();
203+
SqlIdentifier qualifiedTableName = entity.getQualifiedTableName();
204+
205+
if (namedQueries.hasQuery(namedQueryName) || queryMethod.hasAnnotatedQuery()) {
206+
207+
QueryPreprocessor queryPreprocessor = new TableNameQueryPreprocessor(tableName, qualifiedTableName, dialect);
208+
209+
String query = namedQueries.hasQuery(namedQueryName) ? namedQueries.getQuery(namedQueryName) : queryMethod.getRequiredAnnotatedQuery();
210+
query = queryPreprocessor.transform(query);
211+
212+
return new StringBasedR2dbcQuery(query, queryMethod, this.entityOperations, this.converter,
172213
this.dataAccessStrategy,
173214
parser, this.evaluationContextProvider);
174-
} else if (queryMethod.hasAnnotatedQuery()) {
175-
return new StringBasedR2dbcQuery(queryMethod, this.entityOperations, this.converter, this.dataAccessStrategy,
176-
this.parser,
177-
this.evaluationContextProvider);
215+
178216
} else {
179217
return new PartTreeR2dbcQuery(queryMethod, this.entityOperations, this.converter, this.dataAccessStrategy);
180218
}

spring-data-r2dbc/src/main/java/org/springframework/data/r2dbc/repository/support/R2dbcRepositoryFactoryBean.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.springframework.data.r2dbc.core.R2dbcEntityOperations;
2727
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
2828
import org.springframework.data.r2dbc.core.ReactiveDataAccessStrategy;
29+
import org.springframework.data.relational.core.dialect.Dialect;
2930
import org.springframework.data.repository.Repository;
3031
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
3132
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
@@ -51,6 +52,7 @@ public class R2dbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID exten
5152
private @Nullable ReactiveDataAccessStrategy dataAccessStrategy;
5253
private @Nullable R2dbcEntityOperations operations;
5354
private @Nullable ApplicationContext applicationContext;
55+
private @Nullable Dialect dialect;
5456

5557
private boolean mappingContextConfigured = false;
5658

@@ -76,6 +78,10 @@ public void setDataAccessStrategy(ReactiveDataAccessStrategy dataAccessStrategy)
7678
this.dataAccessStrategy = dataAccessStrategy;
7779
}
7880

81+
public void setDialect(Dialect dialect) {
82+
this.dialect = dialect;
83+
}
84+
7985
/**
8086
* @param operations
8187
* @since 1.1.3
@@ -113,7 +119,7 @@ protected Optional<QueryMethodEvaluationContextProvider> createDefaultQueryMetho
113119
*/
114120
protected RepositoryFactorySupport getFactoryInstance(DatabaseClient client,
115121
ReactiveDataAccessStrategy dataAccessStrategy) {
116-
return new R2dbcRepositoryFactory(client, dataAccessStrategy);
122+
return new R2dbcRepositoryFactory(client, dataAccessStrategy, dialect);
117123
}
118124

119125
/**
@@ -124,7 +130,7 @@ protected RepositoryFactorySupport getFactoryInstance(DatabaseClient client,
124130
* @since 1.1.3
125131
*/
126132
protected RepositoryFactorySupport getFactoryInstance(R2dbcEntityOperations operations) {
127-
return new R2dbcRepositoryFactory(operations);
133+
return new R2dbcRepositoryFactory(operations, dialect);
128134
}
129135

130136
@Override

spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/TableNameQueryPreprocessor.java

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.springframework.expression.ParserContext;
2323
import org.springframework.expression.spel.standard.SpelExpressionParser;
2424
import org.springframework.expression.spel.support.StandardEvaluationContext;
25+
import org.springframework.util.Assert;
2526

2627
import java.util.regex.Pattern;
2728

@@ -39,6 +40,10 @@ public class TableNameQueryPreprocessor implements QueryPreprocessor {
3940

4041
public TableNameQueryPreprocessor(SqlIdentifier tableName, SqlIdentifier qualifiedTableName, Dialect dialect) {
4142

43+
Assert.notNull(tableName, "TableName must not be null");
44+
Assert.notNull(qualifiedTableName, "QualifiedTableName must not be null");
45+
Assert.notNull(dialect, "Dialect must not be null");
46+
4247
this.tableName = tableName;
4348
this.qualifiedTableName = qualifiedTableName;
4449
this.dialect = dialect;
+1-2
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,12 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.springframework.data.jdbc.repository.query;
17+
package org.springframework.data.relational.repository.query;
1818

1919
import org.assertj.core.api.SoftAssertions;
2020
import org.junit.jupiter.api.Test;
2121
import org.springframework.data.relational.core.dialect.AnsiDialect;
2222
import org.springframework.data.relational.core.sql.SqlIdentifier;
23-
import org.springframework.data.relational.repository.query.TableNameQueryPreprocessor;
2423

2524
class TableNameQueryPreprocessorUnitTests {
2625

0 commit comments

Comments
 (0)