Skip to content

Commit e987a85

Browse files
committed
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: spring-projects#411.
1 parent 3c16b4d commit e987a85

File tree

7 files changed

+31
-21
lines changed

7 files changed

+31
-21
lines changed

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DocumentTestUtils.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,18 @@ public static Document getAsDocument(Document source, String key) {
4949
/**
5050
* Expects the field with the given key to be not {@literal null} and a {@link BasicDBList}.
5151
*
52-
* @param source the {@link Document} to lookup the {@link BasicDBList} in
53-
* @param key the key of the field to find the {@link BasicDBList} in
52+
* @param source the {@link Document} to lookup the {@link List} in
53+
* @param key the key of the field to find the {@link List} in
5454
* @return
5555
*/
56-
public static List<Object> getAsDBList(Document source, String key) {
56+
public static <T> List<T> getAsDBList(Document source, String key) {
5757
return getTypedValue(source, key, List.class);
5858
}
5959

6060
/**
6161
* Expects the list element with the given index to be a non-{@literal null} {@link Document} and returns it.
6262
*
63-
* @param source the {@link BasicDBList} to look up the {@link Document} element in
63+
* @param source the {@link List} to look up the {@link Document} element in
6464
* @param index the index of the element expected to contain a {@link Document}
6565
* @return
6666
*/

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -3482,7 +3482,7 @@ public void onBeforeSave(BeforeSaveEvent<Document> event) {
34823482

34833483
Document document = new Document();
34843484

3485-
template.insertAll(Arrays.asList(document));
3485+
template.insertAll(Collections.singletonList(document));
34863486

34873487
assertThat(document.id, is(notNullValue()));
34883488
}
@@ -3492,9 +3492,9 @@ public void onBeforeSave(BeforeSaveEvent<Document> event) {
34923492
* @see DATAMONGO-1509
34933493
*/
34943494
@Test
3495-
public void findsByGnericNestedListElements() {
3495+
public void findsByGenericNestedListElements() {
34963496

3497-
List<Model> modelList = Arrays.<Model>asList(new ModelA("value"));
3497+
List<Model> modelList = Collections.singletonList(new ModelA("value"));
34983498
DocumentWithCollection dwc = new DocumentWithCollection(modelList);
34993499

35003500
template.insert(dwc);

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java

+7-8
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public void updateMapperRetainsTypeInformationForCollectionField() {
102102
Document push = getAsDocument(mappedObject, "$push");
103103
Document list = getAsDocument(push, "aliased");
104104

105-
assertThat(list.get("_class"), is(ConcreteChildClass.class.getName()));
105+
assertTypeHint(list, ConcreteChildClass.class);
106106
}
107107

108108
/**
@@ -119,7 +119,7 @@ public void updateMapperShouldRetainTypeInformationForNestedEntities() {
119119

120120
Document set = getAsDocument(mappedObject, "$set");
121121
Document modelDocument = (Document) set.get("model");
122-
assertThat(modelDocument.get("_class"), not(nullValue()));
122+
assertTypeHint(modelDocument, ModelImpl.class);
123123
}
124124

125125
/**
@@ -168,7 +168,7 @@ public void updateMapperShouldRetainTypeInformationForNestedCollectionElements()
168168

169169
Document set = getAsDocument(mappedObject, "$set");
170170
Document modelDocument = getAsDocument(set, "aliased.$");
171-
assertThat(modelDocument.get("_class"), is(ConcreteChildClass.class.getName()));
171+
assertTypeHint(modelDocument, ConcreteChildClass.class);
172172
}
173173

174174
/**
@@ -205,8 +205,8 @@ public void updateMapperShouldWriteTypeInformationForComplexNestedCollectionElem
205205

206206
Document someObject = getAsDocument(document, "aliased.$.someObject");
207207
assertThat(someObject, is(notNullValue()));
208-
assertThat(someObject.get("_class"), is(ConcreteChildClass.class.getName()));
209208
assertThat(someObject.get("value"), is("bubu"));
209+
assertTypeHint(someObject, ConcreteChildClass.class);
210210
}
211211

212212
/**
@@ -276,9 +276,9 @@ public void updateMapperShouldRetainClassInformationForPushCorrectlyWhenCalledWi
276276

277277
Document push = getAsDocument(mappedObject, "$push");
278278
Document model = getAsDocument(push, "models");
279-
List<Object> each = getAsDBList(model, "$each");
279+
List<Document> each = getAsDBList(model, "$each");
280280

281-
assertThat(((Document) each.get(0)).get("_class").toString(), equalTo(ListModel.class.getName()));
281+
assertTypeHint(each.get(0), ListModel.class);
282282
}
283283

284284
/**
@@ -566,8 +566,7 @@ public void doesNotConvertRawDocuments() {
566566
List each = getAsDBList(values, "$each");
567567

568568
for (Object updateValue : each) {
569-
assertThat(((Document) updateValue).get("_class").toString(),
570-
equalTo("org.springframework.data.mongodb.core.convert.UpdateMapperUnitTests$ModelImpl"));
569+
assertTypeHint((Document) updateValue, ModelImpl.class);
571570
}
572571
}
573572

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTests.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static org.hamcrest.core.Is.*;
2020
import static org.hamcrest.core.IsEqual.*;
2121
import static org.junit.Assert.*;
22+
import static org.springframework.data.mongodb.core.DocumentTestUtils.assertTypeHint;
2223
import static org.springframework.data.mongodb.core.query.Criteria.*;
2324
import static org.springframework.data.mongodb.core.query.Query.*;
2425

@@ -421,9 +422,9 @@ private void comparePersonAndDocument(PersonPojoStringId p, PersonPojoStringId p
421422
assertEquals(p.getId(), p2.getId());
422423
assertEquals(p.getText(), p2.getText());
423424

424-
assertEquals("org.springframework.data.mongodb.core.mapping.PersonPojoStringId", document.get("_class"));
425425
assertEquals("1", document.get("_id"));
426426
assertEquals("Text", document.get("text"));
427+
assertTypeHint(document, PersonPojoStringId.class);
427428
}
428429

429430
@Data

src/main/asciidoc/new-features.adoc

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
[[new-features]]
22
= New & Noteworthy
33

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

src/main/asciidoc/reference/mongo-repositories.adoc

+2
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ NOTE: Note that for version 1.0 we currently don't support referring to paramete
273273
| `{"location" : {"$exists" : exists }}`
274274
|===
275275

276+
NOTE: If the property criterion compares a document, the order of the fields and exact equality in the document matters.
277+
276278
[[mongodb.repositories.queries.delete]]
277279
=== Repository delete queries
278280

src/main/asciidoc/reference/mongodb.adoc

+7-5
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,8 @@ When querying and updating `MongoTemplate` will use the converter to handle conv
666666

667667
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.
668668

669-
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.
669+
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.
670+
670671

671672
.Type mapping
672673
====
@@ -685,13 +686,14 @@ sample.value = new Person();
685686
686687
mongoTemplate.save(sample);
687688
688-
{ "_class" : "com.acme.Sample",
689-
"value" : { "_class" : "com.acme.Person" }
689+
{
690+
"value" : { "_class" : "com.acme.Person" },
691+
"_class" : "com.acme.Sample"
690692
}
691693
----
692694
====
693695

694-
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.
696+
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.
695697

696698
==== Customizing type mapping
697699

@@ -1053,7 +1055,7 @@ As you can see most methods return the `Criteria` object to provide a fluent sty
10531055
* `Criteria` *gte* `(Object o)` Creates a criterion using the `$gte` operator
10541056
* `Criteria` *in* `(Object... o)` Creates a criterion using the `$in` operator for a varargs argument.
10551057
* `Criteria` *in* `(Collection<?> collection)` Creates a criterion using the `$in` operator using a collection
1056-
* `Criteria` *is* `(Object o)` Creates a criterion using the `$is` operator
1058+
* `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.
10571059
* `Criteria` *lt* `(Object o)` Creates a criterion using the `$lt` operator
10581060
* `Criteria` *lte* `(Object o)` Creates a criterion using the `$lte` operator
10591061
* `Criteria` *mod* `(Number value, Number remainder)` Creates a criterion using the `$mod` operator

0 commit comments

Comments
 (0)