refactored MongoOperations to use UpdateDefinition/QueryDefinition throughout; added skip/limit/sort to CursorPreparer for queries; cleanup; refactored Query

This commit is contained in:
Thomas Risberg
2011-02-04 14:16:24 -05:00
parent eafed37283
commit 895776bea2
13 changed files with 470 additions and 434 deletions

View File

@@ -26,9 +26,9 @@ import com.mongodb.DBCursor;
public interface CursorPreparer {
/**
* Prepare the given cursor (apply limits, skips and so on).
* Prepare the given cursor (apply limits, skips and so on). Returns th eprepared cursor.
*
* @param cursor
*/
void prepare(DBCursor cursor);
DBCursor prepare(DBCursor cursor);
}

View File

@@ -19,7 +19,9 @@ import java.util.List;
import java.util.Set;
import org.springframework.data.document.mongodb.builder.QueryDefinition;
import org.springframework.data.document.mongodb.builder.UpdateDefinition;
import com.mongodb.CommandResult;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
@@ -53,14 +55,14 @@ public interface MongoOperations {
* exception hierarchy.
* @param jsonCommand a MongoDB command expressed as a JSON string.
*/
void executeCommand(String jsonCommand);
CommandResult executeCommand(String jsonCommand);
/**
* Execute a MongoDB command. Any errors that result from executing this command will be converted
* into Spring's DAO exception hierarchy.
* @param command a MongoDB command
*/
void executeCommand(DBObject command);
CommandResult executeCommand(DBObject command);
/**
* Executes a {@link DbCallback} translating any exceptions as necessary.
@@ -160,6 +162,139 @@ public interface MongoOperations {
*/
void dropCollection(String collectionName);
/**
* Query for a list of objects of type T from the default collection.
*
* 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.
*
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient
* way to map objects since the test for class type is done in the client and not on the server.
*
* @param targetClass the parameterized type of the returned list
* @return the converted collection
*/
<T> List<T> getCollection(Class<T> targetClass);
/**
* Query for a list of objects of type T from the specified collection.
*
* 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.
*
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient
* way to map objects since the test for class type is done in the client and not on the server.
* @param collectionName name of the collection to retrieve the objects from
* @param targetClass the parameterized type of the returned list.
* @return the converted collection
*/
<T> List<T> getCollection(String collectionName, Class<T> targetClass);
/**
* Query for a list of objects of type T from the specified collection, mapping the DBObject using
* the provided MongoReader.
*
* @param collectionName name of the collection to retrieve the objects from
* @param targetClass the parameterized type of the returned list.
* @param reader the MongoReader to convert from DBObject to an object.
* @return the converted collection
*/
<T> List<T> getCollection(String collectionName, Class<T> targetClass,
MongoReader<T> reader);
/**
* Map the results of an ad-hoc query on the default MongoDB 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 QueryDefinition} 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 targetClass the parameterized type of the returned list.
* @return the List of converted objects
*/
<T> List<T> find(QueryDefinition query, Class<T> targetClass);
/**
* Map the results of an ad-hoc query on the default MongoDB 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 QueryDefinition} 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 targetClass the parameterized type of the returned list.
* @param reader the MongoReader to convert from DBObject to an object.
* @return the List of converted objects
*/
<T> List<T> find(QueryDefinition query, Class<T> targetClass,
MongoReader<T> reader);
/**
* Map the results of an ad-hoc query on the default MongoDB 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 QueryDefinition} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param collectionName name of the collection to retrieve the objects from
* @param query the query class that specifies the criteria used to find a record and also an optional fields specification
* @param targetClass the parameterized type of the returned list.
* @return the List of converted objects
*/
<T> List<T> find(String collectionName, QueryDefinition query,
Class<T> targetClass);
/**
* Map the results of an ad-hoc query on the default MongoDB 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 QueryDefinition} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param collectionName name of the collection to retrieve the objects from
* @param query the query class that specifies the criteria used to find a record and also an optional fields specification
* @param targetClass the parameterized type of the returned list.
* @param reader the MongoReader to convert from DBObject to an object.
* @return the List of converted objects
*/
<T> List<T> find(String collectionName, QueryDefinition query,
Class<T> targetClass, MongoReader<T> reader);
/**
* Map the results of an ad-hoc query on the default MongoDB 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 QueryDefinition} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param collectionName name of the collection to retrieve the objects from
* @param query the query class that specifies the criteria used to find a record and also an optional fields specification
* @param targetClass 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).
* @return the List of converted objects.
*/
<T> List<T> find(String collectionName, QueryDefinition query, Class<T> targetClass, CursorPreparer preparer);
/**
* Insert the object into the default collection.
*
@@ -298,7 +433,7 @@ public interface MongoOperations {
* @param updateDoc the update document that contains the updated object or $ operators to manipulate the
* existing object.
*/
void updateFirst(DBObject queryDoc, DBObject updateDoc);
void updateFirst(QueryDefinition query, UpdateDefinition update);
/**
* Updates the first object that is found in the specified collection that matches the query document criteria
@@ -309,8 +444,8 @@ public interface MongoOperations {
* @param updateDoc the update document that contains the updated object or $ operators to manipulate the
* existing object.
*/
void updateFirst(String collectionName, DBObject queryDoc,
DBObject updateDoc);
void updateFirst(String collectionName, QueryDefinition query,
UpdateDefinition update);
/**
* Updates all objects that are found in the default collection that matches the query document criteria
@@ -320,7 +455,7 @@ public interface MongoOperations {
* @param updateDoc the update document that contains the updated object or $ operators to manipulate the
* existing object.
*/
void updateMulti(DBObject queryDoc, DBObject updateDoc);
void updateMulti(QueryDefinition query, UpdateDefinition update);
/**
* Updates all objects that are found in the specified collection that matches the query document criteria
@@ -331,153 +466,20 @@ public interface MongoOperations {
* @param updateDoc the update document that contains the updated object or $ operators to manipulate the
* existing object.
*/
void updateMulti(String collectionName, DBObject queryDoc,
DBObject updateDoc);
void updateMulti(String collectionName, QueryDefinition query,
UpdateDefinition update);
/**
* Remove all documents from the default collection that match the provide query document criteria.
* @param queryDoc the query document that specifies the criteria used to remove a record
*/
void remove(DBObject queryDoc);
void remove(QueryDefinition query);
/**
* Remove all documents from the specified collection that match the provide query document criteria.
* @param collectionName name of the collection where the objects will removed
* @param queryDoc the query document that specifies the criteria used to remove a record
*/
void remove(String collectionName, DBObject queryDoc);
/**
* Query for a list of objects of type T from the default collection.
*
* 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.
*
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient
* way to map objects since the test for class type is done in the client and not on the server.
*
* @param targetClass the parameterized type of the returned list
* @return the converted collection
*/
<T> List<T> getCollection(Class<T> targetClass);
/**
* Query for a list of objects of type T from the specified collection.
*
* 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.
*
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient
* way to map objects since the test for class type is done in the client and not on the server.
* @param collectionName name of the collection to retrieve the objects from
* @param targetClass the parameterized type of the returned list.
* @return the converted collection
*/
<T> List<T> getCollection(String collectionName, Class<T> targetClass);
/**
* Query for a list of objects of type T from the specified collection, mapping the DBObject using
* the provided MongoReader.
*
* @param collectionName name of the collection to retrieve the objects from
* @param targetClass the parameterized type of the returned list.
* @param reader the MongoReader to convert from DBObject to an object.
* @return the converted collection
*/
<T> List<T> getCollection(String collectionName, Class<T> targetClass,
MongoReader<T> reader);
/**
* Map the results of an ad-hoc query on the default MongoDB 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 QueryDefinition} 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 targetClass the parameterized type of the returned list.
* @return the List of converted objects
*/
<T> List<T> find(QueryDefinition query, Class<T> targetClass);
/**
* Map the results of an ad-hoc query on the default MongoDB 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 QueryDefinition} 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 targetClass the parameterized type of the returned list.
* @param reader the MongoReader to convert from DBObject to an object.
* @return the List of converted objects
*/
<T> List<T> find(QueryDefinition query, Class<T> targetClass,
MongoReader<T> reader);
/**
* Map the results of an ad-hoc query on the default MongoDB 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 QueryDefinition} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param collectionName name of the collection to retrieve the objects from
* @param query the query class that specifies the criteria used to find a record and also an optional fields specification
* @param targetClass the parameterized type of the returned list.
* @return the List of converted objects
*/
<T> List<T> find(String collectionName, QueryDefinition query,
Class<T> targetClass);
/**
* Map the results of an ad-hoc query on the default MongoDB 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 QueryDefinition} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param collectionName name of the collection to retrieve the objects from
* @param query the query class that specifies the criteria used to find a record and also an optional fields specification
* @param targetClass the parameterized type of the returned list.
* @param reader the MongoReader to convert from DBObject to an object.
* @return the List of converted objects
*/
<T> List<T> find(String collectionName, QueryDefinition query,
Class<T> targetClass, MongoReader<T> reader);
/**
* Map the results of an ad-hoc query on the default MongoDB 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 QueryDefinition} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param collectionName name of the collection to retrieve the objects from
* @param query the query class that specifies the criteria used to find a record and also an optional fields specification
* @param targetClass 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).
* @return the List of converted objects.
*/
<T> List<T> find(String collectionName, QueryDefinition query, Class<T> targetClass, CursorPreparer preparer);
void remove(String collectionName, QueryDefinition query);
}

View File

@@ -21,14 +21,16 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bson.types.ObjectId;
import org.springframework.beans.ConfigurablePropertyAccessor;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.document.mongodb.MongoPropertyDescriptors.MongoPropertyDescriptor;
import org.springframework.data.document.mongodb.builder.QueryDefinition;
import org.springframework.data.document.mongodb.builder.UpdateDefinition;
import org.springframework.jca.cci.core.ConnectionCallback;
import org.springframework.util.Assert;
@@ -53,6 +55,8 @@ import com.mongodb.util.JSON;
*/
public class MongoTemplate implements InitializingBean, MongoOperations {
private static final Log LOGGER = LogFactory.getLog(MongoTemplate.class);
private static final String ID = "_id";
/*
@@ -215,14 +219,14 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoOperations#executeCommand(java.lang.String)
*/
public void executeCommand(String jsonCommand) {
executeCommand((DBObject)JSON.parse(jsonCommand));
public CommandResult executeCommand(String jsonCommand) {
return executeCommand((DBObject)JSON.parse(jsonCommand));
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoOperations#executeCommand(com.mongodb.DBObject)
*/
public void executeCommand(final DBObject command) {
public CommandResult executeCommand(final DBObject command) {
CommandResult result = execute(new DbCallback<CommandResult>() {
public CommandResult doInDB(DB db) throws MongoException, DataAccessException {
@@ -232,9 +236,13 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
String error = result.getErrorMessage();
if (error != null) {
throw new InvalidDataAccessApiUsageException("Command execution of " +
// TODO: allow configuration of logging level / throw
// throw new InvalidDataAccessApiUsageException("Command execution of " +
// command.toString() + " failed: " + error);
LOGGER.warn("Command execution of " +
command.toString() + " failed: " + error);
}
return result;
}
/* (non-Javadoc)
@@ -295,7 +303,7 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
DBCursor cursor = collectionCallback.doInCollection(getCollection(collectionName));
if (preparer != null) {
preparer.prepare(cursor);
cursor = preparer.prepare(cursor);
}
List<T> result = new ArrayList<T>();
@@ -387,16 +395,52 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
}
private String getRequiredDefaultCollectionName() {
String name = getDefaultCollectionName();
if (name == null) {
throw new IllegalStateException(
"No 'defaultCollection' or 'defaultCollectionName' specified. Check configuration of MongoTemplate.");
}
return name;
// Find methods that take a QueryDefinition to express the query.
public <T> List<T> find(QueryDefinition query, Class<T> targetClass) {
return find(getDefaultCollectionName(), query, targetClass); //
}
public <T> List<T> find(QueryDefinition query, Class<T> targetClass, MongoReader<T> reader) {
return find(getDefaultCollectionName(), query, targetClass, reader);
}
public <T> List<T> find(String collectionName, final QueryDefinition query, Class<T> targetClass) {
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 (MongoException e) {
throw potentiallyConvertRuntimeException(e);
}
return cursorToUse;
}
};
}
return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), targetClass, cursorPreparer);
}
public <T> List<T> find(String collectionName, QueryDefinition query, Class<T> targetClass, MongoReader<T> reader) {
return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), targetClass, reader);
}
public <T> List<T> find(String collectionName, QueryDefinition query,
Class<T> targetClass, CursorPreparer preparer) {
return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), targetClass, preparer);
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoOperations#insert(java.lang.Object)
*/
@@ -557,21 +601,21 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoOperations#updateFirst(com.mongodb.DBObject, com.mongodb.DBObject)
*/
public void updateFirst(DBObject queryDoc, DBObject updateDoc) {
updateFirst(getRequiredDefaultCollectionName(), queryDoc, updateDoc);
public void updateFirst(QueryDefinition query, UpdateDefinition update) {
updateFirst(getRequiredDefaultCollectionName(), query, update);
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoOperations#updateFirst(java.lang.String, com.mongodb.DBObject, com.mongodb.DBObject)
*/
public void updateFirst(String collectionName, final DBObject queryDoc, final DBObject updateDoc) {
public void updateFirst(String collectionName, final QueryDefinition query, final UpdateDefinition update) {
execute(new CollectionCallback<Void>() {
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
if (writeConcern == null) {
collection.update(queryDoc, updateDoc);
collection.update(query.getQueryObject(), update.getUpdateObject());
}
else {
collection.update(queryDoc, updateDoc, false, false, writeConcern);
collection.update(query.getQueryObject(), update.getUpdateObject(), false, false, writeConcern);
}
return null;
}
@@ -581,21 +625,21 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoOperations#updateMulti(com.mongodb.DBObject, com.mongodb.DBObject)
*/
public void updateMulti(DBObject queryDoc, DBObject updateDoc) {
updateMulti(getRequiredDefaultCollectionName(), queryDoc, updateDoc);
public void updateMulti(QueryDefinition query, UpdateDefinition update) {
updateMulti(getRequiredDefaultCollectionName(), query, update);
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoOperations#updateMulti(java.lang.String, com.mongodb.DBObject, com.mongodb.DBObject)
*/
public void updateMulti(String collectionName, final DBObject queryDoc, final DBObject updateDoc) {
public void updateMulti(String collectionName, final QueryDefinition query, final UpdateDefinition update) {
execute(new CollectionCallback<Void>() {
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
if (writeConcern == null) {
collection.updateMulti(queryDoc, updateDoc);
collection.updateMulti(query.getQueryObject(), update.getUpdateObject());
}
else {
collection.update(queryDoc, updateDoc, false, true, writeConcern);
collection.update(query.getQueryObject(), update.getUpdateObject(), false, true, writeConcern);
}
return null;
}
@@ -605,21 +649,21 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoOperations#remove(com.mongodb.DBObject)
*/
public void remove(DBObject queryDoc) {
remove(getRequiredDefaultCollectionName(), queryDoc);
public void remove(QueryDefinition query) {
remove(getRequiredDefaultCollectionName(), query);
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoOperations#remove(java.lang.String, com.mongodb.DBObject)
*/
public void remove(String collectionName, final DBObject queryDoc) {
public void remove(String collectionName, final QueryDefinition query) {
execute(new CollectionCallback<Void>() {
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
if (writeConcern == null) {
collection.remove(queryDoc);
collection.remove(query.getQueryObject());
}
else {
collection.remove(queryDoc, writeConcern);
collection.remove(query.getQueryObject(), writeConcern);
}
return null;
}
@@ -653,29 +697,11 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
collectionName);
}
// Find methods that take a QueryDefinition to express the query.
public DB getDb() {
return MongoDbUtils.getDB(mongo, databaseName, username, password == null ? null : password.toCharArray());
}
public <T> List<T> find(QueryDefinition query, Class<T> targetClass) {
return find(getDefaultCollectionName(), query, targetClass); //
}
public <T> List<T> find(QueryDefinition query, Class<T> targetClass, MongoReader<T> reader) {
return find(getDefaultCollectionName(), query, targetClass, reader);
}
public <T> List<T> find(String collectionName, QueryDefinition query, Class<T> targetClass) {
return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), targetClass, (CursorPreparer) null);
}
public <T> List<T> find(String collectionName, QueryDefinition query, Class<T> targetClass, MongoReader<T> reader) {
return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), targetClass, reader);
}
public <T> List<T> find(String collectionName, QueryDefinition query,
Class<T> targetClass, CursorPreparer preparer) {
return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), targetClass, preparer);
}
/**
* Map the results of an ad-hoc query on the default MongoDB collection to a List of the specified type.
*
@@ -717,12 +743,6 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
collectionName);
}
public DB getDb() {
return MongoDbUtils.getDB(mongo, databaseName, username, password == null ? null : password.toCharArray());
}
protected DBObject convertToDbObject(CollectionOptions collectionOptions) {
DBObject dbo = new BasicDBObject();
if (collectionOptions != null) {
@@ -763,8 +783,18 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
bw.setPropertyValue(idDescriptor.getName(), target);
}
}
/**
private String getRequiredDefaultCollectionName() {
String name = getDefaultCollectionName();
if (name == null) {
throw new IllegalStateException(
"No 'defaultCollection' or 'defaultCollectionName' specified. Check configuration of MongoTemplate.");
}
return name;
}
/**
* Tries to convert the given {@link RuntimeException} into a {@link DataAccessException} but returns the original
* exception if the conversation failed. Thus allows safe rethrowing of the return value.
*

View File

@@ -40,7 +40,7 @@ public class Criteria implements CriteriaDefinition {
public Criteria and(String key) {
return qb.find(key);
return qb.start(key);
}
@@ -121,7 +121,7 @@ public class Criteria implements CriteriaDefinition {
criteria.put("$or", queries);
}
public Query build() {
public Query end() {
return qb;
}

View File

@@ -32,11 +32,11 @@ public class Query implements QueryDefinition {
private int limit;
public static Criteria newQuery(String key) {
return new Query().find(key);
public static Criteria startQueryWithCriteria(String key) {
return new Query().start(key);
}
public Criteria find(String key) {
public Criteria start(String key) {
Criteria c = new Criteria(this);
this.criteria.put(key, c);
return c;
@@ -56,7 +56,7 @@ public class Query implements QueryDefinition {
return this.fieldSpec;
}
public Query slip(int skip) {
public Query skip(int skip) {
this.skip = skip;
return this;
}
@@ -75,9 +75,9 @@ public class Query implements QueryDefinition {
return this.sort;
}
public QueryDefinition build() {
return this;
}
// public QueryDefinition build() {
// return this;
// }
public DBObject getQueryObject() {
DBObject dbo = new BasicDBObject();

View File

@@ -84,9 +84,9 @@ public class Update implements UpdateDefinition {
return this;
}
public UpdateDefinition build() {
return this;
}
// public UpdateDefinition build() {
// return this;
// }
public DBObject getUpdateObject() {
DBObject dbo = new BasicDBObject();

View File

@@ -98,7 +98,7 @@ public class MongoQuery implements RepositoryQuery {
protected List<?> readCollection(Query query) {
return template.find(query.build(), method.getDomainClass());
return template.find(query, method.getDomainClass());
}
}

View File

@@ -75,7 +75,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
protected Criteria create(Part part, BindableParameterIterator iterator) {
return from(part.getType(),
new Query().find(part.getProperty().toDotPath()), iterator);
new Query().start(part.getProperty().toDotPath()), iterator);
}
@@ -107,7 +107,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
@Override
protected Criteria or(Criteria base, Criteria criteria) {
base.or(Arrays.asList(criteria.build()));
base.or(Arrays.asList(criteria.end()));
return base;
}
@@ -122,7 +122,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
@Override
protected Query complete(Criteria criteria, Sort sort) {
Query query = criteria.build();
Query query = criteria.end();
if (LOG.isDebugEnabled()) {
LOG.debug("Created query " + query);

View File

@@ -51,7 +51,7 @@ abstract class QueryUtils {
}
query.limit(pageable.getPageSize());
query.slip(pageable.getOffset());
query.skip(pageable.getOffset());
return applySorting(query, pageable.getSort());
}
@@ -61,18 +61,18 @@ abstract class QueryUtils {
* Applies the given {@link Sort} to the {@link Query}. Will do nothing if
* {@link Sort} is {@literal null}.
*
* @param spec
* @param query
* @param sort
* @return
*/
public static Query applySorting(Query spec, Sort sort) {
public static Query applySorting(Query query, Sort sort) {
if (sort == null) {
return spec;
return query;
}
org.springframework.data.document.mongodb.builder.Sort bSort =
spec.sort();
query.sort();
for (Order order : sort) {
bSort.on(
@@ -81,6 +81,6 @@ abstract class QueryUtils {
: org.springframework.data.document.mongodb.builder.Sort.Order.DESCENDING);
}
return spec;
return query;
}
}

View File

@@ -110,7 +110,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends
List<T> result =
template.find(
new Query().find("_id").is(objectId).build(),
new Query().start("_id").is(objectId).end(),
getDomainClass());
return result.isEmpty() ? null : result.get(0);
}
@@ -160,10 +160,10 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends
*/
public void delete(T entity) {
QueryBuilder builder =
QueryBuilder.start(entityInformation.getFieldName()).is(
entityInformation.getId(entity));
template.remove(builder.get());
Query query =
Query.startQueryWithCriteria(entityInformation.getFieldName()).is(
entityInformation.getId(entity)).end();
template.remove(query);
}

View File

@@ -15,8 +15,9 @@
*/
package org.springframework.data.document.mongodb;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import java.util.List;
@@ -28,8 +29,6 @@ import org.springframework.data.document.mongodb.builder.Query;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.mongodb.QueryBuilder;
/**
* Integration test for {@link MongoTemplate}.
*
@@ -55,8 +54,13 @@ public class MongoTemplateTests {
MongoConverter converter = template.getConverter();
List<Person> result = template.find(Query.newQuery("_id").is(converter.convertObjectId(person.getId())).build(), Person.class);
List<Person> result = template.find(Query.startQueryWithCriteria("_id").is(converter.convertObjectId(person.getId())).end(), Person.class);
assertThat(result.size(), is(1));
assertThat(result, hasItem(person));
}
@Test
public void simpleQuery() throws Exception {
Query.startQueryWithCriteria("name").is("Mary").and("age").lt(33).gt(22).end().skip(22).limit(20);
}
}

View File

@@ -1,74 +1,74 @@
/*
* 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.builder;
import org.junit.Assert;
import org.junit.Test;
public class QueryTests {
@Test
public void testSimpleQuery() {
Query q = new Query();
q.find("name").is("Thomas");
q.find("age").lt(80);
String expected = "{ \"name\" : \"Thomas\" , \"age\" : { \"$lt\" : 80}}";
Assert.assertEquals(expected, q.build().getQueryObject().toString());
}
@Test
public void testQueryWithNot() {
Query q = new Query();
q.find("name").is("Thomas");
q.find("age").not().mod(10, 0);
String expected = "{ \"name\" : \"Thomas\" , \"age\" : { \"$not\" : { \"$mod\" : [ 10 , 0]}}}";
Assert.assertEquals(expected, q.build().getQueryObject().toString());
}
@Test
public void testOrQuery() {
Query q = new Query();;
q.or(
new Query().find("name").is("Sven").and("age").lt(50).build(),
new Query().find("age").lt(50).build(),
new BasicQuery("{'name' : 'Thomas'}")
);
String expected = "{ \"$or\" : [ { \"name\" : \"Sven\" , \"age\" : { \"$lt\" : 50}} , { \"age\" : { \"$lt\" : 50}} , { \"name\" : \"Thomas\"}]}";
Assert.assertEquals(expected, q.build().getQueryObject().toString());
}
@Test
public void testQueryWithLimit() {
Query q = new Query();
q.find("name").gte("M").lte("T").and("age").not().gt(22);
q.limit(50);
String expected = "{ \"name\" : { \"$gte\" : \"M\" , \"$lte\" : \"T\"} , \"age\" : { \"$not\" : { \"$gt\" : 22}}}";
Assert.assertEquals(expected, q.build().getQueryObject().toString());
Assert.assertEquals(50, q.build().getLimit());
}
@Test
public void testQueryWithFieldsAndSlice() {
Query q = new Query();
q.find("name").gte("M").lte("T").and("age").not().gt(22);
q.fields().exclude("address").include("name").slice("orders", 10);
String expected = "{ \"name\" : { \"$gte\" : \"M\" , \"$lte\" : \"T\"} , \"age\" : { \"$not\" : { \"$gt\" : 22}}}";
Assert.assertEquals(expected, q.build().getQueryObject().toString());
String expectedFields = "{ \"address\" : 0 , \"name\" : 1 , \"orders\" : { \"$slice\" : 10}}";
Assert.assertEquals(expectedFields, q.build().getFieldsObject().toString());
}
}
/*
* 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.builder;
import org.junit.Assert;
import org.junit.Test;
public class QueryTests {
@Test
public void testSimpleQuery() {
Query q = new Query();
q.start("name").is("Thomas");
q.start("age").lt(80);
String expected = "{ \"name\" : \"Thomas\" , \"age\" : { \"$lt\" : 80}}";
Assert.assertEquals(expected, q.getQueryObject().toString());
}
@Test
public void testQueryWithNot() {
Query q = new Query();
q.start("name").is("Thomas");
q.start("age").not().mod(10, 0);
String expected = "{ \"name\" : \"Thomas\" , \"age\" : { \"$not\" : { \"$mod\" : [ 10 , 0]}}}";
Assert.assertEquals(expected, q.getQueryObject().toString());
}
@Test
public void testOrQuery() {
Query q = new Query();;
q.or(
new Query().start("name").is("Sven").and("age").lt(50).end(),
new Query().start("age").lt(50).end(),
new BasicQuery("{'name' : 'Thomas'}")
);
String expected = "{ \"$or\" : [ { \"name\" : \"Sven\" , \"age\" : { \"$lt\" : 50}} , { \"age\" : { \"$lt\" : 50}} , { \"name\" : \"Thomas\"}]}";
Assert.assertEquals(expected, q.getQueryObject().toString());
}
@Test
public void testQueryWithLimit() {
Query q = new Query();
q.start("name").gte("M").lte("T").and("age").not().gt(22);
q.limit(50);
String expected = "{ \"name\" : { \"$gte\" : \"M\" , \"$lte\" : \"T\"} , \"age\" : { \"$not\" : { \"$gt\" : 22}}}";
Assert.assertEquals(expected, q.getQueryObject().toString());
Assert.assertEquals(50, q.getLimit());
}
@Test
public void testQueryWithFieldsAndSlice() {
Query q = new Query();
q.start("name").gte("M").lte("T").and("age").not().gt(22);
q.fields().exclude("address").include("name").slice("orders", 10);
String expected = "{ \"name\" : { \"$gte\" : \"M\" , \"$lte\" : \"T\"} , \"age\" : { \"$not\" : { \"$gt\" : 22}}}";
Assert.assertEquals(expected, q.getQueryObject().toString());
String expectedFields = "{ \"address\" : 0 , \"name\" : 1 , \"orders\" : { \"$slice\" : 10}}";
Assert.assertEquals(expectedFields, q.getFieldsObject().toString());
}
}

View File

@@ -1,124 +1,124 @@
/*
* 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.builder;
import java.util.HashMap;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.data.document.mongodb.builder.Sort.Order;
import org.springframework.data.document.mongodb.builder.Update;
public class UpdateTests {
@Test
public void testSet() {
Update u = new Update()
.set("directory", "/Users/Test/Desktop");
Assert.assertEquals("{ \"$set\" : { \"directory\" : \"/Users/Test/Desktop\"}}", u.build().getUpdateObject().toString());
}
@Test
public void testInc() {
Update u = new Update()
.inc("size", 1);
Assert.assertEquals("{ \"$inc\" : { \"size\" : 1}}", u.build().getUpdateObject().toString());
}
@Test
public void testIncAndSet() {
Update u = new Update()
.inc("size", 1)
.set("directory", "/Users/Test/Desktop");
Assert.assertEquals("{ \"$inc\" : { \"size\" : 1} , \"$set\" : { \"directory\" : \"/Users/Test/Desktop\"}}",
u.build().getUpdateObject().toString());
}
@Test
public void testUnset() {
Update u = new Update()
.unset("directory");
Assert.assertEquals("{ \"$unset\" : { \"directory\" : 1}}", u.build().getUpdateObject().toString());
}
@Test
public void testPush() {
Map<String, Object> m = new HashMap<String, Object>();
m.put("name", "Sven");
Update u = new Update()
.push("authors", m);
Assert.assertEquals("{ \"$push\" : { \"authors\" : { \"name\" : \"Sven\"}}}", u.build().getUpdateObject().toString());
}
@Test
public void testPushAll() {
Map<String, Object> m1 = new HashMap<String, Object>();
m1.put("name", "Sven");
Map<String, Object> m2 = new HashMap<String, Object>();
m2.put("name", "Maria");
Update u = new Update()
.pushAll("authors", new Object[] {m1, m2});
Assert.assertEquals("{ \"$pushAll\" : { \"authors\" : [ { \"name\" : \"Sven\"} , { \"name\" : \"Maria\"}]}}", u.build().getUpdateObject().toString());
}
@Test
public void testAddToSet() {
Map<String, Object> m = new HashMap<String, Object>();
m.put("name", "Sven");
Update u = new Update()
.addToSet("authors", m);
Assert.assertEquals("{ \"$addToSet\" : { \"authors\" : { \"name\" : \"Sven\"}}}", u.build().getUpdateObject().toString());
}
@Test
public void testPop() {
Update u = new Update()
.pop("authors", Update.Position.FIRST);
Assert.assertEquals("{ \"$pop\" : { \"authors\" : -1}}", u.build().getUpdateObject().toString());
u = new Update()
.pop("authors", Update.Position.LAST);
Assert.assertEquals("{ \"$pop\" : { \"authors\" : 1}}", u.build().getUpdateObject().toString());
}
@Test
public void testPull() {
Map<String, Object> m = new HashMap<String, Object>();
m.put("name", "Sven");
Update u = new Update()
.pull("authors", m);
Assert.assertEquals("{ \"$pull\" : { \"authors\" : { \"name\" : \"Sven\"}}}", u.build().getUpdateObject().toString());
}
@Test
public void testPullAll() {
Map<String, Object> m1 = new HashMap<String, Object>();
m1.put("name", "Sven");
Map<String, Object> m2 = new HashMap<String, Object>();
m2.put("name", "Maria");
Update u = new Update()
.pullAll("authors", new Object[] {m1, m2});
Assert.assertEquals("{ \"$pullAll\" : { \"authors\" : [ { \"name\" : \"Sven\"} , { \"name\" : \"Maria\"}]}}", u.build().getUpdateObject().toString());
}
@Test
public void testRename() {
Update u = new Update()
.rename("directory", "folder");
Assert.assertEquals("{ \"$rename\" : { \"directory\" : \"folder\"}}", u.build().getUpdateObject().toString());
}
}
/*
* 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.builder;
import java.util.HashMap;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.data.document.mongodb.builder.Sort.Order;
import org.springframework.data.document.mongodb.builder.Update;
public class UpdateTests {
@Test
public void testSet() {
Update u = new Update()
.set("directory", "/Users/Test/Desktop");
Assert.assertEquals("{ \"$set\" : { \"directory\" : \"/Users/Test/Desktop\"}}", u.getUpdateObject().toString());
}
@Test
public void testInc() {
Update u = new Update()
.inc("size", 1);
Assert.assertEquals("{ \"$inc\" : { \"size\" : 1}}", u.getUpdateObject().toString());
}
@Test
public void testIncAndSet() {
Update u = new Update()
.inc("size", 1)
.set("directory", "/Users/Test/Desktop");
Assert.assertEquals("{ \"$inc\" : { \"size\" : 1} , \"$set\" : { \"directory\" : \"/Users/Test/Desktop\"}}",
u.getUpdateObject().toString());
}
@Test
public void testUnset() {
Update u = new Update()
.unset("directory");
Assert.assertEquals("{ \"$unset\" : { \"directory\" : 1}}", u.getUpdateObject().toString());
}
@Test
public void testPush() {
Map<String, Object> m = new HashMap<String, Object>();
m.put("name", "Sven");
Update u = new Update()
.push("authors", m);
Assert.assertEquals("{ \"$push\" : { \"authors\" : { \"name\" : \"Sven\"}}}", u.getUpdateObject().toString());
}
@Test
public void testPushAll() {
Map<String, Object> m1 = new HashMap<String, Object>();
m1.put("name", "Sven");
Map<String, Object> m2 = new HashMap<String, Object>();
m2.put("name", "Maria");
Update u = new Update()
.pushAll("authors", new Object[] {m1, m2});
Assert.assertEquals("{ \"$pushAll\" : { \"authors\" : [ { \"name\" : \"Sven\"} , { \"name\" : \"Maria\"}]}}", u.getUpdateObject().toString());
}
@Test
public void testAddToSet() {
Map<String, Object> m = new HashMap<String, Object>();
m.put("name", "Sven");
Update u = new Update()
.addToSet("authors", m);
Assert.assertEquals("{ \"$addToSet\" : { \"authors\" : { \"name\" : \"Sven\"}}}", u.getUpdateObject().toString());
}
@Test
public void testPop() {
Update u = new Update()
.pop("authors", Update.Position.FIRST);
Assert.assertEquals("{ \"$pop\" : { \"authors\" : -1}}", u.getUpdateObject().toString());
u = new Update()
.pop("authors", Update.Position.LAST);
Assert.assertEquals("{ \"$pop\" : { \"authors\" : 1}}", u.getUpdateObject().toString());
}
@Test
public void testPull() {
Map<String, Object> m = new HashMap<String, Object>();
m.put("name", "Sven");
Update u = new Update()
.pull("authors", m);
Assert.assertEquals("{ \"$pull\" : { \"authors\" : { \"name\" : \"Sven\"}}}", u.getUpdateObject().toString());
}
@Test
public void testPullAll() {
Map<String, Object> m1 = new HashMap<String, Object>();
m1.put("name", "Sven");
Map<String, Object> m2 = new HashMap<String, Object>();
m2.put("name", "Maria");
Update u = new Update()
.pullAll("authors", new Object[] {m1, m2});
Assert.assertEquals("{ \"$pullAll\" : { \"authors\" : [ { \"name\" : \"Sven\"} , { \"name\" : \"Maria\"}]}}", u.getUpdateObject().toString());
}
@Test
public void testRename() {
Update u = new Update()
.rename("directory", "folder");
Assert.assertEquals("{ \"$rename\" : { \"directory\" : \"folder\"}}", u.getUpdateObject().toString());
}
}