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 41897c7d46
commit 3785a52676
2 changed files with 80 additions and 5 deletions

View File

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

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