/** * <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) { 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()) { return StreamUtils.createStreamFromIterator(resultSet.iterator()); } 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, EvaluationContextProvider.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, DefaultEvaluationContextProvider.INSTANCE, 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(), sameInstance(second.getExpression())); assertThat(first.getContext(), not(sameInstance(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(new StandardEvaluationContext(args)); 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, DefaultEvaluationContextProvider.INSTANCE, kvOpsMock, SpelQueryCreator.class); Object[] args = new Object[] { "foo" }; Object first = query.prepareQuery(args).getCriteria(); Object second = query.prepareQuery(args).getCriteria(); assertThat(first, not(sameInstance(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, DefaultEvaluationContextProvider.INSTANCE, kvOpsMock, SpelQueryCreator.class); KeyValueQuery<?> query = partTreeQuery.prepareQuery(new Object[] { PageRequest.of(2, 3) }); assertThat(query.getOffset(), is(6L)); assertThat(query.getRows(), is(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, DefaultEvaluationContextProvider.INSTANCE, kvOpsMock, SpelQueryCreator.class); KeyValueQuery<?> query = partTreeQuery.prepareQuery(new Object[] { "firstname" }); assertThat(query.getCriteria(), is(notNullValue())); assertThat(query.getCriteria(), IsInstanceOf.instanceOf(SpelCriteria.class)); assertThat(((SpelCriteria) query.getCriteria()).getExpression().getExpressionString(), is("#it?.firstname?.equals([0])")); assertThat(query.getRows(), is(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(), new StandardEvaluationContext(args)); }
public JdbcAnnotatedRepositoryQuery(QueryMethod method, NamedParameterJdbcOperations template, String query, RowMapper rowMapper, Strategy strategy, List<String> parametersNames) { this.method = method; this.query = query; this.template = template; this.rowMapper = rowMapper; this.parametersNames = parametersNames; LOGGER.debug("applying strategy {}", strategy.name()); switch (strategy) { case COLLECTION_QUERY: this.strategy = new CollectionQueryJdbcRepositoryStrategy(); break; case COUNT: this.strategy = new CountJdbcRepositoryStrategy(); break; case SINGLE_QUERY: this.strategy = new SingleQueryJdbcRepositoryStrategy(); break; case UPDATE_QUERY: this.strategy = new UpdatetJdbcRepositoryStrategy(); break; case PAGE_QUERY: this.strategy = new PageJdbcRepositoryStrategy(); break; case EXISTS_QUERY: this.strategy = new ExistsJdbcRepositoryStrategy(); break; default: throw new IllegalArgumentException("Unkwnown strategy provided"); } }
public JdbcByNameRepositoryQuery(QueryMethod method, NamedParameterJdbcOperations template, String query, RowMapper rowMapper, LookupStrategy lookupStrategy, List<ParameterProperties> parameterProperties) { this.method = method; this.query = query; this.template = template; this.rowMapper = rowMapper; LOGGER.debug("applying lookupStrategy {}", lookupStrategy.name()); this.strategy = JdbcRepositoryExecutionStrategyFactory.chooseStrategy(lookupStrategy); processMethodParameters(parameterProperties); }
private GcloudDatastoreQueryCreator createCreator(Class<?> repositoryClass, Method method, Object... values) { QueryMethod queryMethod = new QueryMethod(method, new DefaultRepositoryMetadata(repositoryClass), new SpelAwareProxyProjectionFactory()); return new GcloudDatastoreQueryCreator( new PartTree(method.getName(), queryMethod.getResultProcessor().getReturnedType() .getDomainType()), new ParametersParameterAccessor(queryMethod.getParameters(), values), DatastoreOptions.getDefaultInstance()); }
@Override public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory, NamedQueries namedQueries) { QueryMethod queryMethod = new QueryMethod(method, metadata, factory); return new ObjectifyRepositoryQuery(queryMethod); }
/** * 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, EvaluationContextProvider evaluationContextProvider, KeyValueOperations keyValueOperations, Class<? extends AbstractQueryCreator<?, ?>> queryCreator) { super(queryMethod, evaluationContextProvider, keyValueOperations, new VaultQueryCreatorFactory( (MappingContext) keyValueOperations.getMappingContext())); }
/** * <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.getCritieria() == 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, EvaluationContextProvider 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; }
public static ParametersParameterAccessor generateParameters(QueryMethod method) { return new ParametersParameterAccessor(method.getParameters(), new Object[method.getParameters().getNumberOfParameters()]); }
@Override public QueryMethod getQueryMethod() { return method; }
@Override public QueryMethod getQueryMethod() { return new QueryMethod(method , repositoryMetadata,null) ; }
@Override public QueryMethod getQueryMethod() { return queryMethod; }
public ObjectifyRepositoryQuery(QueryMethod queryMethod) { this.queryMethod = 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); }
public CachingKeyValuePartTreeQuery(QueryMethod queryMethod, EvaluationContextProvider 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, DefaultEvaluationContextProvider.INSTANCE, kvOpsMock, SpelQueryCreator.class); KeyValueQuery<?> query = partTreeQuery.prepareQuery(new Object[] {}); assertThat(query.getRows(), is(3)); }
/** * <P> * Create a {@link RepositoryQuery} implementation for each query method defined in a {@link HazelcastRepository}. * </P> * * @param queryMethod Method defined in {@code HazelcastRepository} * @param evalulationContextProvider Not used * @param keyValueOperations Interface to Hazelcast * @param queryCreator Not used */ public HazelcastPartTreeQuery(QueryMethod queryMethod, EvaluationContextProvider evaluationContextProvider, KeyValueOperations keyValueOperations, Class<? extends AbstractQueryCreator<?, ?>> queryCreator) { super(queryMethod, evaluationContextProvider, keyValueOperations, queryCreator); this.queryMethod = queryMethod; this.keyValueOperations = keyValueOperations; this.isRearrangeKnown = false; }
/** * <P> * Execute a "delete" query, not really a query more of an operation. * </P> * <P> * <B>NOTE:</B> Delete is not a collection operation, the return value is a single object that * was deleted. * </P> * <P>Although the <I>find</I> operation returns an iterator, the result set is either empty * or has one domain object in it. If there are multiple possible matches it's random which * one of the matches is deleted. * </P> * * @param query The query to run * @param queryMethod Used here to find the type of object to match the query * @return Query The individual entry deleted */ private Object executeDeleteQuery(final KeyValueQuery<?> query, final QueryMethod queryMethod) { Iterable<?> resultSet = this.keyValueOperations.find(query, queryMethod.getEntityInformation().getJavaType()); Iterator<?> iterator = resultSet.iterator(); if (iterator.hasNext()) { return this.keyValueOperations.delete(iterator.next()); } else { return null; } }
/** * Creates a new {@link KeyValuePartTreeQuery} 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}. */ public KeyValuePartTreeQuery(QueryMethod queryMethod, EvaluationContextProvider evaluationContextProvider, KeyValueOperations keyValueOperations, Class<? extends AbstractQueryCreator<?, ?>> queryCreator) { this(queryMethod, evaluationContextProvider, keyValueOperations, new ConstructorCachingQueryCreatorFactory(queryCreator)); }