下面列出了org.springframework.data.domain.SliceImpl#org.springframework.data.repository.query.QueryMethod 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private <T extends Parameter> int getDynamicQueryConfigurationIndex(QueryMethod method) {
Iterator<T> it = (Iterator<T>)method.getParameters().iterator();
int i = 0;
boolean found = false;
int index = -1;
while (it.hasNext()) {
T parameter = it.next();
if (DynamicQueryConfig.class.isAssignableFrom(parameter.getType())) {
if (found) {
throw new IllegalStateException("Invalid '" + method.getName() + "' repository method signature. "
+ "Only ONE DynamicQueryConfig parameter is allowed");
}
found = true;
index = i;
}
i++;
}
return index;
}
private <T extends Parameter> int getDynamicQueryConfigurationIndex(QueryMethod method) {
Iterator<T> it = (Iterator<T>)method.getParameters().iterator();
int i = 0;
boolean found = false;
int index = -1;
while (it.hasNext()) {
T parameter = it.next();
if (DynamicQueryConfig.class.isAssignableFrom(parameter.getType())) {
if (found) {
throw new IllegalStateException("Invalid '" + method.getName() + "' repository method signature. "
+ "Only ONE DynamicQueryConfig parameter is allowed");
}
found = true;
index = i;
}
i++;
}
return index;
}
/**
* Execute a "delete" query, not really a query more of an operation.
* <p>
*
* @param query The query to run
* @param queryMethod Used here to find the type of object to match the query
* @return Collection of deleted objects or the number of deleted objects
*/
private Object executeDeleteQuery(final KeyValueQuery<?> query, final QueryMethod queryMethod) {
Iterable<?> resultSet = this.keyValueOperations.find(query, queryMethod.getEntityInformation().getJavaType());
Iterator<?> iterator = resultSet.iterator();
List<Object> result = new ArrayList<>();
while (iterator.hasNext()) {
result.add(this.keyValueOperations.delete(iterator.next()));
}
if (queryMethod.isCollectionQuery()) {
return result;
} else if (long.class.equals(queryMethod.getReturnedObjectType()) || Long.class
.equals(queryMethod.getReturnedObjectType())) {
return result.size();
} else {
throw new UnsupportedOperationException(String.format(
"Illegal returned type: %s. The operation 'deleteBy' accepts only 'long' and 'Collection' as the returned "
+ "object type", queryMethod.getReturnedObjectType()));
}
}
/**
* <p>
* Execute a retrieval query. The query engine will return this in an iterator, which may need conversion to a single
* domain entity or a stream.
* </P>
*
* @param query The query to run
* @param queryMethod Holds metadata about the query, is paging etc
* @return Query result
*/
private Object executeFindQuery(final KeyValueQuery<?> query, final QueryMethod queryMethod, final boolean distinct) {
Iterable<?> resultSet = this.keyValueOperations.find(query, queryMethod.getEntityInformation().getJavaType());
if (!queryMethod.isCollectionQuery() && !queryMethod.isPageQuery() && !queryMethod.isSliceQuery() && !queryMethod
.isStreamQuery()) {
// Singleton result
return resultSet.iterator().hasNext() ? resultSet.iterator().next() : null;
}
if (queryMethod.isStreamQuery()) {
if (distinct) {
return StreamUtils.createStreamFromIterator(resultSet.iterator()).distinct();
}
return StreamUtils.createStreamFromIterator(resultSet.iterator());
}
if (distinct) {
return StreamUtils.createStreamFromIterator(resultSet.iterator()).distinct().collect(Collectors.toList());
}
return resultSet;
}
@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());
}
private KeyValueQuery<SpelExpression> createQueryForMethodWithArgs(String methodName, Object... args)
throws NoSuchMethodException, SecurityException {
Class<?>[] argTypes = new Class<?>[args.length];
if (!ObjectUtils.isEmpty(args)) {
for (int i = 0; i < args.length; i++) {
argTypes[i] = args[i].getClass();
}
}
Method method = PersonRepository.class.getMethod(methodName, argTypes);
doReturn(Person.class).when(metadataMock).getReturnedDomainClass(method);
PartTree partTree = new PartTree(method.getName(), method.getReturnType());
SpelQueryCreator creator = new SpelQueryCreator(partTree, new ParametersParameterAccessor(
new QueryMethod(method, metadataMock, new SpelAwareProxyProjectionFactory()).getParameters(), args));
KeyValueQuery<SpelExpression> q = creator.createQuery();
q.getCriteria().setEvaluationContext(
SimpleEvaluationContext.forReadOnlyDataBinding().withRootObject(args).withInstanceMethods().build());
return q;
}
@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);
}
private static SpelCriteria createQueryForMethodWithArgs(String methodName, Object... args) throws Exception {
List<Class<?>> types = new ArrayList<>(args.length);
for (Object arg : args) {
types.add(arg.getClass());
}
Method method = PersonRepository.class.getMethod(methodName, types.toArray(new Class<?>[types.size()]));
RepositoryMetadata metadata = mock(RepositoryMetadata.class);
doReturn(method.getReturnType()).when(metadata).getReturnedDomainClass(method);
PartTree partTree = new PartTree(method.getName(), method.getReturnType());
SpelQueryCreator creator = new SpelQueryCreator(partTree, new ParametersParameterAccessor(
new QueryMethod(method, metadata, new SpelAwareProxyProjectionFactory()).getParameters(), args));
return new SpelCriteria(creator.createQuery().getCriteria(),
SimpleEvaluationContext.forReadOnlyDataBinding().withInstanceMethods().withRootObject(args).build());
}
/**
* <p>
* Slices and pages are similar ways to iterate through the result set in blocks, mimicking a cursor. A
* {@link org.springframework.data.domain.Slice Slice} is a simpler concept, only requiring to know if further blocks
* of data are available. A {@link org.springframework.data.domain.Page Page} requires to know how many blocks of data
* are available in total.
* </P>
*
* @param parameters For the query
* @param query The query to run
* @param queryMethod Holds metadata about the query
* @return Query result
*/
@SuppressWarnings({"rawtypes", "unchecked"})
private Object executePageSliceQuery(final Object[] parameters, final KeyValueQuery<?> query, final QueryMethod queryMethod) {
long totalElements = -1;
int indexOfPageRequest = queryMethod.getParameters().getPageableIndex();
Pageable pageRequest = (Pageable) parameters[indexOfPageRequest];
/* TODO Eliminate count call for Slice, retrieve "rows+1" instead to determine if next page exists.
*/
if (query.getCriteria() == null) {
totalElements = this.keyValueOperations.count(queryMethod.getEntityInformation().getJavaType());
} else {
totalElements = this.keyValueOperations.count(query, queryMethod.getEntityInformation().getJavaType());
}
int requiredRows = pageRequest.getPageSize();
query.setOffset(pageRequest.getOffset());
query.setRows(pageRequest.getPageSize());
Iterable<?> resultSet = this.keyValueOperations.find(query, queryMethod.getEntityInformation().getJavaType());
List<?> content = IterableConverter.toList(resultSet);
if (queryMethod.isPageQuery()) {
return new PageImpl(content, pageRequest, totalElements);
} else {
boolean hasNext = totalElements > (query.getOffset() + query.getRows());
if (content.size() > requiredRows) {
content = content.subList(0, requiredRows);
}
return new SliceImpl(content, pageRequest, hasNext);
}
}
/**
* Creates a new {@link KeyValuePartTreeQuery} for the given {@link QueryMethod}, {@link EvaluationContextProvider},
* {@link KeyValueOperations} using the given {@link QueryCreatorFactory} producing the {@link AbstractQueryCreator}
* in charge of altering the query.
*
* @param queryMethod must not be {@literal null}.
* @param evaluationContextProvider must not be {@literal null}.
* @param keyValueOperations must not be {@literal null}.
* @param queryCreatorFactory must not be {@literal null}.
* @since 2.0
*/
public KeyValuePartTreeQuery(QueryMethod queryMethod, QueryMethodEvaluationContextProvider evaluationContextProvider,
KeyValueOperations keyValueOperations, QueryCreatorFactory queryCreatorFactory) {
Assert.notNull(queryMethod, "Query method must not be null!");
Assert.notNull(evaluationContextProvider, "EvaluationContextprovider must not be null!");
Assert.notNull(keyValueOperations, "KeyValueOperations must not be null!");
Assert.notNull(queryCreatorFactory, "QueryCreatorFactory type must not be null!");
this.queryMethod = queryMethod;
this.keyValueOperations = keyValueOperations;
this.evaluationContextProvider = evaluationContextProvider;
this.queryCreatorFactory = queryCreatorFactory;
}
@Override
public QueryMethod getQueryMethod() {
return this.queryMethod;
}
@Override
public QueryMethod getQueryMethod() {
return this.queryMethod;
}
@Override
public QueryMethod getQueryMethod() {
return this.queryMethod;
}
Class<?> getEntityType(QueryMethod queryMethod) {
return queryMethod.getResultProcessor().getReturnedType().getDomainType();
}
Class<?> getEntityType(QueryMethod queryMethod) {
return queryMethod.getResultProcessor().getReturnedType().getDomainType();
}
@Override
public QueryMethod getQueryMethod() {
return this.queryMethod;
}
@Override
public QueryMethod getQueryMethod() {
return query.getQueryMethod();
}
@Override
public QueryMethod getQueryMethod() {
return new QueryMethod(method , repositoryMetadata) ;
}
/** {@inheritDoc} */
@Override public QueryMethod getQueryMethod() {
return new QueryMethod(mtd, metadata, factory);
}
/** {@inheritDoc} */
@Override public QueryMethod getQueryMethod() {
return new QueryMethod(mtd, metadata, factory);
}
/** {@inheritDoc} */
@Override public QueryMethod getQueryMethod() {
return new QueryMethod(mtd, metadata, factory);
}
@Override
public QueryMethod getQueryMethod() {
return queryMethod;
}
@Override
public QueryMethod getQueryMethod() {
return queryMethod;
}
public CachingKeyValuePartTreeQuery(QueryMethod queryMethod,
QueryMethodEvaluationContextProvider evaluationContextProvider, KeyValueOperations keyValueOperations,
Class<? extends AbstractQueryCreator<?, ?>> queryCreator) {
super(queryMethod, evaluationContextProvider, keyValueOperations, queryCreator);
}
@Test // DATAKV-142
@SuppressWarnings({ "unchecked", "rawtypes" })
public void shouldApplyDerivedMaxResultsToQuery() 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("findTop3By"), metadataMock, projectionFactoryMock);
KeyValuePartTreeQuery partTreeQuery = new KeyValuePartTreeQuery(qm, QueryMethodEvaluationContextProvider.DEFAULT,
kvOpsMock, SpelQueryCreator.class);
KeyValueQuery<?> query = partTreeQuery.prepareQuery(new Object[] {});
assertThat(query.getRows()).isEqualTo(3);
}
@Override
public QueryMethod getQueryMethod() {
return method;
}
/**
* Creates a new {@link VaultPartTreeQuery} for the given {@link QueryMethod},
* {@link EvaluationContextProvider}, {@link KeyValueOperations} and query creator
* type.
* @param queryMethod must not be {@literal null}.
* @param evaluationContextProvider must not be {@literal null}.
* @param keyValueOperations must not be {@literal null}.
* @param queryCreator must not be {@literal null}.
*/
@SuppressWarnings("unchecked")
public VaultPartTreeQuery(QueryMethod queryMethod, QueryMethodEvaluationContextProvider evaluationContextProvider,
KeyValueOperations keyValueOperations, Class<? extends AbstractQueryCreator<?, ?>> queryCreator) {
super(queryMethod, evaluationContextProvider, keyValueOperations,
new VaultQueryCreatorFactory((MappingContext) keyValueOperations.getMappingContext()));
}