DATADOC-76 added support for findAndRemove to MongoTemplate

This commit is contained in:
Thomas Risberg
2011-03-30 18:19:18 -04:00
parent 2c5d0b3893
commit 52f42b29d7
4 changed files with 240 additions and 0 deletions

View File

@@ -396,6 +396,85 @@ public interface MongoOperations {
*/
<T> List<T> find(String collectionName, Query query, Class<T> targetClass, CursorPreparer preparer);
/**
* Map the results of an ad-hoc query on the default MongoDB collection to a single instance of an object
* of the specified type. The first document that matches the query is returned and also removed from the
* collection in the database.
* <p/>
* 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.
* <p/>
* 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 targetClass the parameterized type of the returned list.
* @return the converted object
*/
<T> T findAndRemove(Query query, Class<T> targetClass);
/**
* Map the results of an ad-hoc query on the default MongoDB collection to a single instance of an object
* of the specified type. The first document that matches the query is returned and also removed from the
* collection in the database.
* <p/>
* 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.
* <p/>
* 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 targetClass the parameterized type of the returned list.
* @param reader the MongoReader to convert from DBObject to an object.
* @return the converted object
*/
<T> T findAndRemove(Query query, Class<T> targetClass,
MongoReader<T> reader);
/**
* Map the results of an ad-hoc query on the specified collection to a single instance of an object
* of the specified type. The first document that matches the query is returned and also removed from the
* collection in the database.
* <p/>
* 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.
* <p/>
* 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 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 converted object
*/
<T> T findAndRemove(String collectionName, Query query,
Class<T> targetClass);
/**
* Map the results of an ad-hoc query on the specified collection to a single instance of an object
* of the specified type. The first document that matches the query is returned and also removed from the
* collection in the database.
* <p/>
* 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.
* <p/>
* 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 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 converted object
*/
<T> T findAndRemove(String collectionName, Query query,
Class<T> targetClass, MongoReader<T> reader);
/**
* Insert the object into the default collection.
* <p/>

View File

@@ -548,6 +548,28 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), targetClass, preparer);
}
// 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.
public <T> T findAndRemove(Query query, Class<T> targetClass) {
return findAndRemove(getDefaultCollectionName(), query, targetClass);
}
public <T> T findAndRemove(Query query, Class<T> targetClass,
MongoReader<T> reader) {
return findAndRemove(getDefaultCollectionName(), query, targetClass, reader);
}
public <T> T findAndRemove(String collectionName, Query query,
Class<T> targetClass) {
return findAndRemove(collectionName, query, targetClass, null);
}
public <T> T findAndRemove(String collectionName, Query query,
Class<T> targetClass, MongoReader<T> reader) {
return doFindAndRemove(collectionName, query.getQueryObject(), query.getFieldsObject(), query.getSortObject(), targetClass, reader);
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoOperations#insert(java.lang.Object)
*/
@@ -947,6 +969,28 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
return dbo;
}
/**
* Map the results of an ad-hoc query on the default MongoDB collection to an object using the provided MongoReader
* The first document that matches the query is returned and also removed from the collection in the database.
* <p/>
* The query document is specified as a standard DBObject and so is the fields specification.
*
* @param collectionName name of the collection to retrieve the objects from
* @param query the query document that specifies the criteria used to find a record
* @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.
*/
protected <T> T doFindAndRemove(String collectionName, DBObject query, DBObject fields, DBObject sort, Class<T> targetClass, MongoReader<T> reader) {
MongoReader<? super T> readerToUse = reader;
if (readerToUse == null) {
readerToUse = this.mongoConverter;
}
substituteMappedIdIfNecessary(query, targetClass, readerToUse);
return execute(new FindAndRemoveCallback(query, fields, sort), new ReadDbObjectCallback<T>(readerToUse, targetClass),
collectionName);
}
/**
* Populates the id property of the saved object, if it's not set already.
*
@@ -1175,6 +1219,31 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
}
}
/**
* Simple {@link CollectionCallback} that takes a query {@link DBObject} plus an optional fields specification
* {@link DBObject} and executes that against the {@link DBCollection}.
*
* @author Thomas Risberg
*/
private static class FindAndRemoveCallback implements CollectionCallback<DBObject> {
private final DBObject query;
private final DBObject fields;
private final DBObject sort;
public FindAndRemoveCallback(DBObject query, DBObject fields, DBObject sort) {
this.query = query;
this.fields = fields;
this.sort = sort;
}
public DBObject doInCollection(DBCollection collection) throws MongoException, DataAccessException {
return collection.findAndModify(query, fields, sort, true, null, false, false);
}
}
/**
* Simple internal callback to allow operations on a {@link DBObject}.
*

View File

@@ -0,0 +1,75 @@
/*
* 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;
import java.util.Date;
import org.bson.types.ObjectId;
public class Message {
private ObjectId id;
private String text;
private Date timestamp;
public Message() {
}
public Message(String text) {
super();
this.text = text;
this.timestamp = new Date();
}
public Message(String text, Date timestamp) {
super();
this.text = text;
this.timestamp = timestamp;
}
public ObjectId getId() {
return id;
}
public void setId(ObjectId id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Date getTimestamp() {
return timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
@Override
public String toString() {
return "Message [id=" + id + ", text=" + text + ", timestamp=" + timestamp
+ "]";
}
}

View File

@@ -225,4 +225,21 @@ public class MongoTemplateTests {
assertThat(p8q.get_id(), is(p8.get_id()));
}
@Test
public void testFindAndRemove() throws Exception {
Message m1 = new Message("Hello Spring");
template.insert(m1);
Message m2 = new Message("Hello Mongo");
template.insert(m2);
Query q = new Query(Criteria.where("text").regex("^Hello.*"));
Message found1 = template.findAndRemove(q, Message.class);
Message found2 = template.findAndRemove(q, Message.class);
// Message notFound = template.findAndRemove(q, Message.class);
DBObject notFound = template.getCollection("").findAndRemove(q.getQueryObject());
assertThat(found1, notNullValue());
assertThat(found2, notNullValue());
assertThat(notFound, nullValue());
}
}