DATAMONGO-1509 - Polishing.

Adopt type hint assertion for existing _class field checks. Simplify test code to use Collections.singletonList instead of Arrays.asList. Replace BasicDBList with List in JavaDoc. Use type inference for DocumentTestUtils.getAsDBList to avoid casts in test code. Extend documentation.

Original pull request: #411.
This commit is contained in:
Mark Paluch
2016-11-17 15:10:51 +01:00
parent 3c16b4db7f
commit e987a853ac
7 changed files with 31 additions and 21 deletions

View File

@@ -49,18 +49,18 @@ public abstract class DocumentTestUtils {
/**
* Expects the field with the given key to be not {@literal null} and a {@link BasicDBList}.
*
* @param source the {@link Document} to lookup the {@link BasicDBList} in
* @param key the key of the field to find the {@link BasicDBList} in
* @param source the {@link Document} to lookup the {@link List} in
* @param key the key of the field to find the {@link List} in
* @return
*/
public static List<Object> getAsDBList(Document source, String key) {
public static <T> List<T> getAsDBList(Document source, String key) {
return getTypedValue(source, key, List.class);
}
/**
* Expects the list element with the given index to be a non-{@literal null} {@link Document} and returns it.
*
* @param source the {@link BasicDBList} to look up the {@link Document} element in
* @param source the {@link List} to look up the {@link Document} element in
* @param index the index of the element expected to contain a {@link Document}
* @return
*/

View File

@@ -3482,7 +3482,7 @@ public class MongoTemplateTests {
Document document = new Document();
template.insertAll(Arrays.asList(document));
template.insertAll(Collections.singletonList(document));
assertThat(document.id, is(notNullValue()));
}
@@ -3492,9 +3492,9 @@ public class MongoTemplateTests {
* @see DATAMONGO-1509
*/
@Test
public void findsByGnericNestedListElements() {
public void findsByGenericNestedListElements() {
List<Model> modelList = Arrays.<Model>asList(new ModelA("value"));
List<Model> modelList = Collections.singletonList(new ModelA("value"));
DocumentWithCollection dwc = new DocumentWithCollection(modelList);
template.insert(dwc);

View File

@@ -102,7 +102,7 @@ public class UpdateMapperUnitTests {
Document push = getAsDocument(mappedObject, "$push");
Document list = getAsDocument(push, "aliased");
assertThat(list.get("_class"), is(ConcreteChildClass.class.getName()));
assertTypeHint(list, ConcreteChildClass.class);
}
/**
@@ -119,7 +119,7 @@ public class UpdateMapperUnitTests {
Document set = getAsDocument(mappedObject, "$set");
Document modelDocument = (Document) set.get("model");
assertThat(modelDocument.get("_class"), not(nullValue()));
assertTypeHint(modelDocument, ModelImpl.class);
}
/**
@@ -168,7 +168,7 @@ public class UpdateMapperUnitTests {
Document set = getAsDocument(mappedObject, "$set");
Document modelDocument = getAsDocument(set, "aliased.$");
assertThat(modelDocument.get("_class"), is(ConcreteChildClass.class.getName()));
assertTypeHint(modelDocument, ConcreteChildClass.class);
}
/**
@@ -205,8 +205,8 @@ public class UpdateMapperUnitTests {
Document someObject = getAsDocument(document, "aliased.$.someObject");
assertThat(someObject, is(notNullValue()));
assertThat(someObject.get("_class"), is(ConcreteChildClass.class.getName()));
assertThat(someObject.get("value"), is("bubu"));
assertTypeHint(someObject, ConcreteChildClass.class);
}
/**
@@ -276,9 +276,9 @@ public class UpdateMapperUnitTests {
Document push = getAsDocument(mappedObject, "$push");
Document model = getAsDocument(push, "models");
List<Object> each = getAsDBList(model, "$each");
List<Document> each = getAsDBList(model, "$each");
assertThat(((Document) each.get(0)).get("_class").toString(), equalTo(ListModel.class.getName()));
assertTypeHint(each.get(0), ListModel.class);
}
/**
@@ -566,8 +566,7 @@ public class UpdateMapperUnitTests {
List each = getAsDBList(values, "$each");
for (Object updateValue : each) {
assertThat(((Document) updateValue).get("_class").toString(),
equalTo("org.springframework.data.mongodb.core.convert.UpdateMapperUnitTests$ModelImpl"));
assertTypeHint((Document) updateValue, ModelImpl.class);
}
}

View File

@@ -19,6 +19,7 @@ import static org.hamcrest.collection.IsCollectionWithSize.*;
import static org.hamcrest.core.Is.*;
import static org.hamcrest.core.IsEqual.*;
import static org.junit.Assert.*;
import static org.springframework.data.mongodb.core.DocumentTestUtils.assertTypeHint;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.core.query.Query.*;
@@ -421,9 +422,9 @@ public class ApplicationContextEventTests {
assertEquals(p.getId(), p2.getId());
assertEquals(p.getText(), p2.getText());
assertEquals("org.springframework.data.mongodb.core.mapping.PersonPojoStringId", document.get("_class"));
assertEquals("1", document.get("_id"));
assertEquals("Text", document.get("text"));
assertTypeHint(document, PersonPojoStringId.class);
}
@Data

View File

@@ -1,6 +1,12 @@
[[new-features]]
= New & Noteworthy
[[new-features.2-0-0]]
== What's new in Spring Data MongoDB 2.0
* Upgrade to Java 8.
* Usage of the `Document` API instead of `DBObject`.
* <<mongo.reactive>>.
[[new-features.1-10-0]]
== What's new in Spring Data MongoDB 1.10
* Support for `$min`, `$max` and `$slice` operators via `Update`.

View File

@@ -273,6 +273,8 @@ NOTE: Note that for version 1.0 we currently don't support referring to paramete
| `{"location" : {"$exists" : exists }}`
|===
NOTE: If the property criterion compares a document, the order of the fields and exact equality in the document matters.
[[mongodb.repositories.queries.delete]]
=== Repository delete queries

View File

@@ -666,7 +666,8 @@ When querying and updating `MongoTemplate` will use the converter to handle conv
As MongoDB collections can contain documents that represent instances of a variety of types. A great example here is if you store a hierarchy of classes or simply have a class with a property of type `Object`. In the latter case the values held inside that property have to be read in correctly when retrieving the object. Thus we need a mechanism to store type information alongside the actual document.
To achieve that the `MappingMongoConverter` uses a `MongoTypeMapper` abstraction with `DefaultMongoTypeMapper` as it's main implementation. Its default behavior is storing the fully qualified classname under `_class` inside the document for the top-level document as well as for every value if it's a complex type and a subtype of the property type declared.
To achieve that the `MappingMongoConverter` uses a `MongoTypeMapper` abstraction with `DefaultMongoTypeMapper` as it's main implementation. Its default behavior is storing the fully qualified classname under `_class` inside the document. Type hints are written for top-level documents as well as for every value if it's a complex type and a subtype of the property type declared.
.Type mapping
====
@@ -685,13 +686,14 @@ sample.value = new Person();
mongoTemplate.save(sample);
{ "_class" : "com.acme.Sample",
"value" : { "_class" : "com.acme.Person" }
{
"value" : { "_class" : "com.acme.Person" },
"_class" : "com.acme.Sample"
}
----
====
As you can see we store the type information for the actual root class persistent as well as for the nested type as it is complex and a subtype of `Contact`. So if you're now using `mongoTemplate.findAll(Object.class, "sample")` we are able to find out that the document stored shall be a `Sample` instance. We are also able to find out that the value property shall be a `Person` actually.
As you can see we store the type information as last field for the actual root class as well as for the nested type as it is complex and a subtype of `Contact`. So if you're now using `mongoTemplate.findAll(Object.class, "sample")` we are able to find out that the document stored shall be a `Sample` instance. We are also able to find out that the value property shall be a `Person` actually.
==== Customizing type mapping
@@ -1053,7 +1055,7 @@ As you can see most methods return the `Criteria` object to provide a fluent sty
* `Criteria` *gte* `(Object o)` Creates a criterion using the `$gte` operator
* `Criteria` *in* `(Object... o)` Creates a criterion using the `$in` operator for a varargs argument.
* `Criteria` *in* `(Collection<?> collection)` Creates a criterion using the `$in` operator using a collection
* `Criteria` *is* `(Object o)` Creates a criterion using the `$is` operator
* `Criteria` *is* `(Object o)` Creates a criterion using field matching (`{ key:value }`). If the specified value is a document, the order of the fields and exact equality in the document matters.
* `Criteria` *lt* `(Object o)` Creates a criterion using the `$lt` operator
* `Criteria` *lte* `(Object o)` Creates a criterion using the `$lte` operator
* `Criteria` *mod* `(Number value, Number remainder)` Creates a criterion using the `$mod` operator