DATADOC-147 - Update reference documentation to cover changes from M2 to M3 (partial work)

This commit is contained in:
Mark Pollack
2011-05-27 16:40:18 -04:00
parent 6a73e94c57
commit e0bd465649
6 changed files with 249 additions and 112 deletions

View File

@@ -25,6 +25,7 @@ import org.springframework.context.annotation.ClassPathScanningCandidateComponen
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.authentication.UserCredentials;
import org.springframework.data.document.mongodb.MongoDbFactory;
import org.springframework.data.document.mongodb.MongoTemplate;
import org.springframework.data.document.mongodb.SimpleMongoDbFactory;
@@ -38,27 +39,37 @@ import org.springframework.util.StringUtils;
@Configuration
public abstract class AbstractMongoConfiguration {
public abstract String defaultDatabaseName();
public abstract String getDatabaseName();
@Bean
public abstract Mongo mongo() throws Exception;
@Bean
public abstract MongoTemplate mongoTemplate() throws Exception;
@Bean
public MongoDbFactory mongoDbFactory() throws Exception {
return new SimpleMongoDbFactory(mongo(), defaultDatabaseName());
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory(), mappingMongoConverter());
}
public String mappingBasePackage() {
@Bean
public MongoDbFactory mongoDbFactory() throws Exception {
if (getUserCredentials() == null) {
return new SimpleMongoDbFactory(mongo(), getDatabaseName());
} else {
return new SimpleMongoDbFactory(mongo(), getDatabaseName(), getUserCredentials());
}
}
public String getMappingBasePackage() {
return "";
}
public UserCredentials getUserCredentials() {
return null;
}
@Bean
public MongoMappingContext mongoMappingContext() throws ClassNotFoundException, LinkageError {
MongoMappingContext mappingContext = new MongoMappingContext();
String basePackage = mappingBasePackage();
String basePackage = getMappingBasePackage();
if (StringUtils.hasText(basePackage)) {
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(false);
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));

View File

@@ -26,7 +26,7 @@ import org.springframework.data.document.mongodb.mapping.event.MongoMappingEvent
public class GeoSpatialAppConfig extends AbstractMongoConfiguration {
@Override
public String defaultDatabaseName() {
public String getDatabaseName() {
return "database";
}
@@ -35,18 +35,13 @@ public class GeoSpatialAppConfig extends AbstractMongoConfiguration {
return new Mongo("localhost");
}
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory());
}
@Bean
public LoggingEventListener<MongoMappingEvent> mappingEventsListener() {
return new LoggingEventListener<MongoMappingEvent>();
}
@Override
public String mappingBasePackage() {
public String getMappingBasePackage() {
return "org.springframework.data.document.mongodb";
}

View File

@@ -12,7 +12,7 @@ import org.springframework.data.document.mongodb.convert.MappingMongoConverter;
public class TestMongoConfiguration extends AbstractMongoConfiguration {
@Override
public String defaultDatabaseName() {
public String getDatabaseName() {
return "database";
}
@@ -21,13 +21,8 @@ public class TestMongoConfiguration extends AbstractMongoConfiguration {
return new Mongo("localhost", 27017);
}
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory());
}
@Override
public String mappingBasePackage() {
public String getMappingBasePackage() {
return "org.springframework.data.document.mongodb.mapping";
}

View File

@@ -4,6 +4,8 @@ import com.mongodb.Mongo;
import org.springframework.context.annotation.Bean;
import org.springframework.data.document.mongodb.MongoTemplate;
import org.springframework.data.document.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.document.mongodb.mapping.event.LoggingEventListener;
import org.springframework.data.document.mongodb.mapping.event.MongoMappingEvent;
public class GeoIndexedAppConfig extends AbstractMongoConfiguration {
@@ -11,7 +13,7 @@ public class GeoIndexedAppConfig extends AbstractMongoConfiguration {
public static String GEO_COLLECTION = "geolocation";
@Override
public String defaultDatabaseName() {
public String getDatabaseName() {
return GEO_DB;
}
@@ -20,13 +22,13 @@ public class GeoIndexedAppConfig extends AbstractMongoConfiguration {
return new Mongo("localhost");
}
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory());
}
public String getMappingBasePackage() {
return "org.springframework.data.document.mongodb.mapping";
}
@Bean
public LoggingEventListener<MongoMappingEvent> mappingEventsListener() {
return new LoggingEventListener<MongoMappingEvent>();
}
}

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<chapter id="mongo.mapping">
<title>Mapping support</title>
<chapter id="mapping-chapter">
<title>Mapping</title>
<para>Rich maping support is provided by the
<classname>MongoMappingConverter</classname>.
@@ -23,15 +23,15 @@
<note>
<para><classname>SimpleMongoConverter</classname> has been deprecated in
Spring Data MongoDB M3 as all of its functionality has been subsumed into
MappingMongoConverter.</para>
<classname>MappingMongoConverter</classname>.</para>
</note>
<section>
<title>Convetion based Mapping</title>
<section id="mapping-conventions">
<title>Convention based Mapping</title>
<para>MongoMappingConverter has a few conventions for mapping objects to
documents when no additional mapping metadata is provided. The conventions
are:</para>
<para><classname>MongoMappingConverter</classname> has a few conventions
for mapping objects to documents when no additional mapping metadata is
provided. The conventions are:</para>
<itemizedlist>
<listitem>
@@ -53,7 +53,8 @@
</listitem>
<listitem>
<para>Public JavaBean properties </para>
<para>The fields of an object are used to convert to and from fields
in the document. Public JavaBean properties are not used.</para>
</listitem>
<listitem>
@@ -70,54 +71,57 @@
<para>Mongo requires that you have an '_id' field for all documents. If
you don't provide one the driver will assign a ObjectId with a generated
value. When using the <classname>MongoMappingConverter</classname> there
are certain rules that govern how properties from the Java class is
mapped to this '_id' field.</para>
value. The "_id" field can be of any type the, other than arrays, so
long as it is unique. The driver naturally supports all primitive types
and Dates. When using the <classname>MongoMappingConverter</classname>
there are certain rules that govern how properties from the Java class
is mapped to this '_id' field.</para>
<para>The following outlines what property will be mapped to the '_id'
<para>The following outlines what field will be mapped to the '_id'
document field:</para>
<para><itemizedlist>
<listitem>
<para>A property or field annotated with
<classname>@Id</classname>
<para>A field annotated with <classname>@Id</classname>
(<classname>org.springframework.data.annotation.Id</classname>)
will be mapped to the '_id' field.</para>
</listitem>
<listitem>
<para>A property or field without an annotation but named
<para>A field without an annotation but named
<classname>id</classname> will be mapped to the '_id'
field.</para>
</listitem>
</itemizedlist></para>
<para>The following outlines what type conversion, if any, will be done
on the property mapped to the _id document field when using the
<classname>MappingMongoConverter</classname>, the default for
<classname>MongoTemplate</classname>.</para>
on the property mapped to the _id document field.</para>
<itemizedlist>
<listitem>
<para>An id property or field declared as a String in the Java class
will be converted to and stored as an ObjectId if possible using a
Spring Converter&lt;String, ObjectId&gt;. Valid conversion rules are
delegated to the Mongo Java driver. If it cannot be converted to an
ObjectId, then the value will be stored as a string in the
database.</para>
<para>If a field named 'id' is declared as a String or BigInteger in
the Java class it will be converted to and stored as an ObjectId if
possible. ObjectId as a field type is also valid. If you specify a
value for 'id' in your application, the conversion to an ObjectId is
delected to the MongoDBdriver. If the specified 'id' value cannot be
converted to an ObjectId, then the value will be stored as is in the
document's _id field.</para>
</listitem>
<listitem>
<para>An id property or field declared as BigInteger in the Java
class will be converted to and stored as an ObjectId using a Spring
Converter&lt;BigInteger, ObjectId&gt;.</para>
<para>If a field named ' id' id field is not declared as a String,
BigInteger, or ObjectID in the Java class then you should assign it
a value in your application so it can be stored 'as-is' in the
document's _id field.</para>
</listitem>
<listitem>
<para>If no field named 'id' is present in the Java class then an
implicit '_id' file will be generated by the driver but not mapped
to a property or field of the Java class.</para>
</listitem>
</itemizedlist>
<para>If no field or property specified above is present in the Java
class then an implicit '_id' file will be generated by the driver but
not mapped to a property or field of the Java class.</para>
<para>When querying and updating <classname>MongoTemplate</classname>
will use the converter to handle conversions of the
<classname>Query</classname> and <classname>Update</classname> objects
@@ -127,13 +131,22 @@
</section>
</section>
<section id="mongodb:mapping-configuration">
<title>MongoDB Mapping Configuration</title>
<section id="mapping-configuration">
<title>Mapping Configuration</title>
<para>You can configure the MongoMappingConverter as well as Mongo and
MongoTemplate eithe using Java or XML based metadata.</para>
<para>Unless explicitly configured, an instance of
<classname>MongoMappingConverter</classname> is created by default when
creating a <classname>MongoTemplate</classname>. You can create your own
instance of the <classname>MappingMongoConverter</classname> so as to tell
it where to scan the classpath at startup your domain classes in order to
extract metadata and construct indexes. Also, by creating your own
instance you can register Spring converters to use for mapping specific
classes to and from the database.</para>
<para>Here is an example using Spring's Java based configuration</para>
<para>You can configure the <classname>MongoMappingConverter</classname>
as well as <classname>com.mongodb.Mongo</classname> and MongoTemplate
either using Java or XML based metadata. Here is an example using Spring's
Java based configuration</para>
<example>
<title>@Configuration class to configure MongoDB mapping support</title>
@@ -145,34 +158,60 @@ public class GeoSpatialAppConfig extends AbstractMongoConfiguration {
public Mongo mongo() throws Exception {
return new Mongo("localhost");
}
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongo(), "geospatial", "newyork", mappingMongoConverter());
}
// specify which package to scan for @Document objects.
public String getMappingBasePackage() {
return "org.springframework.data.document.mongodb";
@Override
public String getDatabaseName() {
return "database";
}
@Override
public String getMappingBasePackage() {
return "com.bigbank.domain";
}
// the following are optional
@Override
protected void afterMappingMongoConverterCreation(MappingMongoConverter converter) {
Set&lt;Converter&lt;?, ?&gt;&gt; converterList = new HashSet&lt;Converter&lt;?, ?&gt;&gt;();
converterList.add(new org.springframework.data.document.mongodb.PersonReadConverter());
converterList.add(new org.springframework.data.document.mongodb.PersonWriteConverter());
converter.setCustomConverters(converterList);
}
// optional
@Bean
public LoggingEventListener&lt;MongoMappingEvent&gt; mappingEventsListener() {
return new LoggingEventListener&lt;MongoMappingEvent&gt;();
}
}</programlisting>
</example>
<para><classname>AbstractMongoConfiguration</classname> requires you to
implement methods that define a <classname>Mongo</classname> as well as a
<classname>MongoTemplate</classname> object to the container.
implement methods that define a <classname>com.mongodb.Mongo</classname>
as well as provide a database name.
<classname>AbstractMongoConfiguration</classname> also has a method you
can override named '<methodname>getMappingBasePackage</methodname>' which
tells the configuration where to scan for classes annotated with the
tells the converter where to scan for classes annotated with the
<classname>@org.springframework.data.document.mongodb.mapping.Document</classname>
annotation.</para>
<para>You can add additional converters to the converter by overriding the
method afterMappingMongoConverterCreation. Also shown in the above example
is a <classname>LoggingEventListener</classname> which logs
<classname>MongoMappingEvent</classname>s that are posted onto Spring's
<interfacename>ApplicationContextEvent</interfacename>
infrastructure.</para>
<note>
<para>AbstractMongoConfiguration will create a MongoTemplate instance
and registered with the container under the name 'mongoTemplate'.</para>
</note>
<para>You can also override the method <literal>UserCredentials
getUserCredentials()</literal> to provide the username and password
information to connect to the database.</para>
<para>Spring's Mongo namespace enables you to easily enable mapping
functionality in XML</para>
@@ -192,7 +231,16 @@ public class GeoSpatialAppConfig extends AbstractMongoConfiguration {
&lt;mongo:mongo host="localhost" port="27017"/&gt;
&lt;!-- by default look for a Mongo object named 'mongo' - default name used for the converter is 'mappingConverter' --&gt;
&lt;mongo:mapping-converter base-package="com.mycompany.domain"/&gt;
&lt;mongo:mapping-converter base-package="com.bigbank.domain"&gt;
&lt;mongo:custom-converters&gt;
&lt;mongo:converter ref="readConverter"/&gt;
&lt;mongo:converter&gt;
&lt;bean class="org.springframework.data.document.mongodb.PersonWriteConverter"/&gt;
&lt;/mongo:converter&gt;
&lt;/mongo:custom-converters&gt;
&lt;/mongo:mapping-converter&gt;
&lt;bean id="readConverter" class="org.springframework.data.document.mongodb.PersonReadConverter"/&gt;
&lt;!-- set the mapping converter to be used by the MongoTemplate --&gt;
&lt;bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate"&gt;
@@ -202,20 +250,20 @@ public class GeoSpatialAppConfig extends AbstractMongoConfiguration {
&lt;constructor-arg name="mongoConverter" ref="mappingConverter"/&gt;
&lt;/bean&gt;
&lt;bean class="org.springframework.data.document.mongodb.mapping.event.LoggingEventListener"/&gt;
&lt;/beans
</programlisting>
</example>
<para>This sets up the right objects in the ApplicationContext to perform
the full gamut of mapping operations. The <code>base-package</code>
property tells it where to scan for classes annotated with the
<para>The <code>base-package</code> property tells it where to scan for
classes annotated with the
<classname>@org.springframework.data.document.mongodb.mapping.Document</classname>
annotation.</para>
</section>
<section id="mongodb:mapping-usage">
<title>Mapping Framework Usage</title>
<section id="mapping-usage">
<title>Metadata based Mapping</title>
<para>To take full advantage of the object mapping functionality inside
the Spring Data/MongoDB support, you should annotate your mapped objects
@@ -240,9 +288,12 @@ public class Person {
@Id
private ObjectId id;
@Indexed
private Integer ssn;
private String firstName;
@Indexed
private String lastName;
@@ -258,11 +309,11 @@ public class Person {
document, making searches faster.</para>
</important>
<section>
<section id="mapping-usage-annotations">
<title>Mapping annotation overview</title>
<para>The MappingMongoConverter relies on metadata to drive the mapping
of objects to documents. An overview of the annotations is provided
<para>The MappingMongoConverter can use metadata to drive the mapping of
objects to documents. An overview of the annotations is provided
below</para>
<itemizedlist>
@@ -381,25 +432,20 @@ public class Person&lt;T extends Address&gt; {
<para></para>
</section>
<section>
<title>Id fields</title>
<para>The @Id annotation is applied to fields. MongoDB lets you store
any type as the _id field in the database, including long and string. It
is of course common to use ObjectId for this purpose. If the value on
the @Id field is not null, it is stored into the database as-is. If it
is null, then the converter will assume you want to store an ObjectId in
the database. For this to work the field type should be either ObjectId,
String, or BigInteger.</para>
</section>
<section id="mongodb:mapping-usage:indexes">
<section id="mapping-usage-indexes">
<title>Compound Indexes</title>
<para>Compound indexes are also supported. They are defined at the class
level, rather than on indidvidual properties. Here's an example that
creates a compound index of <code>lastName</code> in ascending order and
<code>age</code> in descending order: <example>
level, rather than on indidvidual properties. </para>
<note>
<para>Compound indexes are very important to improve the performance
of queries that involve criteria on multiple fields</para>
</note>
<para>Here's an example that creates a compound index of
<code>lastName</code> in ascending order and <code>age</code> in
descending order: <example>
<title>Example Compound Index Usage</title>
<programlisting language="java">package com.mycompany.domain;
@@ -421,7 +467,7 @@ public class Person {
</example></para>
</section>
<section id="mongodb:mapping-usage:references">
<section id="mapping-usage-references">
<title>Using DBRefs</title>
<para>The mapping framework doesn't have to store child objects embedded
@@ -474,7 +520,7 @@ public class Person {
</important></para>
</section>
<section id="mongodb:mapping-usage:events">
<section id="mapping-usage-events">
<title>Mapping Framework Events</title>
<para>Events are fired throughout the lifecycle of the mapping process.
@@ -486,15 +532,18 @@ public class Person {
will cause them to be invoked whenever the event is dispatched.</para>
</section>
<section>
<section id="mapping-explicit-converters">
<title>Overriding Mapping with explicit Converters</title>
<para>When storing and querying your objects it is convenient to have a
<interfacename>MongoConverter</interfacename> instance handle the
mapping of all Java types to DBObjects. However, sometimes you may want
the <interfacename>MongoConverter</interfacename>'s do most of the work
but allow you to selectivly handle the conversion for a particular type.
To do this, register one or more one or more
but allow you to selectivly handle the conversion for a particular type
or to optimize performance. </para>
<para>To selectivly handle the conversion yourself, register one or more
one or more
<classname>org.springframework.core.convert.converter.Converter</classname>
instances with the MongoConverter.</para>
@@ -512,7 +561,37 @@ public class Person {
purpose. The method
<methodname>afterMappingMongoConverterCreation</methodname> in
<classname>AbstractMongoConfiguration</classname> can be overriden to
configure a MappingMongoConverter.</para>
configure a MappingMongoConverter. The examples <link
linkend="???">here</link> at the begining of this chapter show how to
perform the configuration using Java and XML. </para>
<para>Below is an example of a Spring Converter implementation that
converts from a DBObject to a Person POJO.</para>
<programlisting language="java">public class PersonReadConverter implements Converter&lt;DBObject, Person&gt; {
public Person convert(DBObject source) {
Person p = new Person((ObjectId) source.get("_id"), (String) source.get("name"));
p.setAge((Integer) source.get("age"));
return p;
}
}</programlisting>
<para>Here is an example that converts from a Person to a
DBObject.</para>
<programlisting language="java">public class PersonWriteConverter implements Converter&lt;Person, DBObject&gt; {
public DBObject convert(Person source) {
DBObject dbo = new BasicDBObject();
dbo.put("_id", source.getId());
dbo.put("name", source.getFirstName());
dbo.put("age", source.getAge());
return dbo;
}
}</programlisting>
<para></para>
</section>

View File

@@ -296,6 +296,61 @@ public class MongoApp {
</section>
<section>
<title>Migrating from M2 to M3</title>
<para>There were several API changes introduced in the M3 release. To
upgrade from M2 to M3 you will need to make. For a full listing of API
changes please refer to this <ulink
url="http://static.springsource.org/spring-data/data-document/docs/jdiff-mongo-m2-m3/mongo-report/">JDiff
Report</ulink>.</para>
<para>The major changes are with respect to MongoTemplate</para>
<itemizedlist>
<listitem>
<para>Constructors have changed on
<classname>MongoTemplate</classname>. <literal>MongoTemplate(Mongo,
String, String)</literal> and <literal>MongoTemplate(Mongo, String,
String, MongoConverter)</literal> were removed.
<literal>MongoTemplate(Mongo, String, UserCredentials),
MongoTemplate(MongoDbFactory), MongoTemplate(MongoDbFactory,
MongoConverter)</literal> were added. These changes will also effect
usage of wiring up <classname>MongoTemplate</classname> in
&lt;bean/&gt; XML defintions.</para>
</listitem>
<listitem>
<para><classname>MongoTemplate</classname> no longer takes a default
collection name. The collection name is now either specified when
the method is invoked or inferred from the Java class, either the
class name or via mapping metadata.</para>
</listitem>
<listitem>
<para>Removed <classname>MongoTemplate</classname> methods that use
<interfacename>MongoReader</interfacename> and
<interfacename>MongoWriter</interfacename>. As an alternative
register a Spring converter with the MappingMongoConverter. See
<link linkend="mapping-explicit-converters">here</link> for
details.</para>
</listitem>
<listitem>
<para><classname>MongoTemplate's</classname> update method
arguements from <literal>(Query, Update)</literal>
to<literal>(Class&lt;?&gt;, Query, Update)</literal>was updateFirst
takes a <classname>java.lang.Class</classname> argument as the first
argument.</para>
</listitem>
<listitem>
<para>Added <literal>findById</literal> methods to
<classname>MongoTemplate.</classname></para>
</listitem>
</itemizedlist>
</section>
</section>
<section>
@@ -628,7 +683,7 @@ public class MongoConfiguration {
&lt;constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/&gt;
&lt;/bean&gt;</programlisting>
<para> </para>
<para></para>
</section>
</section>
@@ -1035,7 +1090,7 @@ DEBUG work.data.document.mongodb.MongoTemplate: 376 - Dropped collection [databa
this case the collection name will be determined by name (not fully
qualfied) of the class. You may also call the save operation with a
specific collection name. The collection to store the object can be
overriden using mapping metadata. </para>
overriden using mapping metadata.</para>
<para>When inserting or saving, if the Id property is not set, the
assumption is that its value will be autogenerated by the database. As
@@ -1826,7 +1881,7 @@ List&lt;Venue&gt; venues =
<para>In order to have more fine grained control over the mapping process
you can register Spring converters with the
<classname>MongoConverter</classname> implementations such as the
<classname>MappingMongoConverter</classname>. </para>
<classname>MappingMongoConverter</classname>.</para>
<para>The <classname>MappingMongoConverter</classname> checks to see if
there are any Spring converters that can handle a specific class before