diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoCursorUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoCursorUtils.java deleted file mode 100644 index f3f3898c6..000000000 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoCursorUtils.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2010-2011 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 - * - * http://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.document.mongodb.repository; - -import java.util.HashMap; -import java.util.Map; - -import org.springframework.data.document.mongodb.CursorPreparer; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.domain.Sort.Order; - -import com.mongodb.BasicDBObject; -import com.mongodb.DBCursor; - - -/** - * Collection of utility methods to apply sorting and pagination to a - * {@link DBCursor}. - * - * @author Oliver Gierke - */ -abstract class MongoCursorUtils { - - private MongoCursorUtils() { - - } - - /** - * Creates a {@link CursorPreparer} applying the given {@link Pageable} to - * the cursor. - * - * @param pageable - * @return - */ - public static CursorPreparer withPagination(Pageable pageable) { - - return new PaginationCursorPreparer(pageable); - } - - - /** - * Creates a {@link CursorPreparer} to apply the given {@link Sort} to the - * cursor. - * - * @param sort - * @return - */ - public static CursorPreparer withSorting(Sort sort) { - - return new SortingCursorPreparer(sort); - } - - /** - * Applies the given {@link Pageable} to the given {@link DBCursor}. - * - * @author Oliver Gierke - */ - private static class PaginationCursorPreparer implements CursorPreparer { - - private final Pageable pageable; - private final SortingCursorPreparer sortingPreparer; - - - /** - * Creates a new {@link PaginationCursorPreparer}. - * - * @param pageable - */ - public PaginationCursorPreparer(Pageable pageable) { - - this.pageable = pageable; - this.sortingPreparer = - new SortingCursorPreparer(pageable.getSort()); - } - - - /* - * (non-Javadoc) - * - * @see - * org.springframework.data.document.mongodb.CursorPreparer#prepare( - * com.mongodb.DBCursor) - */ - public void prepare(DBCursor cursor) { - - if (pageable == null) { - return; - } - - int toSkip = pageable.getOffset(); - int first = pageable.getPageSize(); - - cursor.limit(first).skip(toSkip); - sortingPreparer.prepare(cursor); - } - } - - /** - * Applies the given {@link Sort} to the given {@link DBCursor}. - * - * @author Oliver Gierke - */ - private static class SortingCursorPreparer implements CursorPreparer { - - private final Sort sort; - - - /** - * Creates a new {@link SortingCursorPreparer}. - * - * @param sort - */ - public SortingCursorPreparer(Sort sort) { - - this.sort = sort; - } - - - /* - * (non-Javadoc) - * - * @see - * org.springframework.data.document.mongodb.CursorPreparer#prepare( - * com.mongodb.DBCursor) - */ - public void prepare(DBCursor cursor) { - - if (sort == null) { - return; - } - - Map sorts = new HashMap(); - - for (Order order : sort) { - sorts.put(order.getProperty(), - Direction.ASC.equals(order.getDirection()) ? 1 : -1); - } - - cursor.sort(new BasicDBObject(sorts)); - } - } -} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQuery.java index 12ab095d6..a195587eb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQuery.java @@ -15,12 +15,13 @@ */ package org.springframework.data.document.mongodb.repository; -import static org.springframework.data.document.mongodb.repository.MongoCursorUtils.*; +import static org.springframework.data.document.mongodb.repository.QueryUtils.*; import java.util.List; import org.springframework.data.document.mongodb.CollectionCallback; import org.springframework.data.document.mongodb.MongoTemplate; +import org.springframework.data.document.mongodb.builder.QuerySpec; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.repository.query.QueryMethod; @@ -75,28 +76,31 @@ public class MongoQuery implements RepositoryQuery { SimpleParameterAccessor accessor = new SimpleParameterAccessor(method.getParameters(), parameters); - MongoQueryCreator creator = new MongoQueryCreator(tree, accessor, template.getConverter()); - DBObject query = creator.createQuery(); + QuerySpec spec = new QuerySpec(); + + MongoQueryCreator creator = + new MongoQueryCreator(spec, tree, accessor, + template.getConverter()); + creator.createQuery(); if (method.isCollectionQuery()) { - return new CollectionExecution().execute(query); + return new CollectionExecution().execute(spec); } else if (method.isPageQuery()) { return new PagedExecution(creator, accessor.getPageable()) - .execute(query); + .execute(spec); } else { - return new SingleEntityExecution().execute(query); + return new SingleEntityExecution().execute(spec); } } private abstract class Execution { - abstract Object execute(DBObject query); + abstract Object execute(QuerySpec query); - protected List readCollection(DBObject query) { + protected List readCollection(QuerySpec query) { - return template.find(template.getDefaultCollectionName(), - query, method.getDomainClass()); + return template.query(query.build(), method.getDomainClass()); } } @@ -115,7 +119,7 @@ public class MongoQuery implements RepositoryQuery { * #execute(com.mongodb.DBObject) */ @Override - public Object execute(DBObject query) { + public Object execute(QuerySpec query) { return readCollection(query); } @@ -155,12 +159,13 @@ public class MongoQuery implements RepositoryQuery { */ @Override @SuppressWarnings({ "rawtypes", "unchecked" }) - Object execute(DBObject query) { + Object execute(QuerySpec query) { + + int count = getCollectionCursor(query.getQueryObject()).count(); - int count = getCollectionCursor(creator.createQuery()).count(); List result = - template.find(query, method.getDomainClass(), - withPagination(pageable)); + template.query(applyPagination(query, pageable), + method.getDomainClass()); return new PageImpl(result, pageable, count); } @@ -193,7 +198,7 @@ public class MongoQuery implements RepositoryQuery { * #execute(com.mongodb.DBObject) */ @Override - Object execute(DBObject query) { + Object execute(QuerySpec query) { List result = readCollection(query); return result.isEmpty() ? null : result.get(0); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java index 36e8f03db..36f54eeac 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java @@ -15,11 +15,16 @@ */ package org.springframework.data.document.mongodb.repository; +import java.util.Arrays; import java.util.regex.Pattern; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.data.document.mongodb.MongoConverter; +import org.springframework.data.document.mongodb.builder.Criteria; +import org.springframework.data.document.mongodb.builder.CriteriaSpec; +import org.springframework.data.document.mongodb.builder.Query; +import org.springframework.data.document.mongodb.builder.QuerySpec; import org.springframework.data.domain.Sort; import org.springframework.data.repository.query.SimpleParameterAccessor; import org.springframework.data.repository.query.SimpleParameterAccessor.BindableParameterIterator; @@ -30,7 +35,6 @@ import org.springframework.data.repository.query.parser.PartTree; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; -import com.mongodb.QueryBuilder; /** @@ -38,10 +42,12 @@ import com.mongodb.QueryBuilder; * * @author Oliver Gierke */ -class MongoQueryCreator extends AbstractQueryCreator { - - private static final Log LOG = LogFactory.getLog(MongoQueryCreator.class); - private final MongoConverter converter; +class MongoQueryCreator extends AbstractQueryCreator { + + private static final Log LOG = LogFactory.getLog(MongoQueryCreator.class); + private final MongoConverter converter; + private final QuerySpec querySpec; + /** * Creates a new {@link MongoQueryCreator} from the given {@link PartTree} @@ -50,9 +56,11 @@ class MongoQueryCreator extends AbstractQueryCreator { * @param tree * @param accessor */ - public MongoQueryCreator(PartTree tree, SimpleParameterAccessor accessor, MongoConverter converter) { + public MongoQueryCreator(QuerySpec querySpec, PartTree tree, + SimpleParameterAccessor accessor, MongoConverter converter) { super(tree, accessor); + this.querySpec = querySpec; this.converter = converter; } @@ -67,10 +75,10 @@ class MongoQueryCreator extends AbstractQueryCreator { * .data.repository.query.SimpleParameterAccessor.BindableParameterIterator) */ @Override - protected QueryBuilder create(Part part, BindableParameterIterator iterator) { + protected CriteriaSpec create(Part part, BindableParameterIterator iterator) { - return from(part.getType(), QueryBuilder.start(part.getProperty().toDotPath()), - iterator); + return from(part.getType(), + querySpec.find(part.getProperty().toDotPath()), iterator); } @@ -84,10 +92,11 @@ class MongoQueryCreator extends AbstractQueryCreator { * .data.repository.query.SimpleParameterAccessor.BindableParameterIterator) */ @Override - protected QueryBuilder and(Part part, QueryBuilder base, + protected CriteriaSpec and(Part part, CriteriaSpec base, BindableParameterIterator iterator) { - return from(part.getType(), base.and(part.getProperty().toDotPath()), iterator); + return from(part.getType(), base.and(part.getProperty().toDotPath()), + iterator); } @@ -95,13 +104,13 @@ class MongoQueryCreator extends AbstractQueryCreator { * (non-Javadoc) * * @see - * org.springframework.data.document.mongodb.repository.AbstractQueryCreator - * #reduceCriterias(java.lang.Object, java.lang.Object) + * org.springframework.data.repository.query.parser.AbstractQueryCreator + * #or(java.lang.Object, java.lang.Object) */ @Override - protected QueryBuilder or(QueryBuilder base, QueryBuilder criteria) { + protected CriteriaSpec or(CriteriaSpec base, CriteriaSpec criteria) { - base.or(criteria.get()); + base.or(Arrays.asList(criteria.build())); return base; } @@ -110,19 +119,19 @@ class MongoQueryCreator extends AbstractQueryCreator { * (non-Javadoc) * * @see - * org.springframework.data.document.mongodb.repository.AbstractQueryCreator - * #finalize(java.lang.Object) + * org.springframework.data.repository.query.parser.AbstractQueryCreator + * #complete(java.lang.Object, org.springframework.data.domain.Sort) */ @Override - protected DBObject complete(QueryBuilder criteria, Sort sort) { + protected Void complete(CriteriaSpec criteria, Sort sort) { - DBObject query = criteria.get(); - - if (LOG.isDebugEnabled()) { - LOG.debug("Created query " + query); - } - - return query; + Query query = criteria.build(); + + if (LOG.isDebugEnabled()) { + LOG.debug("Created query " + query); + } + + return null; } @@ -134,38 +143,39 @@ class MongoQueryCreator extends AbstractQueryCreator { * @param parameters * @return */ - private QueryBuilder from(Type type, QueryBuilder criteria, + private CriteriaSpec from(Type type, CriteriaSpec criteria, BindableParameterIterator parameters) { switch (type) { case GREATER_THAN: - return criteria.greaterThan(getConvertedParameter(parameters)); + return criteria.gt(getConvertedParameter(parameters)); case LESS_THAN: - return criteria.lessThan(getConvertedParameter(parameters)); + return criteria.lt(getConvertedParameter(parameters)); case BETWEEN: - return criteria.greaterThan(getConvertedParameter(parameters)).lessThan(getConvertedParameter(parameters)); + return criteria.gt(getConvertedParameter(parameters)).lt( + getConvertedParameter(parameters)); case IS_NOT_NULL: - return criteria.notEquals(null); + return criteria.not().is(null); case IS_NULL: return criteria.is(null); case LIKE: String value = parameters.next().toString(); - return criteria.regex(toLikeRegex(value)); + return criteria.is(toLikeRegex(value)); case SIMPLE_PROPERTY: return criteria.is(getConvertedParameter(parameters)); case NEGATING_SIMPLE_PROPERTY: - return criteria.notEquals(getConvertedParameter(parameters)); + return criteria.not().is(getConvertedParameter(parameters)); } throw new IllegalArgumentException("Unsupported keyword!"); } - - + + private Object getConvertedParameter(BindableParameterIterator parameters) { - - DBObject result = new BasicDBObject(); - converter.write(new ValueHolder(parameters.next()), result); - return result.get("value"); + + DBObject result = new BasicDBObject(); + converter.write(new ValueHolder(parameters.next()), result); + return result.get("value"); } @@ -175,22 +185,27 @@ class MongoQueryCreator extends AbstractQueryCreator { return Pattern.compile(regex); } - /** - * Simple value holder class to allow conversion and accessing the converted value in a deterministic way. - * - * @author Oliver Gierke - */ + /** + * Simple value holder class to allow conversion and accessing the converted + * value in a deterministic way. + * + * @author Oliver Gierke + */ private static class ValueHolder { - - private Object value; - - public ValueHolder(Object value) { - this.value = value; - } - - @SuppressWarnings("unused") - public Object getValue() { - return value; - } + + private Object value; + + + public ValueHolder(Object value) { + + this.value = value; + } + + + @SuppressWarnings("unused") + public Object getValue() { + + return value; + } } } \ No newline at end of file diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/QueryUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/QueryUtils.java new file mode 100644 index 000000000..d2411d152 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/QueryUtils.java @@ -0,0 +1,78 @@ +/* + * Copyright 2010-2011 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 + * + * http://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.document.mongodb.repository; + +import org.springframework.data.document.mongodb.builder.QuerySpec; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; + +import com.mongodb.DBCursor; + + +/** + * Collection of utility methods to apply sorting and pagination to a + * {@link DBCursor}. + * + * @author Oliver Gierke + */ +abstract class QueryUtils { + + private QueryUtils() { + + } + + + /** + * Applies the given {@link Pageable} to the given {@link QuerySpec}. Will + * do nothing if {@link Pageable} is {@literal null}. + * + * @param spec + * @param pageable + * @return + */ + public static QuerySpec applyPagination(QuerySpec spec, Pageable pageable) { + + if (pageable == null) { + return spec; + } + + spec.limit(pageable.getPageSize()); + // spec.skip(pageable.getOffset()); + + return applySorting(spec, pageable.getSort()); + } + + + /** + * Applies the given {@link Sort} to the {@link QuerySpec}. Will do nothing + * if {@link Sort} is {@literal null}. + * + * @param spec + * @param sort + * @return + */ + public static QuerySpec applySorting(QuerySpec spec, Sort sort) { + + if (sort == null) { + return spec; + } + + // TODO apply sorting + // spec. + + return spec; + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/SimpleMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/SimpleMongoRepository.java index cbf73598b..4dd7c4cf3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/SimpleMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/SimpleMongoRepository.java @@ -15,14 +15,14 @@ */ package org.springframework.data.document.mongodb.repository; -import static org.springframework.data.document.mongodb.repository.MongoCursorUtils.*; - import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import org.bson.types.ObjectId; import org.springframework.data.document.mongodb.MongoConverter; import org.springframework.data.document.mongodb.MongoTemplate; +import org.springframework.data.document.mongodb.builder.QuerySpec; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; @@ -32,7 +32,6 @@ import org.springframework.data.repository.support.IsNewAware; import org.springframework.data.repository.support.RepositorySupport; import org.springframework.util.Assert; -import com.mongodb.BasicDBObject; import com.mongodb.QueryBuilder; @@ -55,8 +54,7 @@ public class SimpleMongoRepository extends * @param domainClass * @param template */ - public SimpleMongoRepository(Class domainClass, - MongoTemplate template) { + public SimpleMongoRepository(Class domainClass, MongoTemplate template) { super(domainClass); @@ -105,12 +103,16 @@ public class SimpleMongoRepository extends * ) */ public T findById(ID id) { - - MongoConverter converter = template.getConverter(); - - List result = template.find(QueryBuilder.start("_id").is(converter.convertObjectId(id)).get(), - getDomainClass()); - return result.isEmpty() ? null : result.get(0); + + MongoConverter converter = template.getConverter(); + + ObjectId objectId = converter.convertObjectId(id); + + List result = + template.query( + new QuerySpec().find("_id").is(objectId).build(), + getDomainClass()); + return result.isEmpty() ? null : result.get(0); } @@ -200,10 +202,11 @@ public class SimpleMongoRepository extends public Page findAll(final Pageable pageable) { Long count = count(); + QuerySpec spec = new QuerySpec(); List list = - template.find(new BasicDBObject(), getDomainClass(), - withPagination(pageable)); + template.query(QueryUtils.applyPagination(spec, pageable), + getDomainClass()); return new PageImpl(list, pageable, count); } @@ -218,8 +221,8 @@ public class SimpleMongoRepository extends */ public List findAll(final Sort sort) { - return template.find(new BasicDBObject(), getDomainClass(), - withSorting(sort)); + QuerySpec query = QueryUtils.applySorting(new QuerySpec(), sort); + return template.query(query, getDomainClass()); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java index 942d0ebe4..9a10cf72b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java @@ -25,6 +25,7 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.data.document.mongodb.MongoConverter; import org.springframework.data.document.mongodb.Person; +import org.springframework.data.document.mongodb.builder.QuerySpec; import org.springframework.data.repository.query.Parameters; import org.springframework.data.repository.query.SimpleParameterAccessor; import org.springframework.data.repository.query.parser.PartTree; @@ -40,7 +41,7 @@ public class MongoQueryCreatorUnitTests { Method findByFirstname; Method findByFirstnameAndFriend; - + @Mock MongoConverter converter; @@ -63,16 +64,18 @@ public class MongoQueryCreatorUnitTests { PartTree tree = new PartTree("findByFirstName", Person.class); MongoQueryCreator creator = - new MongoQueryCreator(tree, new SimpleParameterAccessor( - new Parameters(findByFirstname), - new Object[] { "Oliver" }), converter); + new MongoQueryCreator(new QuerySpec(), tree, + new SimpleParameterAccessor(new Parameters( + findByFirstname), new Object[] { "Oliver" }), + converter); creator.createQuery(); creator = - new MongoQueryCreator(new PartTree("findByFirstNameAndFriend", - Person.class), new SimpleParameterAccessor( - new Parameters(findByFirstnameAndFriend), new Object[] { + new MongoQueryCreator(new QuerySpec(), new PartTree( + "findByFirstNameAndFriend", Person.class), + new SimpleParameterAccessor(new Parameters( + findByFirstnameAndFriend), new Object[] { "Oliver", new Person() }), converter); creator.createQuery(); }