From 0ad0dad124df401729d7072487b8712ae3329b5b Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 20 Dec 2011 18:20:59 +0100 Subject: [PATCH] DATAMONGO-330 - Updated reference documentation regarding custom converters. Documented classpath scanning feature of custom converters (DATAMONGO-301). Documented converter disambiguation using @ReadingConverter, @WritingConverter (DATACMNS-113, DATAMONGO-342). Fixed some code formatting on the way. --- src/docbkx/reference/mongodb.xml | 130 ++++++++++++++++++++----------- 1 file changed, 84 insertions(+), 46 deletions(-) diff --git a/src/docbkx/reference/mongodb.xml b/src/docbkx/reference/mongodb.xml index 0aca33c86..6462081fa 100644 --- a/src/docbkx/reference/mongodb.xml +++ b/src/docbkx/reference/mongodb.xml @@ -1035,9 +1035,11 @@ DEBUG work.data.mongodb.core.MongoTemplate: 823 - remove using query: { "id" : " INFO org.spring.example.MongoApp: 46 - Number of people = : 0 DEBUG work.data.mongodb.core.MongoTemplate: 376 - Dropped collection [database.person] - There was implicit conversion using the MongoConverter between a - String and ObjectId as stored in the database and recognizing a convention - of the property "Id" name. + There was implicit conversion using the + MongoConverter between a + String and ObjectId as + stored in the database and recognizing a convention of the property "Id" + name. This example is meant to show the use of save, update and remove @@ -1087,9 +1089,9 @@ DEBUG work.data.mongodb.core.MongoTemplate: 376 - Dropped collection [database.p will be converted to and stored as an ObjectId if possible using a Spring Converter<String, ObjectId>. - Valid conversion rules are delegated to the MongoDB Java driver. If it - cannot be converted to an ObjectId, then the value will be stored as - a string in the database. + Valid conversion rules are delegated to the MongoDB Java driver. If + it cannot be converted to an ObjectId, then the value will be stored + as a string in the database. @@ -1402,22 +1404,26 @@ import static org.springframework.data.mongodb.core.query.Update;
Finding and Upserting documents in a collection - The findAndModify method on DBCollection can update a document and - return either the old or newly updated document in a single operation. - MongoTemplate provides a findAndModify method that takes Query and - Update classes and converts from DBObject to your POJOs. Here are the + The findAndModify(…) method on + DBCollection can update a document and return either the old or newly + updated document in a single operation. + MongoTemplate provides a findAndModify method + that takes Query and + Update classes and converts from + DBObject to your POJOs. Here are the methods - <T> T findAndModify(Query query, Update update, Class<T> entityClass); + <T> T findAndModify(Query query, Update update, Class<T> entityClass); - <T> T findAndModify(Query query, Update update, Class<T> entityClass, String collectionName); +<T> T findAndModify(Query query, Update update, Class<T> entityClass, String collectionName); - <T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass); +<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass); - <T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass, String collectionName); +<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass, String collectionName); - As an example usage, we will insert of few Person objects into the - container and perform a simple findAndUpdate operation + As an example usage, we will insert of few + Person objects into the container and perform a + simple findAndUpdate operation mongoTemplate.insert(new Person("Tom", 21)); mongoTemplate.insert(new Person("Dick", 22)); @@ -1819,7 +1825,8 @@ import static org.springframework.data.mongodb.core.query.Query.query; are available on the Criteria class. There are also a few shape classes, Box, Circle, and Point that are - used in conjunction with geospatial related Criteria methods. + used in conjunction with geospatial related + Criteria methods. To understand how to perform GeoSpatial queries we will use the following Venue class taken from the integration tests.which relies on @@ -1982,43 +1989,34 @@ GeoResults<Restaurant> = operations.geoNear(query, Restaurant.class); The reduce function that will sum up the occurance of each +} The reduce function that will sum up the occurance of each letter across all the documents is shown below function (key, values) { var sum = 0; for (var i = 0; i < values.length; i++) sum += values[i]; return sum; -} - Executing this will result in a collection as shown below. - -{ "_id" : "a", "value" : 1 } +} Executing this will result in a collection as shown below. + { "_id" : "a", "value" : 1 } { "_id" : "b", "value" : 2 } { "_id" : "c", "value" : 2 } -{ "_id" : "d", "value" : 1 } - Assuming that the map and reduce functions are located in - map.js and reduce.js and bundled in your jar so they are available on - the classpath, you can execute a map-reduce operation and obtain the - results as shown below -MapReduceResults<ValueObject> results = mongoOperations.mapReduce("jmr1", "classpath:map.js", "classpath:reduce.js", ValueObject.class); +{ "_id" : "d", "value" : 1 } Assuming that the map and reduce + functions are located in map.js and reduce.js and bundled in your jar so + they are available on the classpath, you can execute a map-reduce + operation and obtain the results as shown below MapReduceResults<ValueObject> results = mongoOperations.mapReduce("jmr1", "classpath:map.js", "classpath:reduce.js", ValueObject.class); for (ValueObject valueObject : results) { System.out.println(valueObject); -} - The output of the above code is -ValueObject [id=a, value=1.0] +} The output of the above code is ValueObject [id=a, value=1.0] ValueObject [id=b, value=2.0] ValueObject [id=c, value=2.0] -ValueObject [id=d, value=1.0] - The MapReduceResults class implements - Iterable and provides access to the raw output, - as well as timing and count statistics. The +ValueObject [id=d, value=1.0] The MapReduceResults class + implements Iterable and provides access to the + raw output, as well as timing and count statistics. The ValueObject class is simply -public class ValueObject { + language="java">public class ValueObject { private String id; - private float value; public String getId() { @@ -2257,11 +2255,14 @@ public class PersonWriteConverter implements Converter<Person, DBObject> {
Registering Spring Converters with the MongoConverter - The mongo XSD namespace provides a convenience way to register - Spring Converters as shown below as well as configuring it into a - MongoTemplate. + The Mongo Spring namespace provides a convenience way to register + Spring Converters with the + MappingMongoConverter. The configuration snippet + below shows how to manually register converter beans as well as + configuring the wrapping MappingMongoConverter + into a MongoTemplate. - <mongo:db-factory dbname="database"/> + <mongo:db-factory dbname="database"/> <mongo:mapping-converter> <mongo:custom-converters> @@ -2277,8 +2278,46 @@ public class PersonWriteConverter implements Converter<Person, DBObject> { <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/> <constructor-arg name="mongoConverter" ref="mappingConverter"/> -</bean> - +</bean> + + You can also use the base-package attribute of the + custom-converters element to enable classpath scanning for all + Converter and + GenericConverter implementations below + the given package. + + <mongo:mapping-converter> + <mongo:custom-converters base-package="com.acme.**.converters" /> +</mongo:mapping-converter> +
+ +
+ Converter disambiguation + + Generally we inspect the Converter + implementations for the source and target types they convert from and + to. Depending on whether one of those is a type MongoDB can handle + natively we will register the converter instance as reading or writing + one. Have a look at the following samples: + + // Write converter as only the target type is one Mongo can handle natively +class MyConverter implements Converter<Person, String> { … } + +// Read converter as only the source type is one Mongo can handle natively +class MyConverter implements Converter<String, Person> { … } + + In case you write a Converter whose + source and target type are native Mongo types there's no way for us to + determine whether we should consider it as reading or writing converter. + Registering the converter instance as both might lead to unwanted + results then. E.g. a Converter<String, + Long> is ambiguous although it probably does not make + sense to try to convert all Strings into + Longs when writing. To be generally able to force + the infrastructure to register a converter for one way only we provide + @ReadingConverter as well as + @WritingConverter to be used at the + converter implementation.
@@ -2308,7 +2347,6 @@ public class PersonWriteConverter implements Converter<Person, DBObject> { void resetIndexCache(); List<IndexInfo> getIndexInfo(); - }