下面列出了org.springframework.context.expression.BeanFactoryAccessor#org.springframework.data.repository.query.QueryMethodEvaluationContextProvider 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Test
void shouldSelectStringBasedNeo4jQueryForNamedQuery() {
final String namedQueryName = "TestEntity.findAllByANamedQuery";
when(namedQueries.hasQuery(namedQueryName)).thenReturn(true);
when(namedQueries.getQuery(namedQueryName)).thenReturn("MATCH (n) RETURN n");
final Neo4jQueryLookupStrategy lookupStrategy = new Neo4jQueryLookupStrategy(mock(Neo4jOperations.class),
mock(
Neo4jMappingContext.class), QueryMethodEvaluationContextProvider.DEFAULT);
RepositoryQuery query = lookupStrategy
.resolveQuery(queryMethod("findAllByANamedQuery"), TEST_REPOSITORY_METADATA,
PROJECTION_FACTORY, namedQueries);
assertThat(query).isInstanceOf(StringBasedNeo4jQuery.class);
}
@Test
void shouldBindParameters() {
Neo4jQueryMethod method = RepositoryQueryTest
.neo4jQueryMethod("annotatedQueryWithValidTemplate", String.class, String.class);
StringBasedNeo4jQuery repositoryQuery = spy(StringBasedNeo4jQuery.create(mock(Neo4jOperations.class),
mock(Neo4jMappingContext.class), QueryMethodEvaluationContextProvider.DEFAULT,
method));
// skip conversion
doAnswer(invocation -> invocation.getArgument(0)).when(repositoryQuery).convertParameter(any());
Map<String, Object> resolveParameters = repositoryQuery
.bindParameters(new Neo4jParameterAccessor(
(Neo4jParameters) method.getParameters(), new Object[] { "A String", "Another String" }));
assertThat(resolveParameters)
.containsEntry("0", "A String")
.containsEntry("1", "Another String");
}
@Override
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(
final QueryLookupStrategy.Key key, final QueryMethodEvaluationContextProvider evaluationContextProvider) {
QueryLookupStrategy strategy = null;
switch (key) {
case CREATE_IF_NOT_FOUND:
strategy = new DefaultArangoQueryLookupStrategy(arangoOperations);
break;
case CREATE:
break;
case USE_DECLARED_QUERY:
break;
}
return Optional.ofNullable(strategy);
}
private QueryMethodEvaluationContextProvider delegateContextProvider(
QueryMethodEvaluationContextProvider evaluationContextProvider) {
return new QueryMethodEvaluationContextProvider() {
@Override
public <T extends Parameters<?, ?>> EvaluationContext getEvaluationContext(
T parameters, Object[] parameterValues) {
StandardEvaluationContext evaluationContext = (StandardEvaluationContext)
evaluationContextProvider
.getEvaluationContext(parameters, parameterValues);
evaluationContext.setRootObject(
DatastoreRepositoryFactory.this.applicationContext);
evaluationContext.addPropertyAccessor(new BeanFactoryAccessor());
evaluationContext.setBeanResolver(new BeanFactoryResolver(
DatastoreRepositoryFactory.this.applicationContext));
return evaluationContext;
}
};
}
private QueryMethodEvaluationContextProvider delegateContextProvider(
QueryMethodEvaluationContextProvider evaluationContextProvider) {
return new QueryMethodEvaluationContextProvider() {
@Override
public <T extends Parameters<?, ?>> EvaluationContext getEvaluationContext(
T parameters, Object[] parameterValues) {
StandardEvaluationContext evaluationContext = (StandardEvaluationContext) evaluationContextProvider
.getEvaluationContext(parameters, parameterValues);
evaluationContext
.setRootObject(SpannerRepositoryFactory.this.applicationContext);
evaluationContext.addPropertyAccessor(new BeanFactoryAccessor());
evaluationContext.setBeanResolver(new BeanFactoryResolver(
SpannerRepositoryFactory.this.applicationContext));
return evaluationContext;
}
};
}
@Before
public void initMocks() {
this.spannerMappingContext = new SpannerMappingContext();
this.spannerTemplate = mock(SpannerTemplate.class);
this.queryMethod = mock(SpannerQueryMethod.class);
this.evaluationContextProvider = mock(QueryMethodEvaluationContextProvider.class);
this.spelExpressionParser = new SpelExpressionParser();
this.spannerQueryLookupStrategy = getSpannerQueryLookupStrategy();
when(this.queryMethod.getQueryAnnotation()).thenReturn(new Query() {
@Override
public Class<? extends Annotation> annotationType() {
return Query.class;
}
@Override
public String value() {
return "";
}
@Override
public boolean dmlStatement() {
return false;
}
});
}
/**
* Creates a {@link QueryLookupStrategy} for the given {@link EbeanServer} and {@link Key}.
*
* @param ebeanServer must not be {@literal null}.
* @param key may be {@literal null}.
* @param evaluationContextProvider must not be {@literal null}.
* @return
*/
public static QueryLookupStrategy create(EbeanServer ebeanServer, Key key,
QueryMethodEvaluationContextProvider evaluationContextProvider) {
Assert.notNull(ebeanServer, "EbeanServer must not be null!");
Assert.notNull(evaluationContextProvider, "EvaluationContextProvider must not be null!");
switch (key != null ? key : Key.CREATE_IF_NOT_FOUND) {
case CREATE:
return new CreateQueryLookupStrategy(ebeanServer);
case USE_DECLARED_QUERY:
return new DeclaredQueryLookupStrategy(ebeanServer, evaluationContextProvider);
case CREATE_IF_NOT_FOUND:
return new CreateIfNotFoundQueryLookupStrategy(ebeanServer, new CreateQueryLookupStrategy(ebeanServer),
new DeclaredQueryLookupStrategy(ebeanServer, evaluationContextProvider));
default:
throw new IllegalArgumentException(String.format("Unsupported query lookup strategy %s!", key));
}
}
/**
* Creates a new {@link NativeEbeanUpdate} encapsulating the query annotated on the given {@link EbeanQueryMethod}.
*
* @param method must not be {@literal null}.
* @param ebeanServer must not be {@literal null}.
* @param queryString must not be {@literal null} or empty.
* @param evaluationContextProvider
*/
public NativeEbeanUpdate(EbeanQueryMethod method, EbeanServer ebeanServer, String queryString,
QueryMethodEvaluationContextProvider evaluationContextProvider, SpelExpressionParser parser) {
super(method, ebeanServer, queryString, evaluationContextProvider, parser);
Parameters<?, ?> parameters = method.getParameters();
boolean hasPagingOrSortingParameter = parameters.hasPageableParameter() || parameters.hasSortParameter();
boolean containsPageableOrSortInQueryExpression = queryString.contains("#pageable")
|| queryString.contains("#sort");
if (hasPagingOrSortingParameter && !containsPageableOrSortInQueryExpression) {
throw new InvalidEbeanQueryMethodException(
"Cannot use native queries with dynamic sorting and/or pagination in method " + method);
}
}
public static QueryLookupStrategy create(SqlSessionTemplate sqlSessionTemplate,
Key key, QueryMethodEvaluationContextProvider evaluationContextProvider) {
Assert.notNull(sqlSessionTemplate, "SqlSessionTemplate must not be null!");
Assert.notNull(evaluationContextProvider,
"EvaluationContextProvider must not be null!");
switch (key != null ? key : Key.CREATE_IF_NOT_FOUND) {
case CREATE:
return new CreateQueryLookupStrategy(sqlSessionTemplate);
case USE_DECLARED_QUERY:
return new DeclaredQueryLookupStrategy(sqlSessionTemplate,
evaluationContextProvider);
case CREATE_IF_NOT_FOUND:
return new CreateIfNotFoundQueryLookupStrategy(sqlSessionTemplate,
new CreateQueryLookupStrategy(sqlSessionTemplate),
new DeclaredQueryLookupStrategy(sqlSessionTemplate,
evaluationContextProvider));
default:
throw new IllegalArgumentException(
String.format("Unsupported query lookup strategy %s!", key));
}
}
/**
* <p>
* Required constructor, capturing arguments for use in {@link #resolveQuery}.
* </P>
* <p>
* Assertions copied from {@link KayValueRepositoryFactory.KeyValueQUeryLookupStrategy} which this class essentially
* duplicates.
* </P>
*
* @param key Not used
* @param evaluationContextProvider For evaluation of query expressions
* @param keyValueOperations Bean to use for Key/Value operations on Hazelcast repos
* @param queryCreator Likely to be {@link HazelcastQueryCreator}
* @param hazelcastInstance Instance of Hazelcast
*/
public HazelcastQueryLookupStrategy(QueryLookupStrategy.Key key,
QueryMethodEvaluationContextProvider evaluationContextProvider,
KeyValueOperations keyValueOperations,
Class<? extends AbstractQueryCreator<?, ?>> queryCreator,
HazelcastInstance hazelcastInstance) {
Assert.notNull(evaluationContextProvider, "EvaluationContextProvider must not be null!");
Assert.notNull(keyValueOperations, "KeyValueOperations must not be null!");
Assert.notNull(queryCreator, "Query creator type must not be null!");
Assert.notNull(hazelcastInstance, "HazelcastInstance must not be null!");
this.evaluationContextProvider = evaluationContextProvider;
this.keyValueOperations = keyValueOperations;
this.queryCreator = queryCreator;
this.hazelcastInstance = hazelcastInstance;
}
/**
* @param key
* @param evaluationContextProvider
* @param keyValueOperations
* @param queryCreator
* @since 1.1
*/
public KeyValueQueryLookupStrategy(@Nullable Key key,
QueryMethodEvaluationContextProvider evaluationContextProvider, KeyValueOperations keyValueOperations,
Class<? extends AbstractQueryCreator<?, ?>> queryCreator,
Class<? extends RepositoryQuery> repositoryQueryType) {
Assert.notNull(evaluationContextProvider, "EvaluationContextProvider must not be null!");
Assert.notNull(keyValueOperations, "KeyValueOperations must not be null!");
Assert.notNull(queryCreator, "Query creator type must not be null!");
Assert.notNull(repositoryQueryType, "RepositoryQueryType type must not be null!");
this.evaluationContextProvider = evaluationContextProvider;
this.keyValueOperations = keyValueOperations;
this.queryCreator = queryCreator;
this.repositoryQueryType = repositoryQueryType;
}
@Override
@SuppressWarnings("unchecked")
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
NamedQueries namedQueries) {
QueryMethod queryMethod = new QueryMethod(method, metadata, factory);
Constructor<? extends KeyValuePartTreeQuery> constructor = (Constructor<? extends KeyValuePartTreeQuery>) ClassUtils
.getConstructorIfAvailable(this.repositoryQueryType, QueryMethod.class,
QueryMethodEvaluationContextProvider.class, KeyValueOperations.class, Class.class);
Assert.state(constructor != null,
String.format(
"Constructor %s(QueryMethod, EvaluationContextProvider, KeyValueOperations, Class) not available!",
ClassUtils.getShortName(this.repositoryQueryType)));
return BeanUtils.instantiateClass(constructor, queryMethod, evaluationContextProvider, this.keyValueOperations,
this.queryCreator);
}
@Test // DATAKV-137
public void cachedSpelExpressionShouldBeReusedWithNewContext() throws NoSuchMethodException, SecurityException {
QueryMethod qm = new QueryMethod(Repo.class.getMethod("findByFirstname", String.class), metadataMock,
projectionFactoryMock);
KeyValuePartTreeQuery query = new CachingKeyValuePartTreeQuery(qm, QueryMethodEvaluationContextProvider.DEFAULT,
kvOpsMock, SpelQueryCreator.class);
Object[] args = new Object[] { "foo" };
SpelCriteria first = (SpelCriteria) query.prepareQuery(args).getCriteria();
SpelCriteria second = (SpelCriteria) query.prepareQuery(args).getCriteria();
assertThat(first.getExpression()).isSameAs(second.getExpression());
assertThat(first.getContext()).isNotSameAs(second.getContext());
}
@Test // DATAKV-115
@SuppressWarnings({ "unchecked", "rawtypes" })
public void spelExpressionAndContextShouldNotBeReused() throws NoSuchMethodException, SecurityException {
when(metadataMock.getDomainType()).thenReturn((Class) Person.class);
when(metadataMock.getReturnedDomainClass(any(Method.class))).thenReturn((Class) Person.class);
QueryMethod qm = new QueryMethod(Repo.class.getMethod("findByFirstname", String.class), metadataMock,
projectionFactoryMock);
KeyValuePartTreeQuery query = new KeyValuePartTreeQuery(qm, QueryMethodEvaluationContextProvider.DEFAULT, kvOpsMock,
SpelQueryCreator.class);
Object[] args = new Object[] { "foo" };
Object first = query.prepareQuery(args).getCriteria();
Object second = query.prepareQuery(args).getCriteria();
assertThat(first).isNotSameAs(second);
}
@Test // DATAKV-142
@SuppressWarnings({ "unchecked", "rawtypes" })
public void shouldApplyPageableParameterToCollectionQuery() throws SecurityException, NoSuchMethodException {
when(metadataMock.getDomainType()).thenReturn((Class) Person.class);
when(metadataMock.getReturnedDomainClass(any(Method.class))).thenReturn((Class) Person.class);
QueryMethod qm = new QueryMethod(Repo.class.getMethod("findBy", Pageable.class), metadataMock,
projectionFactoryMock);
KeyValuePartTreeQuery partTreeQuery = new KeyValuePartTreeQuery(qm, QueryMethodEvaluationContextProvider.DEFAULT,
kvOpsMock, SpelQueryCreator.class);
KeyValueQuery<?> query = partTreeQuery.prepareQuery(new Object[] { PageRequest.of(2, 3) });
assertThat(query.getOffset()).isEqualTo(6L);
assertThat(query.getRows()).isEqualTo(3);
}
@Test // DATAKV-142
@SuppressWarnings({ "unchecked", "rawtypes" })
public void shouldApplyDerivedMaxResultsToQueryWithParameters() throws SecurityException, NoSuchMethodException {
when(metadataMock.getDomainType()).thenReturn((Class) Person.class);
when(metadataMock.getReturnedDomainClass(any(Method.class))).thenReturn((Class) Person.class);
QueryMethod qm = new QueryMethod(Repo.class.getMethod("findTop3ByFirstname", String.class), metadataMock,
projectionFactoryMock);
KeyValuePartTreeQuery partTreeQuery = new KeyValuePartTreeQuery(qm, QueryMethodEvaluationContextProvider.DEFAULT,
kvOpsMock, SpelQueryCreator.class);
KeyValueQuery<?> query = partTreeQuery.prepareQuery(new Object[] { "firstname" });
assertThat(query.getCriteria()).isInstanceOf(SpelCriteria.class);
assertThat(((SpelCriteria) query.getCriteria()).getExpression().getExpressionString())
.isEqualTo("#it?.firstname?.equals([0])");
assertThat(query.getRows()).isEqualTo(3);
}
/**
* Create a {@link ReactiveStringBasedNeo4jQuery} for a query method that is annotated with {@link Query @Query}. The annotation
* is expected to have a value.
*
* @param neo4jOperations reactive Neo4j operations
* @param mappingContext a Neo4jMappingContext instance
* @param evaluationContextProvider a QueryMethodEvaluationContextProvider instance
* @param queryMethod the query method
* @return A new instance of a String based Neo4j query.
*/
static ReactiveStringBasedNeo4jQuery create(ReactiveNeo4jOperations neo4jOperations, Neo4jMappingContext mappingContext,
QueryMethodEvaluationContextProvider evaluationContextProvider,
Neo4jQueryMethod queryMethod) {
Query queryAnnotation = queryMethod.getQueryAnnotation()
.orElseThrow(() -> new MappingException("Expected @Query annotation on the query method!"));
String cypherTemplate = Optional.ofNullable(queryAnnotation.value())
.filter(StringUtils::hasText)
.orElseThrow(() -> new MappingException("Expected @Query annotation to have a value, but it did not."));
return new ReactiveStringBasedNeo4jQuery(neo4jOperations, mappingContext, evaluationContextProvider, queryMethod,
cypherTemplate, Neo4jQueryType.fromDefinition(queryAnnotation));
}
private ReactiveStringBasedNeo4jQuery(ReactiveNeo4jOperations neo4jOperations,
Neo4jMappingContext mappingContext, QueryMethodEvaluationContextProvider evaluationContextProvider,
Neo4jQueryMethod queryMethod, String cypherTemplate, Neo4jQueryType queryType) {
super(neo4jOperations, mappingContext, queryMethod, queryType);
SpelExtractor spelExtractor = SPEL_QUERY_CONTEXT.parse(cypherTemplate);
this.spelEvaluator = new SpelEvaluator(evaluationContextProvider, queryMethod.getParameters(), spelExtractor);
this.cypherQuery = spelExtractor.getQueryString();
}
/**
* Create a {@link StringBasedNeo4jQuery} for a query method that is annotated with {@link Query @Query}. The annotation
* is expected to have a value.
*
* @param neo4jOperations the Neo4j operations
* @param mappingContext a Neo4jMappingContext instance
* @param evaluationContextProvider a QueryMethodEvaluationContextProvider instance
* @param queryMethod the query method
* @return A new instance of a String based Neo4j query.
*/
static StringBasedNeo4jQuery create(Neo4jOperations neo4jOperations, Neo4jMappingContext mappingContext,
QueryMethodEvaluationContextProvider evaluationContextProvider,
Neo4jQueryMethod queryMethod) {
Query queryAnnotation = queryMethod.getQueryAnnotation()
.orElseThrow(() -> new MappingException("Expected @Query annotation on the query method!"));
String cypherTemplate = Optional.ofNullable(queryAnnotation.value())
.filter(StringUtils::hasText)
.orElseThrow(() -> new MappingException("Expected @Query annotation to have a value, but it did not."));
return new StringBasedNeo4jQuery(neo4jOperations, mappingContext, evaluationContextProvider, queryMethod,
cypherTemplate, Neo4jQueryType.fromDefinition(queryAnnotation));
}
private StringBasedNeo4jQuery(Neo4jOperations neo4jOperations,
Neo4jMappingContext mappingContext, QueryMethodEvaluationContextProvider evaluationContextProvider,
Neo4jQueryMethod queryMethod, String cypherTemplate, Neo4jQueryType queryType) {
super(neo4jOperations, mappingContext, queryMethod, queryType);
SpelExtractor spelExtractor = SPEL_QUERY_CONTEXT.parse(cypherTemplate);
this.spelEvaluator = new SpelEvaluator(evaluationContextProvider, queryMethod.getParameters(), spelExtractor);
this.cypherQuery = spelExtractor.getQueryString();
}
public Neo4jQueryLookupStrategy(Neo4jOperations neo4jOperations,
Neo4jMappingContext mappingContext,
QueryMethodEvaluationContextProvider evaluationContextProvider) {
this.neo4jOperations = neo4jOperations;
this.mappingContext = mappingContext;
this.evaluationContextProvider = evaluationContextProvider;
}
public ReactiveNeo4jQueryLookupStrategy(ReactiveNeo4jOperations neo4jOperations,
Neo4jMappingContext mappingContext,
QueryMethodEvaluationContextProvider evaluationContextProvider) {
this.neo4jOperations = neo4jOperations;
this.mappingContext = mappingContext;
this.evaluationContextProvider = evaluationContextProvider;
}
@Override
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(Key key,
QueryMethodEvaluationContextProvider evaluationContextProvider) {
return Optional
.of(new ReactiveNeo4jQueryLookupStrategy(neo4jOperations, mappingContext, evaluationContextProvider));
}
@Test
void shouldSelectPartTreeNeo4jQuery() {
final Neo4jQueryLookupStrategy lookupStrategy = new Neo4jQueryLookupStrategy(mock(Neo4jOperations.class),
mock(
Neo4jMappingContext.class), QueryMethodEvaluationContextProvider.DEFAULT);
RepositoryQuery query = lookupStrategy
.resolveQuery(queryMethod("findById", Object.class), TEST_REPOSITORY_METADATA, PROJECTION_FACTORY,
namedQueries);
assertThat(query).isInstanceOf(PartTreeNeo4jQuery.class);
}
@Test
void shouldSelectStringBasedNeo4jQuery() {
final Neo4jQueryLookupStrategy lookupStrategy = new Neo4jQueryLookupStrategy(mock(Neo4jOperations.class),
mock(
Neo4jMappingContext.class), QueryMethodEvaluationContextProvider.DEFAULT);
RepositoryQuery query = lookupStrategy
.resolveQuery(queryMethod("annotatedQueryWithValidTemplate"), TEST_REPOSITORY_METADATA,
PROJECTION_FACTORY, namedQueries);
assertThat(query).isInstanceOf(StringBasedNeo4jQuery.class);
}
@Test
void shouldDetectInvalidAnnotation() {
Neo4jQueryMethod method = neo4jQueryMethod("annotatedQueryWithoutTemplate");
assertThatExceptionOfType(MappingException.class)
.isThrownBy(
() -> StringBasedNeo4jQuery.create(mock(Neo4jOperations.class), mock(Neo4jMappingContext.class),
QueryMethodEvaluationContextProvider.DEFAULT, method))
.withMessage("Expected @Query annotation to have a value, but it did not.");
}
@Test
void shouldResolveNamedParameters() {
Neo4jQueryMethod method = RepositoryQueryTest
.neo4jQueryMethod("findByDontDoThisInRealLiveNamed", org.neo4j.driver.types.Point.class, String.class,
String.class);
StringBasedNeo4jQuery repositoryQuery = spy(StringBasedNeo4jQuery.create(mock(Neo4jOperations.class),
mock(Neo4jMappingContext.class), QueryMethodEvaluationContextProvider.DEFAULT,
method));
// skip conversion
doAnswer(invocation -> invocation.getArgument(0)).when(repositoryQuery).convertParameter(any());
Point thePoint = Values.point(4223, 1, 2).asPoint();
Map<String, Object> resolveParameters = repositoryQuery.bindParameters(
new Neo4jParameterAccessor((Neo4jParameters) method.getParameters(),
new Object[] { thePoint, "TheName", "TheFirstName" }));
assertThat(resolveParameters)
.hasSize(8)
.containsEntry("0", thePoint)
.containsEntry("location", thePoint)
.containsEntry("1", "TheName")
.containsEntry("name", "TheName")
.containsEntry("2", "TheFirstName")
.containsEntry("firstName", "TheFirstName")
.containsEntry("__SpEL__0", "TheFirstName")
.containsEntry("__SpEL__1", "TheNameTheFirstName");
}
@Override
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(
QueryLookupStrategy.Key key,
QueryMethodEvaluationContextProvider evaluationContextProvider) {
return Optional.of(new ReactiveCosmosQueryLookupStrategy(cosmosOperations,
evaluationContextProvider));
}
public DatastoreQueryLookupStrategy(DatastoreMappingContext datastoreMappingContext,
DatastoreOperations datastoreOperations,
QueryMethodEvaluationContextProvider evaluationContextProvider) {
Assert.notNull(datastoreMappingContext,
"A non-null DatastoreMappingContext is required.");
Assert.notNull(datastoreOperations,
"A non-null DatastoreOperations is required.");
Assert.notNull(evaluationContextProvider,
"A non-null EvaluationContextProvider is required.");
this.datastoreMappingContext = datastoreMappingContext;
this.evaluationContextProvider = evaluationContextProvider;
this.datastoreOperations = datastoreOperations;
}
/**
* Constructor.
* @param type the underlying entity type
* @param queryMethod the underlying query method to support.
* @param datastoreTemplate used for executing queries.
* @param gql the query text.
* @param evaluationContextProvider the provider used to evaluate SpEL expressions in
* queries.
* @param datastoreMappingContext used for getting metadata about entities.
*/
public GqlDatastoreQuery(Class<T> type, DatastoreQueryMethod queryMethod,
DatastoreOperations datastoreTemplate, String gql,
QueryMethodEvaluationContextProvider evaluationContextProvider,
DatastoreMappingContext datastoreMappingContext) {
super(queryMethod, datastoreTemplate, datastoreMappingContext, type);
this.evaluationContextProvider = evaluationContextProvider;
this.originalGql = StringUtils.trimTrailingCharacter(gql.trim(), ';');
setOriginalParamTags();
setEvaluatingSpelQueryContext();
setGqlResolvedEntityClassName();
}