From 478396c503b2e7c0b48728cfc53acfa6bd87ac4c Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Mon, 1 Jul 2013 08:10:13 +0200 Subject: [PATCH] =?UTF-8?q?DATAMONGO-675=20-=20MongoTemplate=20now=20maps?= =?UTF-8?q?=20Update=20in=20findAndModify(=E2=80=A6).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Update object handed to ….findAndModify(…) is now handed through the QueryMapper before being executed. --- .../data/mongodb/core/MongoTemplate.java | 14 ++---- .../data/mongodb/core/query/Update.java | 13 ++--- .../data/mongodb/core/MongoTemplateTests.java | 48 +++++++++++++------ 3 files changed, 46 insertions(+), 29 deletions(-) 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 8ca8b4ba4..3863e55aa 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 @@ -1335,8 +1335,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { /** * 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 MappingMongoConverter will be used. The query document is specified as a standard DBObject - * and so is the fields specification. Can be overridden by subclasses. + * otherwise, an instance of MappingMongoConverter will be used. The query document is specified as a standard + * DBObject and so is the fields specification. Can be overridden by subclasses. * * @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 @@ -1437,19 +1437,15 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { MongoPersistentEntity entity = mappingContext.getPersistentEntity(entityClass); - DBObject updateObj = update.getUpdateObject(); - for (String key : updateObj.keySet()) { - updateObj.put(key, mongoConverter.convertToMongoType(updateObj.get(key))); - } - + DBObject mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), entity); DBObject mappedQuery = mapper.getMappedObject(query, entity); if (LOGGER.isDebugEnabled()) { LOGGER.debug("findAndModify using query: " + mappedQuery + " fields: " + fields + " sort: " + sort - + " for class: " + entityClass + " and update: " + updateObj + " in collection: " + collectionName); + + " for class: " + entityClass + " and update: " + mappedUpdate + " in collection: " + collectionName); } - return executeFindOneInternal(new FindAndModifyCallback(mappedQuery, fields, sort, updateObj, options), + return executeFindOneInternal(new FindAndModifyCallback(mappedQuery, fields, sort, mappedUpdate, options), new ReadDbObjectCallback(readerToUse, entityClass), collectionName); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java index 492e26a68..20b04e815 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java @@ -217,22 +217,23 @@ public class Update { return dbo; } - @SuppressWarnings("unchecked") protected void addMultiFieldOperation(String operator, String key, Object value) { + Object existingValue = this.modifierOps.get(operator); - LinkedHashMap keyValueMap; + DBObject keyValueMap; + if (existingValue == null) { - keyValueMap = new LinkedHashMap(); + keyValueMap = new BasicDBObject(); this.modifierOps.put(operator, keyValueMap); } else { - if (existingValue instanceof LinkedHashMap) { - keyValueMap = (LinkedHashMap) existingValue; + if (existingValue instanceof BasicDBObject) { + keyValueMap = (BasicDBObject) existingValue; } else { throw new InvalidDataAccessApiUsageException("Modifier Operations should be a LinkedHashMap but was " + existingValue.getClass()); } } + keyValueMap.put(key, value); } - } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index 6689ab43e..05c13ffe9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -61,6 +61,7 @@ import org.springframework.data.mongodb.core.index.Index; import org.springframework.data.mongodb.core.index.Index.Duplicates; import org.springframework.data.mongodb.core.index.IndexField; import org.springframework.data.mongodb.core.index.IndexInfo; +import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Criteria; @@ -92,15 +93,12 @@ import com.mongodb.WriteResult; @ContextConfiguration("classpath:infrastructure.xml") public class MongoTemplateTests { - @Autowired - MongoTemplate template; - @Autowired - MongoDbFactory factory; + @Autowired MongoTemplate template; + @Autowired MongoDbFactory factory; MongoTemplate mappingTemplate; - @Rule - public ExpectedException thrown = ExpectedException.none(); + @Rule public ExpectedException thrown = ExpectedException.none(); @Autowired @SuppressWarnings("unchecked") @@ -150,6 +148,7 @@ public class MongoTemplateTests { template.dropCollection(TestClass.class); template.dropCollection(Sample.class); template.dropCollection(MyPerson.class); + template.dropCollection(TypeWithFieldAnnotation.class); template.dropCollection("collection"); template.dropCollection("personX"); } @@ -772,8 +771,7 @@ public class MongoTemplateTests { Query q3 = new Query(Criteria.where("age").in(l1, l2)); template.find(q3, PersonWithIdPropertyOfTypeObjectId.class); Assert.fail("Should have trown an InvalidDocumentStoreApiUsageException"); - } catch (InvalidMongoDbApiUsageException e) { - } + } catch (InvalidMongoDbApiUsageException e) {} } @Test @@ -1625,6 +1623,25 @@ public class MongoTemplateTests { assertThat(template.exists(query, Sample.class, template.getCollectionName(Sample.class)), is(true)); } + /** + * @see DATAMONGO-675 + */ + @Test + public void updateConsidersMappingAnnotations() { + + TypeWithFieldAnnotation entity = new TypeWithFieldAnnotation(); + entity.emailAddress = "old"; + + template.save(entity); + + Query query = query(where("_id").is(entity.id)); + Update update = Update.update("emailAddress", "new"); + + FindAndModifyOptions options = new FindAndModifyOptions().returnNew(true); + TypeWithFieldAnnotation result = template.findAndModify(query, update, options, TypeWithFieldAnnotation.class); + assertThat(result.emailAddress, is("new")); + } + static class MyId { String first; @@ -1633,14 +1650,12 @@ public class MongoTemplateTests { static class TypeWithMyId { - @Id - MyId id; + @Id MyId id; } public static class Sample { - @Id - String id; + @Id String id; String field; } @@ -1697,8 +1712,13 @@ public class MongoTemplateTests { static class VersionedPerson { - @Version - Long version; + @Version Long version; String id, firstname, lastname; } + + static class TypeWithFieldAnnotation { + + @Id ObjectId id; + @Field("email") String emailAddress; + } }