diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CursorPreparer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CursorPreparer.java index a470db656..659820946 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CursorPreparer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CursorPreparer.java @@ -22,7 +22,7 @@ import com.mongodb.DBCursor; * * @author Oliver Gierke */ -public interface CursorPreparer { +interface CursorPreparer { /** * Prepare the given cursor (apply limits, skips and so on). Returns th eprepared cursor. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java index a13ef6350..d670b1499 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java @@ -91,18 +91,6 @@ public interface MongoOperations { */ void executeQuery(Query query, String collectionName, DocumentCallbackHandler dch); - /** - * Execute a MongoDB query and iterate over the query results on a per-document basis with a DocumentCallbackHandler using the - * provided CursorPreparer. - * @param query the query class that specifies the criteria used to find a record and also an optional fields - * specification - * @param collectionName name of the collection to retrieve the objects from - * @param dch the handler that will extract results, one document at a time - * @param preparer allows for customization of the DBCursor used when iterating over the result set, (apply limits, - * skips and so on). - */ - void executeQuery(Query query, String collectionName, DocumentCallbackHandler dch, CursorPreparer preparer); - /** * Executes a {@link DbCallback} translating any exceptions as necessary. *

@@ -271,7 +259,7 @@ public interface MongoOperations { /** - * Execute a group operation over the entire collection. + * Execute a group operation over the entire collection. * The group operation entity class should match the 'shape' of the returned object that takes int account the * initial document structure as well as any finalize functions. * @@ -281,7 +269,7 @@ public interface MongoOperations { * @param entityClass The parameterized type of the returned list * @return The results of the group operation */ - GroupByResults group(String inputCollectionName, GroupBy groupBy, Class entityClass); + GroupByResults group(String inputCollectionName, GroupBy groupBy, Class entityClass); /** * Execute a group operation restricting the rows to those which match the provided Criteria. @@ -452,26 +440,6 @@ public interface MongoOperations { */ List find(Query query, Class entityClass, String collectionName); - /** - * Map the results of an ad-hoc query on the specified collection to a List of the specified type. - *

- * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless - * configured otherwise, an instance of SimpleMongoConverter will be used. - *

- * The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more - * feature rich {@link Query}. - * - * @param query the query class that specifies the criteria used to find a record and also an optional fields - * specification - * @param entityClass the parameterized type of the returned list. - * @param preparer allows for customization of the DBCursor used when iterating over the result set, (apply limits, - * skips and so on). - * @param collectionName name of the collection to retrieve the objects from - * - * @return the List of converted objects. - */ - List find(Query query, Class entityClass, CursorPreparer preparer, String collectionName); - /** * Returns a document with the given id mapped onto the given class. The collection the query is ran against will be * derived from the given target class as well. @@ -647,7 +615,7 @@ public interface MongoOperations { void save(Object objectToSave, String collectionName); /** - * Performs an upsert. If no document is found that matches the query, a new document is created and inserted + * Performs an upsert. If no document is found that matches the query, a new document is created and inserted * by combining the query document and the update document. * * @param query the query document that specifies the criteria used to select a record to be upserted @@ -659,7 +627,7 @@ public interface MongoOperations { /** - * Performs an upsert. If no document is found that matches the query, a new document is created and inserted + * Performs an upsert. If no document is found that matches the query, a new document is created and inserted * by combining the query document and the update document. * * @param query the query document that specifies the criteria used to select a record to be updated diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java index f7cc8d579..eaabab3d5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java @@ -2,6 +2,8 @@ * Copyright 2010-2011 the original author or authors. * * Licensed under t +import org.springframework.util.ResourceUtils; + import org.springframework.data.convert.EntityReader; he Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -125,7 +127,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { * the DB or Collection. */ private WriteConcern writeConcern = null; - + private WriteConcernResolver writeConcernResolver = new DefaultWriteConcernResolver(); /* @@ -135,7 +137,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { private WriteResultChecking writeResultChecking = WriteResultChecking.NONE; /** - * Set the ReadPreference when operating on a collection. See {@link #prepareCollection(DBCollection)} + * Set the ReadPreference when operating on a collection. See {@link #prepareCollection(DBCollection)} */ private ReadPreference readPreference = null; @@ -187,11 +189,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { * @param mongoConverter */ public MongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter mongoConverter) { + Assert.notNull(mongoDbFactory); this.mongoDbFactory = mongoDbFactory; this.mongoConverter = mongoConverter == null ? getDefaultMongoConverter(mongoDbFactory) : mongoConverter; - this.mapper = new QueryMapper(this.mongoConverter.getConversionService()); + this.mapper = new QueryMapper(this.mongoConverter); // We always have a mapping context in the converter, whether it's a simple one or not mappingContext = this.mongoConverter.getMappingContext(); @@ -233,9 +236,11 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { public void setWriteConcernResolver(WriteConcernResolver writeConcernResolver) { this.writeConcernResolver = writeConcernResolver; } - + /** - * Used by @{link {@link #prepareCollection(DBCollection)} to set the {@link ReadPreference} before any operations are performed. + * Used by @{link {@link #prepareCollection(DBCollection)} to set the {@link ReadPreference} before any operations are + * performed. + * * @param readPreference */ public void setReadPreference(ReadPreference readPreference) { @@ -307,16 +312,32 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { } public void executeQuery(Query query, String collectionName, DocumentCallbackHandler dch) { - executeQuery(query, collectionName, dch, null); + executeQuery(query, collectionName, dch, new QueryCursorPreparer(query)); } - public void executeQuery(Query query, String collectionName, DocumentCallbackHandler dch, CursorPreparer preparer) { + /** + * Execute a MongoDB query and iterate over the query results on a per-document basis with a + * {@link DocumentCallbackHandler} using the provided CursorPreparer. + * + * @param query the query class that specifies the criteria used to find a record and also an optional fields + * specification, must not be {@literal null}. + * @param collectionName name of the collection to retrieve the objects from + * @param dch the handler that will extract results, one document at a time + * @param preparer allows for customization of the {@link DBCursor} used when iterating over the result set, (apply + * limits, skips and so on). + */ + protected void executeQuery(Query query, String collectionName, DocumentCallbackHandler dch, CursorPreparer preparer) { + + Assert.notNull(query); + DBObject queryObject = query.getQueryObject(); DBObject fieldsObject = query.getFieldsObject(); + if (LOGGER.isDebugEnabled()) { LOGGER.debug("find using query: " + queryObject + " fields: " + fieldsObject + " in collection: " + collectionName); } + this.executeQueryInternal(new FindCallback(queryObject, fieldsObject), preparer, dch, collectionName); } @@ -456,36 +477,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { } public List find(final Query query, Class entityClass, String collectionName) { - CursorPreparer cursorPreparer = null; - if (query.getSkip() > 0 || query.getLimit() > 0 || query.getSortObject() != null) { - cursorPreparer = new CursorPreparer() { - - public DBCursor prepare(DBCursor cursor) { - DBCursor cursorToUse = cursor; - try { - if (query.getSkip() > 0) { - cursorToUse = cursorToUse.skip(query.getSkip()); - } - if (query.getLimit() > 0) { - cursorToUse = cursorToUse.limit(query.getLimit()); - } - if (query.getSortObject() != null) { - cursorToUse = cursorToUse.sort(query.getSortObject()); - } - } catch (RuntimeException e) { - throw potentiallyConvertRuntimeException(e); - } - return cursorToUse; - } - }; - } + CursorPreparer cursorPreparer = query == null ? null : new QueryCursorPreparer(query); return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), entityClass, cursorPreparer); } - public List find(Query query, Class entityClass, CursorPreparer preparer, String collectionName) { - return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), entityClass, preparer); - } - public T findById(Object id, Class entityClass) { MongoPersistentEntity persistentEntity = mappingContext.getPersistentEntity(entityClass); return findById(id, entityClass, persistentEntity.getCollection()); @@ -542,7 +537,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { return doFindAndModify(collectionName, query.getQueryObject(), query.getFieldsObject(), query.getSortObject(), entityClass, update, options); } - + // Find methods that take a Query to express the query and that return a single object that is also removed from the // collection in the database. @@ -563,13 +558,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { public long count(final Query query, String collectionName) { return count(query, null, collectionName); } - + private long count(Query query, Class entityClass, String collectionName) { - + Assert.hasText(collectionName); final DBObject dbObject = query == null ? null : mapper.getMappedObject(query.getQueryObject(), entityClass == null ? null : mappingContext.getPersistentEntity(entityClass)); - + return execute(collectionName, new CollectionCallback() { public Long doInCollection(DBCollection collection) throws MongoException, DataAccessException { return collection.count(dbObject); @@ -729,7 +724,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { } return execute(collectionName, new CollectionCallback() { public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException { - MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.INSERT, collectionName, entityClass, dbDoc, null); + MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.INSERT, collectionName, + entityClass, dbDoc, null); WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); if (writeConcernToUse == null) { collection.insert(dbDoc); @@ -751,7 +747,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { } execute(collectionName, new CollectionCallback() { public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException { - MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.INSERT_LIST, collectionName, null, null, null); + MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.INSERT_LIST, collectionName, null, + null, null); WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); if (writeConcernToUse == null) { collection.insert(dbDocList); @@ -781,7 +778,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { } return execute(collectionName, new CollectionCallback() { public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException { - MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.SAVE, collectionName, entityClass, dbDoc, null); + MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.SAVE, collectionName, entityClass, + dbDoc, null); WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); if (writeConcernToUse == null) { collection.save(dbDoc); @@ -793,15 +791,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { }); } - public WriteResult upsert(Query query, Update update, Class entityClass) { return doUpdate(determineCollectionName(entityClass), query, update, entityClass, true, false); } - + public WriteResult upsert(Query query, Update update, String collectionName) { return doUpdate(collectionName, query, update, null, true, false); } - + public WriteResult updateFirst(Query query, Update update, Class entityClass) { return doUpdate(determineCollectionName(entityClass), query, update, entityClass, false, false); } @@ -840,7 +837,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { } WriteResult wr; - MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName, entityClass, updateObj, queryObj); + MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName, + entityClass, updateObj, queryObj); WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); if (writeConcernToUse == null) { wr = collection.update(queryObj, updateObj, upsert, multi); @@ -861,18 +859,18 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { remove(getIdQueryFor(object), object.getClass()); } - + public void remove(Object object, String collection) { - + Assert.hasText(collection); - + if (object == null) { return; } - + remove(getIdQueryFor(object), collection); } - + /** * Returns a {@link Query} for the given entity by its id. * @@ -880,9 +878,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { * @return */ private Query getIdQueryFor(Object object) { - + Assert.notNull(object); - + MongoPersistentEntity entity = mappingContext.getPersistentEntity(object.getClass()); MongoPersistentProperty idProp = entity.getIdProperty(); @@ -894,10 +892,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { Object idProperty = null; try { - + idProperty = BeanWrapper.create(object, service).getProperty(idProp, Object.class, true); return new Query(where(idProp.getFieldName()).is(idProperty)); - + } catch (IllegalAccessException e) { throw new MappingException(e.getMessage(), e); } catch (InvocationTargetException e) { @@ -920,7 +918,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException { DBObject dboq = mapper.getMappedObject(queryObject, entity); WriteResult wr = null; - MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.REMOVE, collectionName, entityClass, null, queryObject); + MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.REMOVE, collectionName, + entityClass, null, queryObject); WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); if (LOGGER.isDebugEnabled()) { LOGGER.debug("remove using query: " + queryObject + " in collection: " + collection.getName()); @@ -1012,28 +1011,30 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { return mapReduceResult; } - + public GroupByResults group(String inputCollectionName, GroupBy groupBy, Class entityClass) { return group(null, inputCollectionName, groupBy, entityClass); } - - public GroupByResults group(Criteria criteria, String inputCollectionName, GroupBy groupBy, Class entityClass) { - + + public GroupByResults group(Criteria criteria, String inputCollectionName, GroupBy groupBy, + Class entityClass) { + DBObject dbo = groupBy.getGroupByObject(); dbo.put("ns", inputCollectionName); - + if (criteria == null) { dbo.put("cond", null); } else { dbo.put("cond", criteria.getCriteriaObject()); } - //If initial document was a JavaScript string, potentially loaded by Spring's Resource abstraction, load it and convert to DBObject - + // If initial document was a JavaScript string, potentially loaded by Spring's Resource abstraction, load it and + // convert to DBObject + if (dbo.containsField("initial")) { Object initialObj = dbo.get("initial"); if (initialObj instanceof String) { - String initialAsString = replaceWithResourceIfNecessary((String)initialObj); - dbo.put("initial", JSON.parse(initialAsString)); + String initialAsString = replaceWithResourceIfNecessary((String) initialObj); + dbo.put("initial", JSON.parse(initialAsString)); } } @@ -1046,16 +1047,16 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { if (dbo.containsField("finalize")) { dbo.put("finalize", replaceWithResourceIfNecessary(dbo.get("finalize").toString())); } - + DBObject commandObject = new BasicDBObject("group", dbo); - + if (LOGGER.isDebugEnabled()) { LOGGER.debug("Executing Group with DBObject [" + commandObject.toString() + "]"); } CommandResult commandResult = null; try { - commandResult = executeCommand(commandObject, getDb().getOptions()); - commandResult.throwOnError(); + commandResult = executeCommand(commandObject, getDb().getOptions()); + commandResult.throwOnError(); } catch (RuntimeException ex) { this.potentiallyConvertRuntimeException(ex); } @@ -1068,10 +1069,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Group command result = [" + commandResult + "]"); } - + @SuppressWarnings("unchecked") - Iterable resultSet = (Iterable) commandResult.get( "retval" ); - + Iterable resultSet = (Iterable) commandResult.get("retval"); + List mappedResults = new ArrayList(); DbObjectCallback callback = new ReadDbObjectCallback(mongoConverter, entityClass); for (DBObject dbObject : resultSet) { @@ -1079,7 +1080,6 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { } GroupByResults groupByResult = new GroupByResults(mappedResults, commandResult); return groupByResult; - } @@ -1298,30 +1298,28 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { return executeFindOneInternal(new FindAndRemoveCallback(mapper.getMappedObject(query, entity), fields, sort), new ReadDbObjectCallback(readerToUse, entityClass), collectionName); } - + protected T doFindAndModify(String collectionName, DBObject query, DBObject fields, DBObject sort, - Class entityClass, Update update, FindAndModifyOptions options ) { - + Class entityClass, Update update, FindAndModifyOptions options) { + EntityReader readerToUse = this.mongoConverter; MongoPersistentEntity entity = mappingContext.getPersistentEntity(entityClass); - + DBObject updateObj = update.getUpdateObject(); for (String key : updateObj.keySet()) { updateObj.put(key, mongoConverter.convertToMongoType(updateObj.get(key))); } - + if (LOGGER.isDebugEnabled()) { LOGGER.debug("findAndModify using query: " + query + " fields: " + fields + " sort: " + sort + " for class: " + entityClass + " and update: " + updateObj + " in collection: " + collectionName); } - - return executeFindOneInternal(new FindAndModifyCallback(mapper.getMappedObject(query, entity), fields, sort, updateObj, options), - new ReadDbObjectCallback(readerToUse, entityClass), collectionName); + return executeFindOneInternal(new FindAndModifyCallback(mapper.getMappedObject(query, entity), fields, sort, + updateObj, options), new ReadDbObjectCallback(readerToUse, entityClass), collectionName); } - /** * Populates the id property of the saved object, if it's not set already. * @@ -1478,7 +1476,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { /** * Checks and handles any errors. *

- * Current implementation logs errors. Future version may make this configurable to log warning, errors or throw exception. + * Current implementation logs errors. Future version may make this configurable to log warning, errors or throw + * exception. */ private void handleAnyWriteResultErrors(WriteResult wr, DBObject query, String operation) { if (WriteResultChecking.NONE == this.writeResultChecking) { @@ -1611,7 +1610,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { return collection.findAndModify(query, fields, sort, true, null, false, false); } } - + private static class FindAndModifyCallback implements CollectionCallback { private final DBObject query; @@ -1620,7 +1619,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { private final DBObject update; private final FindAndModifyOptions options; - public FindAndModifyCallback(DBObject query, DBObject fields, DBObject sort, DBObject update, FindAndModifyOptions options) { + public FindAndModifyCallback(DBObject query, DBObject fields, DBObject sort, DBObject update, + FindAndModifyOptions options) { this.query = query; this.fields = fields; this.sort = sort; @@ -1629,7 +1629,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { } public DBObject doInCollection(DBCollection collection) throws MongoException, DataAccessException { - return collection.findAndModify(query, fields, sort, options.isRemove(), update, options.isReturnNew(), options.isUpsert()); + return collection.findAndModify(query, fields, sort, options.isRemove(), update, options.isReturnNew(), + options.isUpsert()); } } @@ -1673,15 +1674,61 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { return source; } } - + private class DefaultWriteConcernResolver implements WriteConcernResolver { public WriteConcern resolve(MongoAction action) { - return action.getDefaultWriteConcern(); + return action.getDefaultWriteConcern(); } - + } + class QueryCursorPreparer implements CursorPreparer { + + private final Query query; + + public QueryCursorPreparer(Query query) { + this.query = query; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.CursorPreparer#prepare(com.mongodb.DBCursor) + */ + public DBCursor prepare(DBCursor cursor) { + + if (query == null) { + return cursor; + } + + if (query.getSkip() <= 0 && query.getLimit() <= 0 && query.getSortObject() == null && !StringUtils + .hasText(query.getHint())) { + return cursor; + } + + DBCursor cursorToUse = cursor; + + try { + if (query.getSkip() > 0) { + cursorToUse = cursorToUse.skip(query.getSkip()); + } + if (query.getLimit() > 0) { + cursorToUse = cursorToUse.limit(query.getLimit()); + } + if (query.getSortObject() != null) { + cursorToUse = cursorToUse.sort(query.getSortObject()); + } + if (StringUtils.hasText(query.getHint())) { + cursorToUse = cursorToUse.hint(query.getHint()); + } + } catch (RuntimeException e) { + throw potentiallyConvertRuntimeException(e); + } + + return cursorToUse; + } + } + /** * {@link DbObjectCallback} that assumes a {@link GeoResult} to be created, delegates actual content unmarshalling to * a delegate and creates a {@link GeoResult} from the result. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java index 104abde43..4e45c0372 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java @@ -19,9 +19,11 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; +import org.springframework.data.mongodb.InvalidMongoDbApiUsageException; +import org.springframework.util.Assert; + import com.mongodb.BasicDBObject; import com.mongodb.DBObject; -import org.springframework.data.mongodb.InvalidMongoDbApiUsageException; public class Query { @@ -30,6 +32,7 @@ public class Query { private Sort sort; private int skip; private int limit; + private String hint; /** * Static factory method to create a Query using the provided criteria @@ -79,6 +82,18 @@ public class Query { return this; } + /** + * Configures the query to use the given hint when being executed. + * + * @param name must not be {@literal null} or empty. + * @return + */ + public Query withHint(String name) { + Assert.hasText(name, "Hint must not be empty or null!"); + this.hint = name; + return this; + } + public Sort sort() { if (this.sort == null) { this.sort = new Sort(); @@ -119,6 +134,10 @@ public class Query { return this.limit; } + public String getHint() { + return hint; + } + protected List getCriteria() { return new ArrayList(this.criteria.values()); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryCursorPreparerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryCursorPreparerUnitTests.java new file mode 100644 index 000000000..f5b0cd98a --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryCursorPreparerUnitTests.java @@ -0,0 +1,58 @@ +/* + * Copyright 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.mongodb.core; + +import static org.springframework.data.mongodb.core.query.Query.*; +import static org.springframework.data.mongodb.core.query.Criteria.*; +import static org.mockito.Mockito.*; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.core.MongoTemplate.QueryCursorPreparer; +import org.springframework.data.mongodb.core.query.Query; + +import com.mongodb.DBCursor; + +/** + * Unit tests for {@link QueryCursorPreparer}. + * + * @author Oliver Gierke + */ +@RunWith(MockitoJUnitRunner.class) +public class QueryCursorPreparerUnitTests { + + @Mock + MongoDbFactory factory; + @Mock + DBCursor cursor; + + /** + * @see DATAMONGO-185 + */ + @Test + public void appliesHintsCorrectly() { + + Query query = query(where("foo").is("bar")).withHint("hint"); + + CursorPreparer preparer = new MongoTemplate(factory).new QueryCursorPreparer(query); + preparer.prepare(cursor); + + verify(cursor).hint("hint"); + } +}