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
@@ -20,16 +20,20 @@ import static org.springframework.data.jdbc.repository.query.JdbcQueryExecution.
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.sql.SQLType;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.beans.BeanInstantiationException;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.data.expression.ValueEvaluationContext;
|
||||
import org.springframework.data.expression.ValueExpressionParser;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcColumnTypes;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcConverter;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcValue;
|
||||
@@ -37,14 +41,17 @@ import org.springframework.data.jdbc.support.JdbcUtil;
|
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
||||
import org.springframework.data.relational.repository.query.RelationalParameterAccessor;
|
||||
import org.springframework.data.relational.repository.query.RelationalParametersParameterAccessor;
|
||||
import org.springframework.data.repository.query.CachingValueExpressionDelegate;
|
||||
import org.springframework.data.repository.query.Parameter;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.QueryMethodValueEvaluationContextAccessor;
|
||||
import org.springframework.data.repository.query.ResultProcessor;
|
||||
import org.springframework.data.repository.query.SpelEvaluator;
|
||||
import org.springframework.data.repository.query.SpelQueryContext;
|
||||
import org.springframework.data.repository.query.ValueExpressionDelegate;
|
||||
import org.springframework.data.repository.query.ValueExpressionQueryRewriter;
|
||||
import org.springframework.data.util.Lazy;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.jdbc.core.ResultSetExtractor;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||
@@ -74,12 +81,14 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery {
|
||||
private static final String PARAMETER_NEEDS_TO_BE_NAMED = "For queries with named parameters you need to provide names for method parameters; Use @Param for query method parameters, or use the javac flag -parameters";
|
||||
private final JdbcConverter converter;
|
||||
private final RowMapperFactory rowMapperFactory;
|
||||
private final SpelEvaluator spelEvaluator;
|
||||
private final ValueExpressionQueryRewriter.ParsedQuery parsedQuery;
|
||||
private final boolean containsSpelExpressions;
|
||||
private final String query;
|
||||
|
||||
private final CachedRowMapperFactory cachedRowMapperFactory;
|
||||
private final CachedResultSetExtractorFactory cachedResultSetExtractorFactory;
|
||||
private final ValueExpressionDelegate delegate;
|
||||
private final List<Map.Entry<String, String>> parameterBindings;
|
||||
|
||||
/**
|
||||
* Creates a new {@link StringBasedJdbcQuery} for the given {@link JdbcQueryMethod}, {@link RelationalMappingContext}
|
||||
@@ -88,7 +97,9 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery {
|
||||
* @param queryMethod must not be {@literal null}.
|
||||
* @param operations must not be {@literal null}.
|
||||
* @param defaultRowMapper can be {@literal null} (only in case of a modifying query).
|
||||
* @deprecated since 3.4, use the constructors accepting {@link ValueExpressionDelegate} instead.
|
||||
*/
|
||||
@Deprecated(since = "3.4")
|
||||
public StringBasedJdbcQuery(JdbcQueryMethod queryMethod, NamedParameterJdbcOperations operations,
|
||||
@Nullable RowMapper<?> defaultRowMapper, JdbcConverter converter,
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
@@ -116,6 +127,23 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery {
|
||||
evaluationContextProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link StringBasedJdbcQuery} for the given {@link JdbcQueryMethod}, {@link RelationalMappingContext}
|
||||
* and {@link RowMapperFactory}.
|
||||
*
|
||||
* @param queryMethod must not be {@literal null}.
|
||||
* @param operations must not be {@literal null}.
|
||||
* @param rowMapperFactory must not be {@literal null}.
|
||||
* @param converter must not be {@literal null}.
|
||||
* @param delegate must not be {@literal null}.
|
||||
* @since 3.4
|
||||
*/
|
||||
public StringBasedJdbcQuery(JdbcQueryMethod queryMethod, NamedParameterJdbcOperations operations,
|
||||
RowMapperFactory rowMapperFactory, JdbcConverter converter,
|
||||
ValueExpressionDelegate delegate) {
|
||||
this(queryMethod.getRequiredQuery(), queryMethod, operations, rowMapperFactory, converter, delegate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link StringBasedJdbcQuery} for the given {@link JdbcQueryMethod}, {@link RelationalMappingContext}
|
||||
* and {@link RowMapperFactory}.
|
||||
@@ -125,15 +153,13 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery {
|
||||
* @param operations must not be {@literal null}.
|
||||
* @param rowMapperFactory must not be {@literal null}.
|
||||
* @param converter must not be {@literal null}.
|
||||
* @param evaluationContextProvider must not be {@literal null}.
|
||||
* @param delegate must not be {@literal null}.
|
||||
* @since 3.4
|
||||
*/
|
||||
public StringBasedJdbcQuery(String query, JdbcQueryMethod queryMethod, NamedParameterJdbcOperations operations,
|
||||
RowMapperFactory rowMapperFactory, JdbcConverter converter,
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
|
||||
ValueExpressionDelegate delegate) {
|
||||
super(queryMethod, operations);
|
||||
|
||||
Assert.hasText(query, "Query must not be null or empty");
|
||||
Assert.notNull(rowMapperFactory, "RowMapperFactory must not be null");
|
||||
|
||||
@@ -160,13 +186,40 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery {
|
||||
this.cachedResultSetExtractorFactory = new CachedResultSetExtractorFactory(
|
||||
this.cachedRowMapperFactory::getRowMapper);
|
||||
|
||||
SpelQueryContext.EvaluatingSpelQueryContext queryContext = SpelQueryContext
|
||||
.of((counter, expression) -> String.format("__$synthetic$__%d", counter + 1), String::concat)
|
||||
.withEvaluationContextProvider(evaluationContextProvider);
|
||||
this.parameterBindings = new ArrayList<>();
|
||||
|
||||
ValueExpressionQueryRewriter rewriter = ValueExpressionQueryRewriter.of(delegate, (counter, expression) -> {
|
||||
String newName = String.format("__$synthetic$__%d", counter + 1);
|
||||
parameterBindings.add(new AbstractMap.SimpleEntry<>(newName, expression));
|
||||
return newName;
|
||||
}, String::concat);
|
||||
|
||||
this.query = query;
|
||||
this.spelEvaluator = queryContext.parse(this.query, getQueryMethod().getParameters());
|
||||
this.containsSpelExpressions = !this.spelEvaluator.getQueryString().equals(this.query);
|
||||
this.parsedQuery = rewriter.parse(this.query);
|
||||
this.containsSpelExpressions = !this.parsedQuery.getQueryString().equals(this.query);
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link StringBasedJdbcQuery} for the given {@link JdbcQueryMethod}, {@link RelationalMappingContext}
|
||||
* and {@link RowMapperFactory}.
|
||||
*
|
||||
* @param query must not be {@literal null} or empty.
|
||||
* @param queryMethod must not be {@literal null}.
|
||||
* @param operations must not be {@literal null}.
|
||||
* @param rowMapperFactory must not be {@literal null}.
|
||||
* @param converter must not be {@literal null}.
|
||||
* @param evaluationContextProvider must not be {@literal null}.
|
||||
* @since 3.4
|
||||
* @deprecated since 3.4, use the constructors accepting {@link ValueExpressionDelegate} instead.
|
||||
*/
|
||||
@Deprecated(since = "3.4")
|
||||
public StringBasedJdbcQuery(String query, JdbcQueryMethod queryMethod, NamedParameterJdbcOperations operations,
|
||||
RowMapperFactory rowMapperFactory, JdbcConverter converter,
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
this(query, queryMethod, operations, rowMapperFactory, converter, new CachingValueExpressionDelegate(new QueryMethodValueEvaluationContextAccessor(null,
|
||||
rootObject -> evaluationContextProvider.getEvaluationContext(queryMethod.getParameters(), new Object[] { rootObject })), ValueExpressionParser.create(
|
||||
SpelExpressionParser::new)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -178,15 +231,19 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery {
|
||||
JdbcQueryExecution<?> queryExecution = createJdbcQueryExecution(accessor, processor);
|
||||
MapSqlParameterSource parameterMap = this.bindParameters(accessor);
|
||||
|
||||
return queryExecution.execute(processSpelExpressions(objects, parameterMap), parameterMap);
|
||||
return queryExecution.execute(processSpelExpressions(objects, accessor.getBindableParameters(), parameterMap), parameterMap);
|
||||
}
|
||||
|
||||
private String processSpelExpressions(Object[] objects, MapSqlParameterSource parameterMap) {
|
||||
private String processSpelExpressions(Object[] objects, Parameters<?, ?> bindableParameters, MapSqlParameterSource parameterMap) {
|
||||
|
||||
if (containsSpelExpressions) {
|
||||
|
||||
spelEvaluator.evaluate(objects).forEach(parameterMap::addValue);
|
||||
return spelEvaluator.getQueryString();
|
||||
ValueEvaluationContext evaluationContext = delegate.createValueContextProvider(bindableParameters)
|
||||
.getEvaluationContext(objects);
|
||||
for (Map.Entry<String, String> entry : parameterBindings) {
|
||||
parameterMap.addValue(
|
||||
entry.getKey(), delegate.parse(entry.getValue()).evaluate(evaluationContext));
|
||||
}
|
||||
return parsedQuery.getQueryString();
|
||||
}
|
||||
|
||||
return this.query;
|
||||
|
||||
@@ -41,8 +41,8 @@ import org.springframework.data.relational.repository.support.RelationalQueryLoo
|
||||
import org.springframework.data.repository.core.NamedQueries;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.data.repository.query.ValueExpressionDelegate;
|
||||
import org.springframework.jdbc.core.ResultSetExtractor;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.SingleColumnRowMapper;
|
||||
@@ -73,12 +73,12 @@ abstract class JdbcQueryLookupStrategy extends RelationalQueryLookupStrategy {
|
||||
private final JdbcConverter converter;
|
||||
private final QueryMappingConfiguration queryMappingConfiguration;
|
||||
private final NamedParameterJdbcOperations operations;
|
||||
protected final QueryMethodEvaluationContextProvider evaluationContextProvider;
|
||||
protected final ValueExpressionDelegate delegate;
|
||||
|
||||
JdbcQueryLookupStrategy(ApplicationEventPublisher publisher, @Nullable EntityCallbacks callbacks,
|
||||
RelationalMappingContext context, JdbcConverter converter, Dialect dialect,
|
||||
QueryMappingConfiguration queryMappingConfiguration, NamedParameterJdbcOperations operations,
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
ValueExpressionDelegate delegate) {
|
||||
|
||||
super(context, dialect);
|
||||
|
||||
@@ -86,7 +86,7 @@ abstract class JdbcQueryLookupStrategy extends RelationalQueryLookupStrategy {
|
||||
Assert.notNull(converter, "JdbcConverter must not be null");
|
||||
Assert.notNull(queryMappingConfiguration, "QueryMappingConfiguration must not be null");
|
||||
Assert.notNull(operations, "NamedParameterJdbcOperations must not be null");
|
||||
Assert.notNull(evaluationContextProvider, "QueryMethodEvaluationContextProvider must not be null");
|
||||
Assert.notNull(delegate, "ValueExpressionDelegate must not be null");
|
||||
|
||||
this.context = context;
|
||||
this.publisher = publisher;
|
||||
@@ -94,7 +94,7 @@ abstract class JdbcQueryLookupStrategy extends RelationalQueryLookupStrategy {
|
||||
this.converter = converter;
|
||||
this.queryMappingConfiguration = queryMappingConfiguration;
|
||||
this.operations = operations;
|
||||
this.evaluationContextProvider = evaluationContextProvider;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public RelationalMappingContext getMappingContext() {
|
||||
@@ -112,10 +112,10 @@ abstract class JdbcQueryLookupStrategy extends RelationalQueryLookupStrategy {
|
||||
CreateQueryLookupStrategy(ApplicationEventPublisher publisher, @Nullable EntityCallbacks callbacks,
|
||||
RelationalMappingContext context, JdbcConverter converter, Dialect dialect,
|
||||
QueryMappingConfiguration queryMappingConfiguration, NamedParameterJdbcOperations operations,
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
ValueExpressionDelegate delegate) {
|
||||
|
||||
super(publisher, callbacks, context, converter, dialect, queryMappingConfiguration, operations,
|
||||
evaluationContextProvider);
|
||||
delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -143,9 +143,9 @@ abstract class JdbcQueryLookupStrategy extends RelationalQueryLookupStrategy {
|
||||
DeclaredQueryLookupStrategy(ApplicationEventPublisher publisher, @Nullable EntityCallbacks callbacks,
|
||||
RelationalMappingContext context, JdbcConverter converter, Dialect dialect,
|
||||
QueryMappingConfiguration queryMappingConfiguration, NamedParameterJdbcOperations operations,
|
||||
@Nullable BeanFactory beanfactory, QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
@Nullable BeanFactory beanfactory, ValueExpressionDelegate delegate) {
|
||||
super(publisher, callbacks, context, converter, dialect, queryMappingConfiguration, operations,
|
||||
evaluationContextProvider);
|
||||
delegate);
|
||||
|
||||
this.rowMapperFactory = new BeanFactoryRowMapperFactory(beanfactory);
|
||||
}
|
||||
@@ -166,7 +166,7 @@ abstract class JdbcQueryLookupStrategy extends RelationalQueryLookupStrategy {
|
||||
String queryString = evaluateTableExpressions(repositoryMetadata, queryMethod.getRequiredQuery());
|
||||
|
||||
return new StringBasedJdbcQuery(queryString, queryMethod, getOperations(), rowMapperFactory, getConverter(),
|
||||
evaluationContextProvider);
|
||||
delegate);
|
||||
}
|
||||
|
||||
throw new IllegalStateException(
|
||||
@@ -235,10 +235,10 @@ abstract class JdbcQueryLookupStrategy extends RelationalQueryLookupStrategy {
|
||||
RelationalMappingContext context, JdbcConverter converter, Dialect dialect,
|
||||
QueryMappingConfiguration queryMappingConfiguration, NamedParameterJdbcOperations operations,
|
||||
CreateQueryLookupStrategy createStrategy,
|
||||
DeclaredQueryLookupStrategy lookupStrategy, QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
DeclaredQueryLookupStrategy lookupStrategy, ValueExpressionDelegate delegate) {
|
||||
|
||||
super(publisher, callbacks, context, converter, dialect, queryMappingConfiguration, operations,
|
||||
evaluationContextProvider);
|
||||
delegate);
|
||||
|
||||
Assert.notNull(createStrategy, "CreateQueryLookupStrategy must not be null");
|
||||
Assert.notNull(lookupStrategy, "DeclaredQueryLookupStrategy must not be null");
|
||||
@@ -284,20 +284,20 @@ abstract class JdbcQueryLookupStrategy extends RelationalQueryLookupStrategy {
|
||||
public static QueryLookupStrategy create(@Nullable Key key, ApplicationEventPublisher publisher,
|
||||
@Nullable EntityCallbacks callbacks, RelationalMappingContext context, JdbcConverter converter, Dialect dialect,
|
||||
QueryMappingConfiguration queryMappingConfiguration, NamedParameterJdbcOperations operations,
|
||||
@Nullable BeanFactory beanFactory, QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
|
||||
@Nullable BeanFactory beanFactory, ValueExpressionDelegate delegate) {
|
||||
Assert.notNull(publisher, "ApplicationEventPublisher must not be null");
|
||||
Assert.notNull(context, "RelationalMappingContextPublisher must not be null");
|
||||
Assert.notNull(converter, "JdbcConverter must not be null");
|
||||
Assert.notNull(dialect, "Dialect must not be null");
|
||||
Assert.notNull(queryMappingConfiguration, "QueryMappingConfiguration must not be null");
|
||||
Assert.notNull(operations, "NamedParameterJdbcOperations must not be null");
|
||||
Assert.notNull(delegate, "ValueExpressionDelegate must not be null");
|
||||
|
||||
CreateQueryLookupStrategy createQueryLookupStrategy = new CreateQueryLookupStrategy(publisher, callbacks, context,
|
||||
converter, dialect, queryMappingConfiguration, operations, evaluationContextProvider);
|
||||
converter, dialect, queryMappingConfiguration, operations, delegate);
|
||||
|
||||
DeclaredQueryLookupStrategy declaredQueryLookupStrategy = new DeclaredQueryLookupStrategy(publisher, callbacks,
|
||||
context, converter, dialect, queryMappingConfiguration, operations, beanFactory, evaluationContextProvider);
|
||||
context, converter, dialect, queryMappingConfiguration, operations, beanFactory, delegate);
|
||||
|
||||
Key keyToUse = key != null ? key : Key.CREATE_IF_NOT_FOUND;
|
||||
|
||||
@@ -311,7 +311,7 @@ abstract class JdbcQueryLookupStrategy extends RelationalQueryLookupStrategy {
|
||||
case CREATE_IF_NOT_FOUND:
|
||||
return new CreateIfNotFoundQueryLookupStrategy(publisher, callbacks, context, converter, dialect,
|
||||
queryMappingConfiguration, operations, createQueryLookupStrategy, declaredQueryLookupStrategy,
|
||||
evaluationContextProvider);
|
||||
delegate);
|
||||
default:
|
||||
throw new IllegalArgumentException(String.format("Unsupported query lookup strategy %s", key));
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.PersistentEntityInformation;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.ValueExpressionDelegate;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -132,12 +132,10 @@ public class JdbcRepositoryFactory extends RepositoryFactorySupport {
|
||||
return SimpleJdbcRepository.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(@Nullable QueryLookupStrategy.Key key,
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
|
||||
@Override protected Optional<QueryLookupStrategy> getQueryLookupStrategy(QueryLookupStrategy.Key key,
|
||||
ValueExpressionDelegate valueExpressionDelegate) {
|
||||
return Optional.of(JdbcQueryLookupStrategy.create(key, publisher, entityCallbacks, context, converter, dialect,
|
||||
queryMappingConfiguration, operations, beanFactory, evaluationContextProvider));
|
||||
queryMappingConfiguration, operations, beanFactory, valueExpressionDelegate));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,7 +33,10 @@ import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.convert.ReadingConverter;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
@@ -41,6 +44,7 @@ import org.springframework.data.domain.Limit;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.expression.ValueExpressionParser;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcConverter;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcCustomConversions;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcTypeFactory;
|
||||
@@ -53,9 +57,9 @@ import org.springframework.data.relational.core.mapping.RelationalMappingContext
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.PropertiesBasedNamedQueries;
|
||||
import org.springframework.data.repository.query.ExtensionAwareQueryMethodEvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.QueryMethodValueEvaluationContextAccessor;
|
||||
import org.springframework.data.repository.query.ValueExpressionDelegate;
|
||||
import org.springframework.data.spel.spi.EvaluationContextExtension;
|
||||
import org.springframework.jdbc.core.ResultSetExtractor;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
@@ -82,7 +86,7 @@ class StringBasedJdbcQueryUnitTests {
|
||||
NamedParameterJdbcOperations operations;
|
||||
RelationalMappingContext context;
|
||||
JdbcConverter converter;
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider;
|
||||
ValueExpressionDelegate delegate;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
@@ -91,7 +95,8 @@ class StringBasedJdbcQueryUnitTests {
|
||||
this.operations = mock(NamedParameterJdbcOperations.class);
|
||||
this.context = mock(RelationalMappingContext.class, RETURNS_DEEP_STUBS);
|
||||
this.converter = new MappingJdbcConverter(context, mock(RelationResolver.class));
|
||||
this.evaluationContextProvider = mock(QueryMethodEvaluationContextProvider.class);
|
||||
QueryMethodValueEvaluationContextAccessor accessor = new QueryMethodValueEvaluationContextAccessor(new StandardEnvironment(), new StaticApplicationContext());
|
||||
this.delegate = new ValueExpressionDelegate(accessor, ValueExpressionParser.create());
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-165
|
||||
@@ -248,7 +253,7 @@ class StringBasedJdbcQueryUnitTests {
|
||||
JdbcQueryMethod queryMethod = createMethod("sliceAll", Pageable.class);
|
||||
|
||||
assertThatThrownBy(
|
||||
() -> new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter, evaluationContextProvider))
|
||||
() -> new StringBasedJdbcQuery(queryMethod, operations, result -> defaultRowMapper, converter, delegate))
|
||||
.isInstanceOf(UnsupportedOperationException.class)
|
||||
.hasMessageContaining("Slice queries are not supported using string-based queries");
|
||||
}
|
||||
@@ -259,7 +264,7 @@ class StringBasedJdbcQueryUnitTests {
|
||||
JdbcQueryMethod queryMethod = createMethod("pageAll", Pageable.class);
|
||||
|
||||
assertThatThrownBy(
|
||||
() -> new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter, evaluationContextProvider))
|
||||
() -> new StringBasedJdbcQuery(queryMethod, operations, result -> defaultRowMapper, converter, delegate))
|
||||
.isInstanceOf(UnsupportedOperationException.class)
|
||||
.hasMessageContaining("Page queries are not supported using string-based queries");
|
||||
}
|
||||
@@ -270,7 +275,7 @@ class StringBasedJdbcQueryUnitTests {
|
||||
JdbcQueryMethod queryMethod = createMethod("unsupportedLimitQuery", String.class, Limit.class);
|
||||
|
||||
assertThatThrownBy(
|
||||
() -> new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter, evaluationContextProvider))
|
||||
() -> new StringBasedJdbcQuery(queryMethod, operations, result -> defaultRowMapper, converter, delegate))
|
||||
.isInstanceOf(UnsupportedOperationException.class);
|
||||
}
|
||||
|
||||
@@ -350,11 +355,11 @@ class StringBasedJdbcQueryUnitTests {
|
||||
|
||||
List<EvaluationContextExtension> list = new ArrayList<>();
|
||||
list.add(new MyEvaluationContextProvider());
|
||||
QueryMethodEvaluationContextProvider evaluationContextProviderImpl = new ExtensionAwareQueryMethodEvaluationContextProvider(
|
||||
list);
|
||||
|
||||
StringBasedJdbcQuery sut = new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter,
|
||||
evaluationContextProviderImpl);
|
||||
QueryMethodValueEvaluationContextAccessor accessor = new QueryMethodValueEvaluationContextAccessor(new StandardEnvironment(), list);
|
||||
this.delegate = new ValueExpressionDelegate(accessor, ValueExpressionParser.create());
|
||||
|
||||
StringBasedJdbcQuery sut = new StringBasedJdbcQuery(queryMethod, operations, result -> defaultRowMapper, converter, delegate);
|
||||
|
||||
ArgumentCaptor<SqlParameterSource> paramSource = ArgumentCaptor.forClass(SqlParameterSource.class);
|
||||
ArgumentCaptor<String> query = ArgumentCaptor.forClass(String.class);
|
||||
@@ -398,7 +403,7 @@ class StringBasedJdbcQueryUnitTests {
|
||||
: this.converter;
|
||||
|
||||
StringBasedJdbcQuery query = new StringBasedJdbcQuery(method.getDeclaredQuery(), method, operations, result -> mock(RowMapper.class),
|
||||
converter, evaluationContextProvider);
|
||||
converter, delegate);
|
||||
|
||||
query.execute(arguments);
|
||||
|
||||
@@ -434,7 +439,7 @@ class StringBasedJdbcQueryUnitTests {
|
||||
}
|
||||
|
||||
private StringBasedJdbcQuery createQuery(JdbcQueryMethod queryMethod, String preparedReference, Object value) {
|
||||
return new StringBasedJdbcQuery(queryMethod, operations, new StubRowMapperFactory(preparedReference, value), converter, evaluationContextProvider);
|
||||
return new StringBasedJdbcQuery(queryMethod, operations, new StubRowMapperFactory(preparedReference, value), converter, delegate);
|
||||
}
|
||||
|
||||
interface MyRepository extends Repository<Object, Long> {
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.data.repository.query.ValueExpressionDelegate;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
|
||||
@@ -137,7 +138,7 @@ class JdbcQueryLookupStrategyUnitTests {
|
||||
.registerRowMapper(NumberFormat.class, numberFormatMapper);
|
||||
|
||||
QueryLookupStrategy queryLookupStrategy = JdbcQueryLookupStrategy.create(key, publisher, callbacks, mappingContext,
|
||||
converter, H2Dialect.INSTANCE, mappingConfiguration, operations, null, evaluationContextProvider);
|
||||
converter, H2Dialect.INSTANCE, mappingConfiguration, operations, null, ValueExpressionDelegate.create());
|
||||
|
||||
assertThat(queryLookupStrategy).isInstanceOf(expectedClass);
|
||||
}
|
||||
@@ -157,7 +158,7 @@ class JdbcQueryLookupStrategyUnitTests {
|
||||
QueryMappingConfiguration mappingConfiguration) {
|
||||
|
||||
QueryLookupStrategy queryLookupStrategy = JdbcQueryLookupStrategy.create(key, publisher, callbacks, mappingContext,
|
||||
converter, H2Dialect.INSTANCE, mappingConfiguration, operations, null, evaluationContextProvider);
|
||||
converter, H2Dialect.INSTANCE, mappingConfiguration, operations, null, ValueExpressionDelegate.create());
|
||||
|
||||
Method method = ReflectionUtils.findMethod(MyRepository.class, name);
|
||||
return queryLookupStrategy.resolveQuery(method, metadata, projectionFactory, namedQueries);
|
||||
|
||||
Reference in New Issue
Block a user