DATAMONGO-1998 - Fix Querydsl id handling for nested property references using ObjectId hex String representation.

We now follow the conversion rules for id properties with a valid ObjectId representation when parsing Querydsl queries.

Original pull request: #567.
This commit is contained in:
Christoph Strobl
2018-06-06 09:36:15 +02:00
committed by Mark Paluch
parent 06622bed35
commit fe43ba470b
2 changed files with 76 additions and 4 deletions

View File

@@ -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)

View File

@@ -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<Outer> 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<Outer> 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;
}
}