Add support for Value Expressions for Repository Query methods.
Closes #1904 Original pull request: #1906
This commit is contained in:
committed by
Mark Paluch
parent
fd4aedc760
commit
d526cd3a22
@@ -15,9 +15,11 @@
|
||||
*/
|
||||
package org.springframework.data.r2dbc.repository.query;
|
||||
|
||||
import org.springframework.data.expression.ValueEvaluationContext;
|
||||
import org.springframework.data.expression.ValueExpression;
|
||||
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
|
||||
import org.springframework.data.repository.query.ValueExpressionDelegate;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.r2dbc.core.Parameter;
|
||||
|
||||
@@ -30,12 +32,12 @@ import org.springframework.r2dbc.core.Parameter;
|
||||
*/
|
||||
class DefaultR2dbcSpELExpressionEvaluator implements R2dbcSpELExpressionEvaluator {
|
||||
|
||||
private final ExpressionParser parser;
|
||||
private final ValueExpressionDelegate delegate;
|
||||
|
||||
private final EvaluationContext context;
|
||||
private final ValueEvaluationContext context;
|
||||
|
||||
DefaultR2dbcSpELExpressionEvaluator(ExpressionParser parser, EvaluationContext context) {
|
||||
this.parser = parser;
|
||||
DefaultR2dbcSpELExpressionEvaluator(ValueExpressionDelegate delegate, ValueEvaluationContext context) {
|
||||
this.delegate = delegate;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@@ -51,12 +53,12 @@ class DefaultR2dbcSpELExpressionEvaluator implements R2dbcSpELExpressionEvaluato
|
||||
@Override
|
||||
public Parameter evaluate(String expression) {
|
||||
|
||||
Expression expr = parser.parseExpression(expression);
|
||||
ValueExpression expr = delegate.parse(expression);
|
||||
|
||||
Object value = expr.getValue(context, Object.class);
|
||||
Class<?> valueType = expr.getValueType(context);
|
||||
Object value = expr.evaluate(context);
|
||||
Class<?> valueType = value != null ? value.getClass() : Object.class;
|
||||
|
||||
return org.springframework.r2dbc.core.Parameter.fromOrEmpty(value, valueType != null ? valueType : Object.class);
|
||||
return org.springframework.r2dbc.core.Parameter.fromOrEmpty(value, valueType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,7 +18,8 @@ package org.springframework.data.r2dbc.repository.query;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.repository.query.SpelQueryContext;
|
||||
import org.springframework.data.expression.ValueExpressionParser;
|
||||
import org.springframework.data.repository.query.ValueExpressionQueryRewriter;
|
||||
|
||||
/**
|
||||
* Query using Spring Expression Language to indicate parameter bindings. Queries using SpEL use {@code :#{…}} to
|
||||
@@ -48,18 +49,17 @@ class ExpressionQuery {
|
||||
* @param query the query string to parse.
|
||||
* @return the parsed {@link ExpressionQuery}.
|
||||
*/
|
||||
public static ExpressionQuery create(String query) {
|
||||
public static ExpressionQuery create(ValueExpressionParser parser, String query) {
|
||||
|
||||
List<ParameterBinding> parameterBindings = new ArrayList<>();
|
||||
|
||||
SpelQueryContext queryContext = SpelQueryContext.of((counter, expression) -> {
|
||||
|
||||
ValueExpressionQueryRewriter rewriter = ValueExpressionQueryRewriter.of(parser, (counter, expression) -> {
|
||||
String parameterName = String.format(SYNTHETIC_PARAMETER_TEMPLATE, counter);
|
||||
parameterBindings.add(new ParameterBinding(parameterName, expression));
|
||||
return parameterName;
|
||||
}, String::concat);
|
||||
|
||||
SpelQueryContext.SpelExtractor parsed = queryContext.parse(query);
|
||||
ValueExpressionQueryRewriter.ParsedQuery parsed = rewriter.parse(query);
|
||||
|
||||
return new ExpressionQuery(parsed.getQueryString(), parameterBindings);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,10 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.data.expression.ReactiveValueEvaluationContextProvider;
|
||||
import org.springframework.data.expression.ValueEvaluationContextProvider;
|
||||
import org.springframework.data.expression.ValueExpressionParser;
|
||||
import org.springframework.data.r2dbc.convert.R2dbcConverter;
|
||||
import org.springframework.data.r2dbc.core.R2dbcEntityOperations;
|
||||
import org.springframework.data.r2dbc.core.ReactiveDataAccessStrategy;
|
||||
@@ -29,8 +33,10 @@ import org.springframework.data.r2dbc.dialect.BindTargetBinder;
|
||||
import org.springframework.data.r2dbc.repository.Query;
|
||||
import org.springframework.data.relational.repository.query.RelationalParameterAccessor;
|
||||
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.QueryMethodValueEvaluationContextAccessor;
|
||||
import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.ResultProcessor;
|
||||
import org.springframework.data.repository.query.ValueExpressionDelegate;
|
||||
import org.springframework.data.spel.ExpressionDependencies;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
@@ -52,10 +58,10 @@ public class StringBasedR2dbcQuery extends AbstractR2dbcQuery {
|
||||
|
||||
private final ExpressionQuery expressionQuery;
|
||||
private final ExpressionEvaluatingParameterBinder binder;
|
||||
private final ExpressionParser expressionParser;
|
||||
private final ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider;
|
||||
private final ExpressionDependencies expressionDependencies;
|
||||
private final ReactiveDataAccessStrategy dataAccessStrategy;
|
||||
private final ValueExpressionDelegate valueExpressionDelegate;
|
||||
private final ValueEvaluationContextProvider valueContextProvider;
|
||||
|
||||
/**
|
||||
* Creates a new {@link StringBasedR2dbcQuery} for the given {@link StringBasedR2dbcQuery}, {@link DatabaseClient},
|
||||
@@ -67,7 +73,9 @@ public class StringBasedR2dbcQuery extends AbstractR2dbcQuery {
|
||||
* @param dataAccessStrategy must not be {@literal null}.
|
||||
* @param expressionParser must not be {@literal null}.
|
||||
* @param evaluationContextProvider must not be {@literal null}.
|
||||
* @deprecated use the constructor version with {@link ValueExpressionDelegate}
|
||||
*/
|
||||
@Deprecated(since = "3.4")
|
||||
public StringBasedR2dbcQuery(R2dbcQueryMethod queryMethod, R2dbcEntityOperations entityOperations,
|
||||
R2dbcConverter converter, ReactiveDataAccessStrategy dataAccessStrategy, ExpressionParser expressionParser,
|
||||
ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
@@ -79,26 +87,60 @@ public class StringBasedR2dbcQuery extends AbstractR2dbcQuery {
|
||||
* Create a new {@link StringBasedR2dbcQuery} for the given {@code query}, {@link R2dbcQueryMethod},
|
||||
* {@link DatabaseClient}, {@link SpelExpressionParser}, and {@link QueryMethodEvaluationContextProvider}.
|
||||
*
|
||||
* @param query must not be {@literal null}.
|
||||
* @param method must not be {@literal null}.
|
||||
* @param entityOperations must not be {@literal null}.
|
||||
* @param converter must not be {@literal null}.
|
||||
* @param dataAccessStrategy must not be {@literal null}.
|
||||
* @param expressionParser must not be {@literal null}.
|
||||
* @param evaluationContextProvider must not be {@literal null}.
|
||||
* @deprecated use the constructor version with {@link ValueExpressionDelegate}
|
||||
*/
|
||||
@Deprecated(since = "3.4")
|
||||
public StringBasedR2dbcQuery(String query, R2dbcQueryMethod method, R2dbcEntityOperations entityOperations,
|
||||
R2dbcConverter converter, ReactiveDataAccessStrategy dataAccessStrategy, ExpressionParser expressionParser,
|
||||
ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
this(query, method, entityOperations, converter, dataAccessStrategy, new ValueExpressionDelegate(new QueryMethodValueEvaluationContextAccessor(new StandardEnvironment(), evaluationContextProvider.getEvaluationContextProvider()), ValueExpressionParser.create(() -> expressionParser)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link StringBasedR2dbcQuery} for the given {@code query}, {@link R2dbcQueryMethod},
|
||||
* {@link DatabaseClient}, {@link SpelExpressionParser}, and {@link QueryMethodEvaluationContextProvider}.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @param entityOperations must not be {@literal null}.
|
||||
* @param converter must not be {@literal null}.
|
||||
* @param dataAccessStrategy must not be {@literal null}.
|
||||
* @param valueExpressionDelegate must not be {@literal null}.
|
||||
*/
|
||||
public StringBasedR2dbcQuery(R2dbcQueryMethod method, R2dbcEntityOperations entityOperations,
|
||||
R2dbcConverter converter, ReactiveDataAccessStrategy dataAccessStrategy, ValueExpressionDelegate valueExpressionDelegate) {
|
||||
this(method.getRequiredAnnotatedQuery(), method, entityOperations, converter, dataAccessStrategy, valueExpressionDelegate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link StringBasedR2dbcQuery} for the given {@code query}, {@link R2dbcQueryMethod},
|
||||
* {@link DatabaseClient}, {@link SpelExpressionParser}, and {@link QueryMethodEvaluationContextProvider}.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @param entityOperations must not be {@literal null}.
|
||||
* @param converter must not be {@literal null}.
|
||||
* @param dataAccessStrategy must not be {@literal null}.
|
||||
* @param valueExpressionDelegate must not be {@literal null}.
|
||||
*/
|
||||
public StringBasedR2dbcQuery(String query, R2dbcQueryMethod method, R2dbcEntityOperations entityOperations,
|
||||
R2dbcConverter converter, ReactiveDataAccessStrategy dataAccessStrategy, ValueExpressionDelegate valueExpressionDelegate) {
|
||||
|
||||
super(method, entityOperations, converter);
|
||||
this.expressionParser = expressionParser;
|
||||
this.evaluationContextProvider = evaluationContextProvider;
|
||||
this.valueExpressionDelegate = valueExpressionDelegate;
|
||||
|
||||
Assert.hasText(query, "Query must not be empty");
|
||||
|
||||
this.dataAccessStrategy = dataAccessStrategy;
|
||||
this.expressionQuery = ExpressionQuery.create(query);
|
||||
this.expressionQuery = ExpressionQuery.create(valueExpressionDelegate, query);
|
||||
this.binder = new ExpressionEvaluatingParameterBinder(expressionQuery, dataAccessStrategy);
|
||||
this.valueContextProvider = valueExpressionDelegate.createValueContextProvider(
|
||||
method.getParameters());
|
||||
this.expressionDependencies = createExpressionDependencies();
|
||||
|
||||
if (method.isSliceQuery()) {
|
||||
@@ -126,7 +168,7 @@ public class StringBasedR2dbcQuery extends AbstractR2dbcQuery {
|
||||
List<ExpressionDependencies> dependencies = new ArrayList<>();
|
||||
|
||||
for (ExpressionQuery.ParameterBinding binding : expressionQuery.getBindings()) {
|
||||
dependencies.add(ExpressionDependencies.discover(expressionParser.parseExpression(binding.getExpression())));
|
||||
dependencies.add(valueExpressionDelegate.parse(binding.getExpression()).getExpressionDependencies());
|
||||
}
|
||||
|
||||
return ExpressionDependencies.merged(dependencies);
|
||||
@@ -160,11 +202,11 @@ public class StringBasedR2dbcQuery extends AbstractR2dbcQuery {
|
||||
}
|
||||
|
||||
private Mono<R2dbcSpELExpressionEvaluator> getSpelEvaluator(RelationalParameterAccessor accessor) {
|
||||
|
||||
return evaluationContextProvider
|
||||
.getEvaluationContextLater(getQueryMethod().getParameters(), accessor.getValues(), expressionDependencies)
|
||||
Assert.isInstanceOf(ReactiveValueEvaluationContextProvider.class, valueContextProvider, "ValueEvaluationContextProvider must be reactive");
|
||||
return ((ReactiveValueEvaluationContextProvider) valueContextProvider)
|
||||
.getEvaluationContextLater(accessor.getValues(), expressionDependencies)
|
||||
.<R2dbcSpELExpressionEvaluator> map(
|
||||
context -> new DefaultR2dbcSpELExpressionEvaluator(expressionParser, context))
|
||||
context -> new DefaultR2dbcSpELExpressionEvaluator(valueExpressionDelegate, context))
|
||||
.defaultIfEmpty(DefaultR2dbcSpELExpressionEvaluator.unsupported());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020-2024 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.r2dbc.repository.support;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.ParseException;
|
||||
import org.springframework.expression.ParserContext;
|
||||
|
||||
/**
|
||||
* Caching variant of {@link ExpressionParser}. This implementation does not support
|
||||
* {@link #parseExpression(String, ParserContext) parsing with ParseContext}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.2
|
||||
*/
|
||||
class CachingExpressionParser implements ExpressionParser {
|
||||
|
||||
private final ExpressionParser delegate;
|
||||
private final Map<String, Expression> cache = new ConcurrentHashMap<>();
|
||||
|
||||
CachingExpressionParser(ExpressionParser delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression parseExpression(String expressionString) throws ParseException {
|
||||
return cache.computeIfAbsent(expressionString, delegate::parseExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression parseExpression(String expressionString, ParserContext context) throws ParseException {
|
||||
throw new UnsupportedOperationException("Parsing using ParserContext is not supported");
|
||||
}
|
||||
}
|
||||
@@ -37,13 +37,12 @@ import org.springframework.data.repository.core.NamedQueries;
|
||||
import org.springframework.data.repository.core.RepositoryInformation;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.ReactiveRepositoryFactorySupport;
|
||||
import org.springframework.data.repository.query.CachingValueExpressionDelegate;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.data.repository.query.ValueExpressionDelegate;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.r2dbc.core.DatabaseClient;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -56,8 +55,6 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class R2dbcRepositoryFactory extends ReactiveRepositoryFactorySupport {
|
||||
|
||||
private static final SpelExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();
|
||||
|
||||
private final DatabaseClient databaseClient;
|
||||
private final ReactiveDataAccessStrategy dataAccessStrategy;
|
||||
private final MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> mappingContext;
|
||||
@@ -116,11 +113,9 @@ public class R2dbcRepositoryFactory extends ReactiveRepositoryFactorySupport {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(@Nullable Key key,
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
return Optional.of(new R2dbcQueryLookupStrategy(this.operations,
|
||||
(ReactiveQueryMethodEvaluationContextProvider) evaluationContextProvider, this.converter,
|
||||
this.dataAccessStrategy));
|
||||
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(Key key,
|
||||
ValueExpressionDelegate valueExpressionDelegate) {
|
||||
return Optional.of(new R2dbcQueryLookupStrategy(operations, new CachingValueExpressionDelegate(valueExpressionDelegate), converter, dataAccessStrategy));
|
||||
}
|
||||
|
||||
public <T, ID> RelationalEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
|
||||
@@ -145,19 +140,17 @@ public class R2dbcRepositoryFactory extends ReactiveRepositoryFactorySupport {
|
||||
private static class R2dbcQueryLookupStrategy extends RelationalQueryLookupStrategy {
|
||||
|
||||
private final R2dbcEntityOperations entityOperations;
|
||||
private final ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider;
|
||||
private final R2dbcConverter converter;
|
||||
private final ValueExpressionDelegate delegate;
|
||||
private final ReactiveDataAccessStrategy dataAccessStrategy;
|
||||
private final ExpressionParser parser = new CachingExpressionParser(EXPRESSION_PARSER);
|
||||
|
||||
R2dbcQueryLookupStrategy(R2dbcEntityOperations entityOperations,
|
||||
ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider, R2dbcConverter converter,
|
||||
ValueExpressionDelegate delegate, R2dbcConverter converter,
|
||||
ReactiveDataAccessStrategy dataAccessStrategy) {
|
||||
|
||||
super(converter.getMappingContext(), dataAccessStrategy.getDialect());
|
||||
|
||||
this.delegate = delegate;
|
||||
this.entityOperations = entityOperations;
|
||||
this.evaluationContextProvider = evaluationContextProvider;
|
||||
this.converter = converter;
|
||||
this.dataAccessStrategy = dataAccessStrategy;
|
||||
}
|
||||
@@ -175,8 +168,7 @@ public class R2dbcRepositoryFactory extends ReactiveRepositoryFactorySupport {
|
||||
: queryMethod.getRequiredAnnotatedQuery();
|
||||
query = evaluateTableExpressions(metadata, query);
|
||||
|
||||
return new StringBasedR2dbcQuery(query, queryMethod, this.entityOperations, this.converter,
|
||||
this.dataAccessStrategy, parser, this.evaluationContextProvider);
|
||||
return new StringBasedR2dbcQuery(query, queryMethod, this.entityOperations, this.converter, this.dataAccessStrategy, this.delegate);
|
||||
|
||||
} else {
|
||||
return new PartTreeR2dbcQuery(queryMethod, this.entityOperations, this.converter, this.dataAccessStrategy);
|
||||
|
||||
@@ -17,9 +17,10 @@ package org.springframework.data.r2dbc.repository.query;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.assertj.core.api.SoftAssertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.data.expression.ValueExpressionParser;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ExpressionQuery}.
|
||||
*
|
||||
@@ -32,18 +33,15 @@ class ExpressionQueryUnitTests {
|
||||
void bindsMultipleSpelParametersCorrectly() {
|
||||
|
||||
ExpressionQuery query = ExpressionQuery
|
||||
.create("INSERT IGNORE INTO table (x, y) VALUES (:#{#point.x}, :#{#point.y})");
|
||||
.create(ValueExpressionParser.create(), "INSERT IGNORE INTO table (x, y) VALUES (:#{#point.x}, :${point.y})");
|
||||
|
||||
assertThat(query.getQuery())
|
||||
.isEqualTo("INSERT IGNORE INTO table (x, y) VALUES (:__synthetic_0__, :__synthetic_1__)");
|
||||
|
||||
SoftAssertions.assertSoftly(softly -> {
|
||||
|
||||
softly.assertThat(query.getBindings()).hasSize(2);
|
||||
softly.assertThat(query.getBindings().get(0).getExpression()).isEqualTo("#point.x");
|
||||
softly.assertThat(query.getBindings().get(0).getParameterName()).isEqualTo("__synthetic_0__");
|
||||
softly.assertThat(query.getBindings().get(1).getExpression()).isEqualTo("#point.y");
|
||||
softly.assertThat(query.getBindings().get(1).getParameterName()).isEqualTo("__synthetic_1__");
|
||||
});
|
||||
assertThat(query.getBindings()).hasSize(2);
|
||||
assertThat(query.getBindings().get(0).getExpression()).isEqualTo("#{#point.x}");
|
||||
assertThat(query.getBindings().get(0).getParameterName()).isEqualTo("__synthetic_0__");
|
||||
assertThat(query.getBindings().get(1).getExpression()).isEqualTo("${point.y}");
|
||||
assertThat(query.getBindings().get(1).getParameterName()).isEqualTo("__synthetic_1__");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import reactor.test.StepVerifier;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -33,8 +34,10 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
|
||||
import org.springframework.data.domain.Limit;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.expression.ValueExpressionParser;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.r2dbc.convert.MappingR2dbcConverter;
|
||||
@@ -51,8 +54,10 @@ import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.AbstractRepositoryMetadata;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.QueryMethodValueEvaluationContextAccessor;
|
||||
import org.springframework.data.repository.query.ValueExpressionDelegate;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.r2dbc.core.DatabaseClient;
|
||||
import org.springframework.r2dbc.core.PreparedOperation;
|
||||
import org.springframework.r2dbc.core.binding.BindTarget;
|
||||
@@ -67,7 +72,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
public class StringBasedR2dbcQueryUnitTests {
|
||||
|
||||
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
|
||||
private static final ValueExpressionParser PARSER = ValueExpressionParser.create(SpelExpressionParser::new);
|
||||
|
||||
@Mock private R2dbcEntityOperations entityOperations;
|
||||
@Mock private BindTarget bindTarget;
|
||||
@@ -77,6 +82,7 @@ public class StringBasedR2dbcQueryUnitTests {
|
||||
private ReactiveDataAccessStrategy accessStrategy;
|
||||
private ProjectionFactory factory;
|
||||
private RepositoryMetadata metadata;
|
||||
private MockEnvironment environment;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
@@ -86,6 +92,7 @@ public class StringBasedR2dbcQueryUnitTests {
|
||||
this.accessStrategy = new DefaultReactiveDataAccessStrategy(PostgresDialect.INSTANCE, converter);
|
||||
this.metadata = AbstractRepositoryMetadata.getMetadata(SampleRepository.class);
|
||||
this.factory = new SpelAwareProxyProjectionFactory();
|
||||
this.environment = new MockEnvironment();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -322,8 +329,10 @@ public class StringBasedR2dbcQueryUnitTests {
|
||||
|
||||
R2dbcQueryMethod queryMethod = new R2dbcQueryMethod(method, metadata, factory, converter.getMappingContext());
|
||||
|
||||
return new StringBasedR2dbcQuery(queryMethod, entityOperations, converter, accessStrategy, PARSER,
|
||||
ReactiveQueryMethodEvaluationContextProvider.DEFAULT);
|
||||
QueryMethodValueEvaluationContextAccessor accessor = new QueryMethodValueEvaluationContextAccessor(
|
||||
environment, Collections.emptySet());
|
||||
|
||||
return new StringBasedR2dbcQuery(queryMethod, entityOperations, converter, accessStrategy, new ValueExpressionDelegate(accessor, PARSER));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
|
||||
@@ -24,7 +24,8 @@ import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
|
||||
import org.springframework.data.r2dbc.dialect.H2Dialect;
|
||||
import org.springframework.data.r2dbc.repository.R2dbcRepository;
|
||||
import org.springframework.data.repository.query.ReactiveExtensionAwareQueryMethodEvaluationContextProvider;
|
||||
import org.springframework.data.spel.EvaluationContextProvider;
|
||||
import org.springframework.data.spel.ReactiveExtensionAwareEvaluationContextProvider;
|
||||
import org.springframework.r2dbc.core.DatabaseClient;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
@@ -49,8 +50,8 @@ class R2dbcRepositoryFactoryBeanUnitTests {
|
||||
Object factory = ReflectionTestUtils.getField(factoryBean, "factory");
|
||||
Object evaluationContextProvider = ReflectionTestUtils.getField(factory, "evaluationContextProvider");
|
||||
|
||||
assertThat(evaluationContextProvider).isInstanceOf(ReactiveExtensionAwareQueryMethodEvaluationContextProvider.class)
|
||||
.isNotEqualTo(ReactiveExtensionAwareQueryMethodEvaluationContextProvider.DEFAULT);
|
||||
assertThat(evaluationContextProvider).isInstanceOf(ReactiveExtensionAwareEvaluationContextProvider.class)
|
||||
.isNotEqualTo(EvaluationContextProvider.DEFAULT);
|
||||
}
|
||||
|
||||
static class Person {}
|
||||
|
||||
Reference in New Issue
Block a user