diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java index 6fd82e837..d6881341b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java @@ -126,15 +126,30 @@ class SpringDataMongodbSerializer extends MongodbSerializer { value = value instanceof Optional ? ((Optional) value).orElse(null) : value; - if (ID_KEY.equals(key)) { - DBObject superIdValue = super.asDBObject(key, value); - Document mappedIdValue = mapper.getMappedObject((BasicDBObject) superIdValue, Optional.empty()); - return (DBObject) JSON.parse(mappedIdValue.toJson()); + if (key.endsWith(ID_KEY)) { + return convertId(key, value); } return super.asDBObject(key, value instanceof Pattern ? value : toQuerydslMongoType(value)); } + /** + * Convert a given, already known to be an {@literal id} or even a nested document id, value into the according id + * representation following the conversion rules of {@link QueryMapper#convertId(Object)}. + * + * @param key the property path to the given value. + * @param idValue the raw {@literal id} value. + * @return the {@literal id} representation in the required format. + */ + private DBObject convertId(String key, Object idValue) { + + Object convertedId = mapper.convertId(idValue); + + Document mappedIdValue = mapper.getMappedObject((BasicDBObject) super.asDBObject(key, convertedId), + Optional.empty()); + return (DBObject) JSON.parse(mappedIdValue.toJson()); + } + /* * (non-Javadoc) * @see com.querydsl.mongodb.MongodbSerializer#isReference(com.querydsl.core.types.Path) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java index f4990bf9b..acaa18845 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java @@ -18,13 +18,18 @@ package org.springframework.data.mongodb.repository.support; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; +import lombok.Data; + import java.util.Arrays; +import org.bson.types.ObjectId; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.repository.Person; import org.springframework.data.mongodb.repository.QPerson; @@ -49,7 +54,9 @@ public class QuerydslRepositorySupportTests { @Before public void setUp() { + operations.remove(new Query(), Outer.class); operations.remove(new Query(), Person.class); + person = new Person("Dave", "Matthews"); operations.save(person); @@ -97,4 +104,54 @@ public class QuerydslRepositorySupportTests { assertThat(queryUsingIdField.fetchOne(), equalTo(person)); assertThat(queryUsingIdField.fetchOne(), equalTo(queryUsingRefObject.fetchOne())); } + + @Test // DATAMONGO-1998 + public void shouldLeaveStringIdThatIsNoValidObjectIdAsItIs() { + + Outer outer = new Outer(); + outer.id = "outer-1"; + outer.inner = new Inner(); + outer.inner.id = "inner-1"; + outer.inner.value = "go climb a rock"; + + operations.save(outer); + + QQuerydslRepositorySupportTests_Outer o = QQuerydslRepositorySupportTests_Outer.outer; + SpringDataMongodbQuery query = repoSupport.from(o).where(o.inner.id.eq(outer.inner.id)); + + assertThat(query.fetchOne(), equalTo(outer)); + } + + @Test // DATAMONGO-1998 + public void shouldConvertStringIdThatIsAValidObjectIdIntoTheSuch() { + + Outer outer = new Outer(); + outer.id = new ObjectId().toHexString(); + outer.inner = new Inner(); + outer.inner.id = new ObjectId().toHexString(); + outer.inner.value = "eat sleep workout repeat"; + + operations.save(outer); + + QQuerydslRepositorySupportTests_Outer o = QQuerydslRepositorySupportTests_Outer.outer; + SpringDataMongodbQuery query = repoSupport.from(o).where(o.inner.id.eq(outer.inner.id)); + + assertThat(query.fetchOne(), equalTo(outer)); + } + + @Data + @Document + public static class Outer { + + @Id String id; + Inner inner; + } + + @Data + public static class Inner { + + @Id String id; + String value; + + } }