From fd28ab4d330f7d6bb6b11c27714c2473ef5e6d19 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Fri, 21 Jun 2013 18:57:24 +0200 Subject: [PATCH] DATAMONGO-705 - Fixed handling of DBRefs in QueryMapper. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QueryMapper now converts values to become DBRefs correctly in getMappedKeyword(…). Added an exclusion path for the value handling in case we have an $exists keyword. --- .../mongodb/core/convert/QueryMapper.java | 25 +++++++---- .../core/convert/QueryMapperUnitTests.java | 41 +++++++++++++------ 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index d09e1bde0..b0c286097 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -123,13 +123,13 @@ public class QueryMapper { * @param property * @return */ - public DBObject getMappedKeyword(Keyword keyword, Field property) { + private DBObject getMappedKeyword(Keyword keyword, Field property) { - if (property.isAssociation()) { - convertAssociation(keyword.value, property.getProperty()); - } + boolean needsAssociationConversion = property.isAssociation() && !keyword.isExists(); + Object value = needsAssociationConversion ? convertAssociation(keyword.value, property.getProperty()) + : getMappedValue(keyword.value, property.with(keyword.key)); - return new BasicDBObject(keyword.key, getMappedValue(keyword.value, property.with(keyword.key))); + return new BasicDBObject(keyword.key, value); } /** @@ -196,7 +196,7 @@ public class QueryMapper { } /** - * Converts the given source assuming it's actually an association to anoter object. + * Converts the given source assuming it's actually an association to another object. * * @param source * @param property @@ -256,7 +256,7 @@ public class QueryMapper { String key; Object value; - Keyword(Object source) { + public Keyword(Object source) { Assert.isInstanceOf(DBObject.class, source); @@ -268,6 +268,15 @@ public class QueryMapper { this.value = value.get(key); } + /** + * Returns whether the current keyword is the {@code $exists} keyword. + * + * @return + */ + public boolean isExists() { + return "$exists".equalsIgnoreCase(key); + } + /** * Returns whether the given value actually represents a keyword. If this returns {@literal true} it's safe to call * the constructor. @@ -275,7 +284,7 @@ public class QueryMapper { * @param value * @return */ - static boolean isKeyword(Object value) { + public static boolean isKeyword(Object value) { if (!(value instanceof DBObject)) { return false; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 9f93dc3e6..ec7ac8719 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -37,6 +37,7 @@ import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.DBObjectUtils; import org.springframework.data.mongodb.core.Person; +import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -63,8 +64,7 @@ public class QueryMapperUnitTests { MongoMappingContext context; MappingMongoConverter converter; - @Mock - MongoDbFactory factory; + @Mock MongoDbFactory factory; @Before public void setUp() { @@ -334,7 +334,11 @@ public class QueryMapperUnitTests { DBObject result = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(WithDBRef.class)); DBObject reference = DBObjectUtils.getAsDBObject(result, "reference"); - assertThat(reference.containsField("$in"), is(true)); + + BasicDBList inClause = getAsDBList(reference, "$in"); + assertThat(inClause, hasSize(2)); + assertThat(inClause.get(0), is(instanceOf(com.mongodb.DBRef.class))); + assertThat(inClause.get(1), is(instanceOf(com.mongodb.DBRef.class))); } /** @@ -394,6 +398,22 @@ public class QueryMapperUnitTests { assertThat(mapped.get("_id"), is(instanceOf(ObjectId.class))); } + /** + * @see DATAMONGO-705 + */ + @Test + public void convertsDBRefWithExistsQuery() { + + Query query = query(where("reference").exists(false)); + + BasicMongoPersistentEntity entity = context.getPersistentEntity(WithDBRef.class); + DBObject mappedObject = mapper.getMappedObject(query.getQueryObject(), entity); + + DBObject reference = getAsDBObject(mappedObject, "reference"); + assertThat(reference.containsField("$exists"), is(true)); + assertThat(reference.get("$exists"), is((Object) false)); + } + class IdWrapper { Object id; } @@ -406,14 +426,12 @@ public class QueryMapperUnitTests { class Sample { - @Id - private String foo; + @Id private String foo; } class BigIntegerId { - @Id - private BigInteger id; + @Id private BigInteger id; } enum Enum { @@ -427,14 +445,12 @@ public class QueryMapperUnitTests { class CustomizedField { - @Field("foo") - CustomizedField field; + @Field("foo") CustomizedField field; } class WithDBRef { - @DBRef - Reference reference; + @DBRef Reference reference; } class Reference { @@ -449,7 +465,6 @@ public class QueryMapperUnitTests { class WithMapDBRef { - @DBRef - Map mapWithDBRef; + @DBRef Map mapWithDBRef; } }