Add additional remove methods to MongoTemplate and make consistent with write handling of String <-> ObjectId conversion when using SimpleMongoConverter

Update docs
This commit is contained in:
Mark Pollack
2011-04-07 23:40:38 -04:00
parent e7d47c4626
commit 8c4219bbd2
7 changed files with 252 additions and 41 deletions

View File

@@ -23,6 +23,7 @@ import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.WriteResult;
import org.bson.types.ObjectId;
import org.springframework.data.document.mongodb.index.IndexDefinition;
import org.springframework.data.document.mongodb.query.Query;
import org.springframework.data.document.mongodb.query.Update;
@@ -690,13 +691,30 @@ public interface MongoOperations {
WriteResult updateMulti(String collectionName, Query query,
Update update);
/**
* Remove the given object from the collection by Id
* @param object
*/
void remove(Object object);
/**
* Remove all documents from the default collection that match the provided query document criteria.
*
* @param queryDoc the query document that specifies the criteria used to remove a record
*/
void remove(Query query);
/**
* Remove all documents from the default collection that matchthe provided query document critera. The
* Class parameter is use to help convert the Id of the object if it is present in the query.
* @param <T>
* @param query
* @param targetClass
*/
<T> void remove(Query query, Class<T> targetClass);
/**
* Remove all documents from the specified collection that match the provided query document criteria.
*

View File

@@ -16,6 +16,9 @@
package org.springframework.data.document.mongodb;
import static org.springframework.data.document.mongodb.query.Criteria.whereId;
import static org.springframework.data.document.mongodb.query.Query.query;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
@@ -165,7 +168,14 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
if (writeResultChecking != null) {
this.writeResultChecking = writeResultChecking;
}
setMongoConverter(mongoConverter == null ? new SimpleMongoConverter() : mongoConverter);
if (mongoConverter == null) {
SimpleMongoConverter smc = new SimpleMongoConverter();
smc.afterPropertiesSet();
setMongoConverter(smc);
} else {
setMongoConverter(mongoConverter);
}
//setMongoConverter(mongoConverter == null ? new SimpleMongoConverter() : mongoConverter);
}
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
@@ -808,33 +818,50 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
* @see org.springframework.data.document.mongodb.MongoOperations#remove(com.mongodb.DBObject)
*/
public void remove(Query query) {
remove(getRequiredDefaultCollectionName(), query);
remove(query, null);
}
public void remove(Object object) {
Object idValue = this.getIdValue(object);
remove(new Query(whereId().is(idValue)), object.getClass());
}
public <T> void remove(Query query, Class<T> targetClass) {
remove(getEntityCollection(targetClass), query, targetClass);
}
public <T> void remove(String collectionName, final Query query, Class<T> targetClass) {
if (query == null) {
throw new InvalidDataAccessApiUsageException("Query passed in to remove can't be null");
}
final DBObject queryObject = query.getQueryObject();
if (targetClass == null) {
substituteMappedIdIfNecessary(queryObject);
} else {
substituteMappedIdIfNecessary(queryObject, targetClass, this.mongoConverter);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("remove using query: " + queryObject);
}
execute(collectionName, new CollectionCallback<Void>() {
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
WriteResult wr = null;
if (writeConcern == null) {
wr = collection.remove(queryObject);
} else {
wr = collection.remove(queryObject, writeConcern);
}
handleAnyWriteResultErrors(wr, queryObject, "remove");
return null;
}
});
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoOperations#remove(java.lang.String, com.mongodb.DBObject)
*/
public void remove(String collectionName, final Query query) {
if (query == null) {
throw new InvalidDataAccessApiUsageException("Query passed in to remove can't be null");
}
final DBObject queryObject = query.getQueryObject();
substituteMappedIdIfNecessary(queryObject);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("remove using query: " + queryObject);
}
execute(collectionName, new CollectionCallback<Void>() {
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
WriteResult wr = null;
if (writeConcern == null) {
wr = collection.remove(queryObject);
} else {
wr = collection.remove(queryObject, writeConcern);
}
handleAnyWriteResultErrors(wr, queryObject, "remove");
return null;
}
});
remove(collectionName, query, null);
}
@@ -909,9 +936,6 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
readerToUse = this.mongoConverter;
}
substituteMappedIdIfNecessary(query, targetClass, readerToUse);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("findOne using query: " + query + " fields: " + fields + " for class: " + targetClass);
}
return execute(new FindOneCallback(query, fields), new ReadDbObjectCallback<T>(readerToUse, targetClass),
collectionName);
}
@@ -1006,6 +1030,32 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
collectionName);
}
protected Object getIdValue(Object object) {
if (null != mappingContext) {
PersistentEntity<?> entity = mappingContext.getPersistentEntity(object.getClass());
if (null != entity) {
PersistentProperty idProp = entity.getIdProperty();
if (null != idProp) {
try {
return MappingBeanHelper.getProperty(object, idProp, Object.class, true);
} catch (IllegalAccessException e) {
throw new MappingException(e.getMessage(), e);
} catch (InvocationTargetException e) {
throw new MappingException(e.getMessage(), e);
}
}
}
}
ConfigurablePropertyAccessor bw = PropertyAccessorFactory.forDirectFieldAccess(object);
MongoPropertyDescriptor idDescriptor = new MongoPropertyDescriptors(object.getClass()).getIdDescriptor();
if (idDescriptor == null) {
return null;
}
return bw.getPropertyValue(idDescriptor.getName());
}
/**
* Populates the id property of the saved object, if it's not set already.
*
@@ -1249,8 +1299,14 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
public DBObject doInCollection(DBCollection collection) throws MongoException, DataAccessException {
if (fields == null) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("findOne using query: " + query + " in db.collection: " + collection.getFullName());
}
return collection.findOne(query);
} else {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("findOne using query: " + query + " fields: " + fields + " in db.collection: " + collection.getFullName());
}
return collection.findOne(query, fields);
}
}

View File

@@ -59,6 +59,10 @@ public class Criteria implements CriteriaDefinition {
public static Criteria where(String key) {
return new Criteria(key);
}
public static Criteria whereId() {
return new Criteria("id");
}
/**
* Static factory method to create a Criteria using the provided key

View File

@@ -1,7 +1,29 @@
/*
* Copyright 2002-2010 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.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import static org.springframework.data.document.mongodb.query.Criteria.where;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.springframework.data.document.mongodb.query.Criteria.*;
import org.springframework.data.document.mongodb.query.Query;
import static org.springframework.data.document.mongodb.query.Query.query;
import org.springframework.data.document.mongodb.query.Update;
@@ -9,23 +31,49 @@ import static org.springframework.data.document.mongodb.query.Update.update;
public class PersonExample {
private static final Log log = LogFactory.getLog(PersonExample.class);
@Autowired
private MongoOperations mongoOps;
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(PersonExampleAppConfig.class);
PersonExample example = applicationContext.getBean(PersonExample.class);
example.doWork();
}
public void doWork() {
Person p = new Person();
mongoOps.dropCollection("personexample");
PersonWithIdPropertyOfTypeString p = new PersonWithIdPropertyOfTypeString();
p.setFirstName("Sven");
p.setAge(22);
mongoOps.save(p);
log.debug("Saved: " + p);
System.out.println(p.getId());
p = mongoOps.findOne(query(whereId().is(p.getId())), PersonWithIdPropertyOfTypeString.class);
mongoOps.updateFirst(new Query(where("firstName").is("Sven")), new Update().set("age", 24));
log.debug("Found: " + p);
mongoOps.updateFirst(new Query(where("firstName").is("Sven")), update("age", 24));
// mongoOps.updateFirst(new Query(where("firstName").is("Sven")), new Update().set("age", 24));
// mongoOps.updateFirst(new Query(where("firstName").is("Sven")), update("age", 24));
mongoOps.updateFirst(query(where("firstName").is("Sven")), update("age", 24));
p = mongoOps.findOne(query(whereId().is(p.getId())), PersonWithIdPropertyOfTypeString.class);
log.debug("Updated: " + p);
//mongoOps.remove( query(whereId().is(p.getId())), p.getClass());
mongoOps.remove(p);
List<PersonWithIdPropertyOfTypeString> people = mongoOps.getCollection(PersonWithIdPropertyOfTypeString.class);
//PersonWithIdPropertyOfTypeString p2 = mongoOps.findOne(query(whereId().is(p.getId())), PersonWithIdPropertyOfTypeString.class);
log.debug("Number of people = : " + people.size());
mongoOps.updateFirst(query(where("firstName").is("Sven")), update("age", 24));
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2002-2010 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 org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.mongodb.Mongo;
@Configuration
public class PersonExampleAppConfig {
@Bean
public Mongo mongo() throws Exception {
return new Mongo("localhost");
}
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongo(), "database", "personexample");
}
@Bean
public PersonExample personExample()
{
return new PersonExample();
}
}

View File

@@ -47,5 +47,11 @@ public class PersonWithIdPropertyOfTypeString {
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "PersonWithIdPropertyOfTypeString [id=" + id + ", firstName="
+ firstName + ", age=" + age + "]";
}
}

View File

@@ -419,16 +419,54 @@ public class AppConfig {
<para>You can save, update and delete the object as shown below</para>
<programlisting>public class PersonExample {
<programlisting language="java">public class PersonExample {
@Inject
private static final Log log = LogFactory.getLog(PersonExample.class);
Person p = new Person();
p.setFirstName("Sven");
p.setAge(22);
@Autowired
private MongoOperations mongoOps;
public void doWork() {
Person p = new Person();
p.setFirstName("Sven");
p.setAge(22);
// Save
mongoOps.save(p);
log.debug("Saved: " + p);
// Find
p = mongoOps.findOne(query(whereId().is(p.getId())), Person.class);
log.debug("Found: " + p);
// Update age to 24 for Sven
mongoOps.updateFirst(query(where("firstName").is("Sven")), update("age", 24));
p = mongoOps.findOne(query(whereId().is(p.getId())), Person.class);
log.debug("Updated: " + p);
// Delete
mongoOps.remove(p);
// Check that deletion worked
List&lt;Person&gt; people = mongoOps.getCollection(Person.class);
log.debug("Number of people = : " + people.size());
mongo</programlisting>
}</programlisting>
<para>This would produce the following log output (including some debug
message from MongoTemplate itself)</para>
<programlisting>Saved: PersonWithIdPropertyOfTypeString [id=4d9e82ac94fa72c65a9e7d5f, firstName=Sven, age=22]
findOne using query: { "_id" : { "$oid" : "4d9e82ac94fa72c65a9e7d5f"}} in db.collection: database.personexample
Found: PersonWithIdPropertyOfTypeString [id=4d9e82ac94fa72c65a9e7d5f, firstName=Sven, age=22]
findOne using query: { "_id" : { "$oid" : "4d9e82ac94fa72c65a9e7d5f"}} in db.collection: database.personexample
Updated: PersonWithIdPropertyOfTypeString [id=4d9e82ac94fa72c65a9e7d5f, firstName=Sven, age=24]
remove using query: { "_id" : { "$oid" : "4d9e82ac94fa72c65a9e7d5f"}}
Number of people = : 0</programlisting>
<para>There was implicit conversion using SimpleMongoConverter between a
String and ObjectId as stored in the database.</para>
<section>
<title>Methods for saving documents</title>
@@ -444,14 +482,14 @@ mongo</programlisting>
MongoTemplate</title>
<programlisting language="java">import static org.springframework.data.document.mongodb.query.Criteria.where;
import static org.springframework.data.document.mongodb.query.Criteria.query;
...
Person p = new Person("Bob", 33);
mongoTemplate.insert("MyCollection", p);
Person qp = mongoTemplate.findOne("MyCollection",
new Query(where("id").is(p.getId())), Person.class);
Person qp = mongoTemplate.findOne("MyCollection", query(where("id").is(p.getId())), Person.class);
</programlisting>
</example>