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 d2f0dfef1..2ab007824 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 @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * Copyright 2011-2018 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. @@ -20,6 +20,7 @@ import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; +import com.mongodb.util.JSON; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.convert.QueryMapper; @@ -40,7 +41,7 @@ import com.querydsl.mongodb.MongodbSerializer; /** * Custom {@link MongodbSerializer} to take mapping information into account when building keys for constraints. - * + * * @author Oliver Gierke * @author Christoph Strobl */ @@ -64,7 +65,7 @@ class SpringDataMongodbSerializer extends MongodbSerializer { /** * Creates a new {@link SpringDataMongodbSerializer} for the given {@link MappingContext}. - * + * * @param mappingContext must not be {@literal null}. */ public SpringDataMongodbSerializer(MongoConverter converter) { @@ -115,12 +116,29 @@ class SpringDataMongodbSerializer extends MongodbSerializer { @Override protected DBObject asDBObject(String key, Object value) { - if (ID_KEY.equals(key)) { - return mapper.getMappedObject(super.asDBObject(key, value), null); + if (key.endsWith(ID_KEY)) { + return convertId(key, value); } return super.asDBObject(key, value instanceof Pattern ? value : converter.convertToMongoType(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); + + DBObject mappedIdValue = mapper.getMappedObject(super.asDBObject(key, convertedId), + null); + return (DBObject) JSON.parse(JSON.serialize(mappedIdValue)); + } + /* * (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 e4b6ba694..d96efbc67 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; + + } }