Skip to content

Commit

Permalink
DATAMONGO-893 - Converter must not write "_class" information for kno…
Browse files Browse the repository at this point in the history
…w types.

We now actively pass on property type information to MetadataBackedField to ensure type hints get picked up correctly when converting a value to the according DBObject.

This has to be done as the fix for DATAMONGO-812 enforced proper writing of _class information for Updates, which caused trouble when querying documents by nested (complex) properties using an 'in' clause.

Original pull request: #169.
  • Loading branch information
christophstrobl authored and odrotbohm committed Apr 15, 2014
1 parent 31a4bf9 commit 86670cd
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 6 deletions.
Expand Up @@ -919,7 +919,7 @@ public Object convertToMongoType(Object obj, TypeInformation<?> typeInformation)
return getPotentiallyConvertedSimpleWrite(obj);
}

TypeInformation<?> typeHint = typeInformation == null ? null : ClassTypeInformation.OBJECT;
TypeInformation<?> typeHint = typeInformation == null ? ClassTypeInformation.OBJECT : typeInformation;

if (obj instanceof BasicDBList) {
return maybeConvertList((BasicDBList) obj, typeHint);
Expand Down
Expand Up @@ -306,7 +306,7 @@ protected Object convertSimpleOrDBObject(Object source, MongoPersistentEntity<?>
* @return the converted mongo type or null if source is null
*/
protected Object delegateConvertToMongoType(Object source, MongoPersistentEntity<?> entity) {
return converter.convertToMongoType(source);
return converter.convertToMongoType(source, entity == null ? null : entity.getTypeInformation());
}

protected Object convertAssociation(Object source, Field field) {
Expand Down Expand Up @@ -611,6 +611,21 @@ protected static class MetadataBackedField extends Field {
*/
public MetadataBackedField(String name, MongoPersistentEntity<?> entity,
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> context) {
this(name, entity, context, null);
}

/**
* Creates a new {@link MetadataBackedField} with the given name, {@link MongoPersistentEntity} and
* {@link MappingContext} with the given {@link MongoPersistentProperty}.
*
* @param name must not be {@literal null} or empty.
* @param entity must not be {@literal null}.
* @param context must not be {@literal null}.
* @param property may be {@literal null}.
*/
public MetadataBackedField(String name, MongoPersistentEntity<?> entity,
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> context,
MongoPersistentProperty property) {

super(name);

Expand All @@ -620,7 +635,7 @@ public MetadataBackedField(String name, MongoPersistentEntity<?> entity,
this.mappingContext = context;

this.path = getPath(name);
this.property = path == null ? null : path.getLeafProperty();
this.property = path == null ? property : path.getLeafProperty();
this.association = findAssociation();
}

Expand All @@ -630,7 +645,7 @@ public MetadataBackedField(String name, MongoPersistentEntity<?> entity,
*/
@Override
public MetadataBackedField with(String name) {
return new MetadataBackedField(name, entity, mappingContext);
return new MetadataBackedField(name, entity, mappingContext, property);
}

/*
Expand Down
Expand Up @@ -1398,6 +1398,7 @@ public void writesProjectingTypeCorrectly() {

/**
* @see DATAMONGO-812
* @see DATAMONGO-893
*/
@Test
public void convertsListToBasicDBListAndRetainsTypeInformationForComplexObjects() {
Expand All @@ -1407,7 +1408,7 @@ public void convertsListToBasicDBListAndRetainsTypeInformationForComplexObjects(
address.street = "Foo";

Object result = converter.convertToMongoType(Collections.singletonList(address),
ClassTypeInformation.from(Address.class));
ClassTypeInformation.from(InterfaceType.class));

assertThat(result, is(instanceOf(BasicDBList.class)));

Expand Down Expand Up @@ -1833,7 +1834,11 @@ void method() {
abstract void method();
}

static class Address {
static interface InterfaceType {

}

static class Address implements InterfaceType {
String street;
String city;
}
Expand Down
Expand Up @@ -39,6 +39,7 @@
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.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
Expand Down Expand Up @@ -568,10 +569,42 @@ public void queryMapperShouldBeAbleToProcessQueriesThatIncludeDbRefFields() {
assertThat(mappedFields, is(notNullValue()));
}

/**
* @see DATAMONGO-893
*/
@Test
public void classInformationShouldNotBePresentInDBObjectUsedInFinderMethods() {

EmbeddedClass embedded = new EmbeddedClass();
embedded.id = "1";

EmbeddedClass embedded2 = new EmbeddedClass();
embedded2.id = "2";
Query query = query(where("embedded").in(Arrays.asList(embedded, embedded2)));

DBObject dbo = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(Foo.class));
assertThat(dbo.toString(), equalTo("{ \"embedded\" : { \"$in\" : [ { \"_id\" : \"1\"} , { \"_id\" : \"2\"}]}}"));
}

@Document
public class Foo {
@Id private ObjectId id;
EmbeddedClass embedded;
}

public class EmbeddedClass {
public String id;
}

class IdWrapper {
Object id;
}

class ClassWithEmbedded {
@Id String id;
Sample sample;
}

class ClassWithDefaultId {

String id;
Expand Down
Expand Up @@ -863,4 +863,21 @@ public void deleteByUsingAnnotatedQueryShouldRemoveElementsMatchingDerivedQuery(
public void deleteByUsingAnnotatedQueryShouldReturnNumberOfDocumentsRemovedIfReturnTypeIsLong() {
assertThat(repository.removePersonByLastnameUsingAnnotatedQuery("Beauford"), is(1L));
}

/**
* @see DATAMONGO-893
*/
@Test
public void findByNestedPropertyInCollectionShouldFindMatchingDocuments() {

Person p = new Person("Mary", "Poppins");
Address adr = new Address("some", "2", "where");
p.setAddress(adr);

repository.save(p);

Page<Person> result = repository.findByAddressIn(Arrays.asList(adr), new PageRequest(0, 10));

assertThat(result.getContent(), hasSize(1));
}
}
Expand Up @@ -286,4 +286,8 @@ public interface PersonRepository extends MongoRepository<Person, String>, Query
@Query(value = "{ 'lastname' : ?0 }", delete = true)
Long removePersonByLastnameUsingAnnotatedQuery(String lastname);

/**
* @see DATAMONGO-893
*/
Page<Person> findByAddressIn(List<Address> address, Pageable page);
}

0 comments on commit 86670cd

Please sign in to comment.