DATADOC-147 - Update reference documentation to cover changes from M2 to M3 (partial work)
2104 lines
84 KiB
XML
2104 lines
84 KiB
XML
<?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.core">
|
|
<title>MongoDB support</title>
|
|
|
|
<para>The MongoDB support contains a wide range of features which are
|
|
summarized below.</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Spring configuration support using Java based @Configuration
|
|
classes or an XML namespace for a Mongo driver instance and replica
|
|
sets</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>MongoTemplate helper class that increases productivity performing
|
|
common Mongo operations. Includes integrated object mapping between
|
|
documents and POJOs.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Exception translation into Spring's portable Data Access Exception
|
|
hierarchy</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Feature Rich Object Mapping integrated with Spring's Conversion
|
|
Service</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Annotation based mapping metadata but extensible to support other
|
|
metadata formats</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Persistence and mapping lifecycle events</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Java based Query, Criteria, and Update DSLs</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Automatic implementatin of Repository interfaces including support
|
|
for custom finder methods.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>QueryDSL integration to support type-safe queries.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Cross-store persistance - support for JPA Entities with fields
|
|
transparently persisted/retrieved using MongoDB</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Log4j log appender</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>GeoSpatial integration</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>For most tasks you will find yourself using
|
|
<classname>MongoTemplate</classname> or the Repository support that both
|
|
leverage the rich mapping functionality. MongoTemplate is the place to look
|
|
for accessing functionality such as incrementing counters or ad-hoc CRUD
|
|
operations. MongoTemplate also provides callback methods so that it is easy
|
|
for you to get a hold of the low level API artifacts such as
|
|
<literal>org.mongo.DB</literal> to communicate directly with MongoDB. The
|
|
goal with naming conventions on various API artifacts is to copy those in
|
|
the base MongoDB Java driver so you can easily map your existing knowledge
|
|
onto the Spring APIs.</para>
|
|
|
|
<section id="mongodb-requirements">
|
|
<title>Getting Started</title>
|
|
|
|
<para>Spring MongoDB support requires MongoDB 1.4 or higher and Java SE 5
|
|
or higher. The latest production release (1.8.x as of this writing) is
|
|
recommended. An easy way to bootstrap setting up a working environment is
|
|
to create a Spring based project in <ulink
|
|
url="http://www.springsource.com/developer/sts">STS</ulink>.</para>
|
|
|
|
<para>First you need to set up a running Mongodb server. Refer to the
|
|
<ulink url="http://www.mongodb.org/display/DOCS/Quickstart">Mongodb Quick
|
|
Start guide</ulink> for an explanation on how to startup a Mongo instance.
|
|
Once installed starting Mongo is typically a matter of executing the
|
|
following command: <literal>MONGO_HOME/bin/mongod</literal></para>
|
|
|
|
<para>To create a Spring project in STS go to File -> New -> Spring
|
|
Template Project -> Simple Spring Utility Project --> press Yes when
|
|
prompted. Then enter a project and a package name such as
|
|
org.spring.mongodb.example.</para>
|
|
|
|
<para>Then add the following to pom.xml dependencies section.</para>
|
|
|
|
<programlisting lang="" language="xml"><dependencies>
|
|
|
|
<!-- other dependency elements omitted -->
|
|
|
|
<dependency>
|
|
<groupId>org.springframework.data</groupId>
|
|
<artifactId>spring-data-mongodb</artifactId>
|
|
<version>1.0.0.M3</version>
|
|
</dependency>
|
|
|
|
</dependencies>
|
|
</programlisting>
|
|
|
|
<para>Also change the version of Spring in the pom.xml to be</para>
|
|
|
|
<programlisting lang="" language="xml"><spring.framework.version>3.0.5.RELEASE</spring.framework.version></programlisting>
|
|
|
|
<para>You will also need to add the location of the Spring Milestone
|
|
repository for maven to your pom.xml which is at the same level of your
|
|
<dependencies/> element</para>
|
|
|
|
<programlisting language="xml"><repositories>
|
|
<repository>
|
|
<id>spring-milestone</id>
|
|
<name>Spring Maven MILESTONE Repository</name>
|
|
<url>http://maven.springframework.org/milestone</url>
|
|
</repository>
|
|
</repositories></programlisting>
|
|
|
|
<para>The repository is also <ulink
|
|
url="http://shrub.appspot.com/maven.springframework.org/milestone/org/springframework/data/">browseable
|
|
here</ulink>.</para>
|
|
|
|
<para>You may also want to set the logging level to DEBUG to see some
|
|
additional information, edit the log4j.properties file to have</para>
|
|
|
|
<programlisting>log4j.category.org.springframework.data.document.mongodb=DEBUG
|
|
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %40.40c:%4L - %m%n</programlisting>
|
|
|
|
<para>Create a simple Person class to persist</para>
|
|
|
|
<programlisting language="java">package org.spring.mongodb.example;
|
|
|
|
public class Person {
|
|
|
|
private String id;
|
|
private String name;
|
|
private int age;
|
|
|
|
public Person(String name, int age) {
|
|
this.name = name;
|
|
this.age = age;
|
|
}
|
|
|
|
public String getId() {
|
|
return id;
|
|
}
|
|
public String getName() {
|
|
return name;
|
|
}
|
|
public int getAge() {
|
|
return age;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
|
|
}
|
|
|
|
}</programlisting>
|
|
|
|
<para>And a main application to run</para>
|
|
|
|
<programlisting language="java">package org.spring.mongodb.example;
|
|
|
|
import static org.springframework.data.document.mongodb.query.Criteria.where;
|
|
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
import org.springframework.data.document.mongodb.MongoOperations;
|
|
import org.springframework.data.document.mongodb.MongoTemplate;
|
|
import org.springframework.data.document.mongodb.query.Query;
|
|
|
|
import com.mongodb.Mongo;
|
|
|
|
public class MongoApp {
|
|
|
|
private static final Log log = LogFactory.getLog(MongoApp.class);
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
|
|
MongoOperations mongoOps = new MongoTemplate(new Mongo(), "database");
|
|
|
|
mongoOps.insert(new Person("Joe", 34));
|
|
|
|
log.info(mongoOps.findOne(new Query(where("name").is("Joe")), Person.class));
|
|
|
|
mongoOps.dropCollection("person");
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>This will produce the following output</para>
|
|
|
|
<programlisting>10:01:32,062 DEBUG apping.MongoPersistentEntityIndexCreator: 80 - Analyzing class class org.spring.example.Person for index information.
|
|
10:01:32,265 DEBUG work.data.document.mongodb.MongoTemplate: 631 - insert DBObject containing fields: [_class, age, name] in collection: Person
|
|
10:01:32,765 DEBUG work.data.document.mongodb.MongoTemplate:1243 - findOne using query: { "name" : "Joe"} in db.collection: database.Person
|
|
10:01:32,953 INFO org.spring.mongodb.example.MongoApp: 25 - Person [id=4ddbba3c0be56b7e1b210166, name=Joe, age=34]
|
|
10:01:32,984 DEBUG work.data.document.mongodb.MongoTemplate: 375 - Dropped collection [database.person]</programlisting>
|
|
|
|
<para>Even in this simple example, there are few things to take notice
|
|
of</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>You can instantiate the central helper class of Spring Mongo,
|
|
<link linkend="mongo-template">MongoTemplate</link>, using the
|
|
standard <classname>com.mongodb.Mongo</classname> object and the name
|
|
of the database to use.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The mapper works against standard POJO objects without the need
|
|
for any additional metadata (though you can optionally provide that
|
|
information. See <link linkend="mongo.mapping">here</link>.).</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Conventions are used for handling the id field, converting it to
|
|
be a ObjectId when stored in the database.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Mapping conventions can use field access. Notice the Person
|
|
class has only getters.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>If the constructor argument names match the field names of the
|
|
stored document, they will be used to instantiate the object</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<section id="mongodb-required-jars">
|
|
|
|
|
|
<title>Required Jars</title>
|
|
|
|
The following jars are required to use Sping Mongo
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>spring-data-mongodb-1.0.0.M3.jar</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
In addition to the above listed Spring Data jars you need to provide the following dependencies:
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>com.springsource.org.aopalliance-1.0.0.jar</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>commons-logging-1.1.1.jar</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>mongo-java-driver-2.5.3.jar</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>spring-aop-3.0.5.RELEASE.jar</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>spring-asm-3.0.5.RELEASE.jar</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>spring-beans-3.0.5.RELEASE.jar</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>spring-context-3I.0.5.RELEASE.jar</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>spring-core-3.0.5.RELEASE.jar</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>spring-expression-3.0.5.RELEASE.jar</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Examples Repository</title>
|
|
|
|
<para>There is an <ulink
|
|
url="https://github.com/SpringSource/spring-data-document-examples">github
|
|
repository with several examples</ulink> that you can download and play
|
|
around with to get a feel for how the library works.</para>
|
|
</section>
|
|
|
|
<section id="mongodb-connectors">
|
|
<title>Connecting to MongoDB with Spring</title>
|
|
|
|
<para>One of the first tasks when using MongoDB and Spring is to create a
|
|
<classname>com.mongodb.Mongo</classname> object using the IoC container.
|
|
There are two main ways to do this, either using Java based bean metadata
|
|
or XML based bean metadata. These are discussed in the following sections.
|
|
<note>
|
|
<para>For those not familiar with how to configure the Spring
|
|
container using Java based bean metadata instead of XML based metadata
|
|
see the high level introduction in the reference docs <ulink
|
|
url="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/new-in-3.html#new-java-configuration"
|
|
userlevel="">here </ulink> as well as the detailed documentation<ulink
|
|
url="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-java-instantiating-container">
|
|
here</ulink>.</para>
|
|
</note></para>
|
|
|
|
<section>
|
|
<title>Registering a Mongo instance using Java based metadata</title>
|
|
|
|
<para>An example of using Java based bean metadata to register an
|
|
instance of a <classname>com.mongodb.Mongo</classname> is shown below
|
|
<example>
|
|
<title>Registering a com.mongodb.Mongo object using Java based bean
|
|
metadata</title>
|
|
|
|
<programlisting language="java">@Configuration
|
|
public class AppConfig {
|
|
|
|
/*
|
|
* Use the standard Mongo driver API to create a com.mongodb.Mongo instance.
|
|
*/
|
|
public @Bean Mongo mongo() throws UnknownHostException {
|
|
return new Mongo("localhost");
|
|
}
|
|
} </programlisting>
|
|
</example></para>
|
|
|
|
<para>This approach allows you to use the standard
|
|
<classname>com.mongodb.Mongo</classname> API that you may already be
|
|
used to using but also pollutes the code with the UnknownHostException
|
|
checked exception. The use of the checked exception is not desirable as
|
|
Java based bean metadata uses methods as a means to set object
|
|
dependencies, making the calling code cluttered.</para>
|
|
|
|
<para>An alternative is to register an instance of
|
|
<classname>com.mongodb.Mongo</classname> instance with the container
|
|
using Spring's<interfacename> MongoFactoryBean</interfacename>. As
|
|
compared to instantiating a <classname>com.mongodb.Mongo</classname>
|
|
instance directly, the FactoryBean approach does not throw a checked
|
|
exception and has the added advantage of also providing the container
|
|
with an ExceptionTranslator implementation that translates Mongo
|
|
exceptions to exceptions in Spring's portable
|
|
<classname>DataAccessException</classname> hierarchy for data access
|
|
classes annoated with the <literal>@Repository</literal> annotation.
|
|
This hierarchy and use of <literal>@Repository</literal> is described in
|
|
<ulink
|
|
url="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/dao.html">Spring's
|
|
DAO support features</ulink>.</para>
|
|
|
|
<para>An example of a Java based bean metadata that supports exception
|
|
translation on <classname>@Repository</classname> annotated classes is
|
|
shown below:</para>
|
|
|
|
<example>
|
|
<title>Registering a com.mongodb.Mongo object using Spring's
|
|
MongoFactoryBean and enabling Spring's exception translation
|
|
support</title>
|
|
|
|
<programlisting language="java">@Configuration
|
|
public class AppConfig {
|
|
|
|
/*
|
|
* Factory bean that creates the com.mongodb.Mongo instance
|
|
*/
|
|
public @Bean MongoFactoryBean mongo() {
|
|
MongoFactoryBean mongo = new MongoFactoryBean();
|
|
mongo.setHost("localhost");
|
|
return mongo;
|
|
}
|
|
}
|
|
</programlisting>
|
|
|
|
<para>To access the <classname>com.mongodb.Mongo</classname> object
|
|
created by the <classname>MongoFactoryBean</classname> in other
|
|
<literal>@Configuration</literal> or your own classes, use a
|
|
"<literal>private @Autowired Mongo mongo;</literal>" field.</para>
|
|
</example>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Registering a Mongo instance using XML based metadata</title>
|
|
|
|
<para>While you can use Spring's traditional
|
|
<literal><beans/></literal> XML namespace to register an instance
|
|
of <classname>com.mongodb.Mongo</classname> with the container, the XML
|
|
can be quite verbose as it is general purpose. XML namespaces are a
|
|
better alternative to configuring commonly used objects such as the
|
|
Mongo instance. The mongo namespace alows you to create a Mongo instance
|
|
server location, replica-sets, and options.</para>
|
|
|
|
<para>To use the Mongo namespace elements you will need to reference the
|
|
Mongo schema:</para>
|
|
|
|
<example>
|
|
<title>XML schema to configure MongoDB</title>
|
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?>
|
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xmlns:context="http://www.springframework.org/schema/context"
|
|
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
|
|
xsi:schemaLocation=
|
|
"http://www.springframework.org/schema/context
|
|
http://www.springframework.org/schema/context/spring-context-3.0.xsd
|
|
<emphasis role="bold">http://www.springframework.org/schema/data/mongo
|
|
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd</emphasis>
|
|
http://www.springframework.org/schema/beans
|
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
|
|
|
|
<!-- Default bean name is 'mongo' -->
|
|
<emphasis role="bold"><mongo:mongo host="localhost" port="27017"/></emphasis>
|
|
|
|
</beans>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>A more advanced configuration with MongoOptions is shown below
|
|
(note these are not recommended values)</para>
|
|
|
|
<example>
|
|
<title>XML schema to configure a com.mongodb.Mongo object with
|
|
MongoOptions</title>
|
|
|
|
<programlisting language="xml"><beans>
|
|
|
|
<mongo:mongo host="localhost" port="27017">
|
|
<mongo:options connections-per-host="8"
|
|
threads-allowed-to-block-for-connection-multiplier="4"
|
|
connect-timeout="1000"
|
|
max-wait-time="1500}"
|
|
auto-connect-retry="true"
|
|
socket-keep-alive="true"
|
|
socket-timeout="1500"
|
|
slave-ok="true"
|
|
write-number="1"
|
|
write-timeout="0"
|
|
write-fsync="true"/>
|
|
</mongo:mongo/>
|
|
|
|
</beans>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>A configuration using replica sets is shown below. <example>
|
|
<title>XML schema to configure com.mongodb.Mongo object with Replica
|
|
Sets</title>
|
|
|
|
<programlisting language="xml"><mongo:mongo id="replicaSetMongo" replica-set="127.0.0.1:27017,localhost:27018"/> </programlisting>
|
|
</example></para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Registering a MongoDbFactory instance using Java based
|
|
metadata</title>
|
|
|
|
<para>As an alternative to configuring a
|
|
<classname>com.mongodb.Mongo</classname> instance and later providing
|
|
the database name and optionally the username and password, is to use
|
|
<classname>SimpleMongoDbFactory</classname>, which implements the
|
|
<interfacename>MongoDbFactory</interfacename> inteface shown below. A
|
|
reference to <interfacename>MongoDbFactory</interfacename> can be passed
|
|
to constructors of <classname>MongoTemplate</classname> to simplify its
|
|
creation.</para>
|
|
|
|
<programlisting language="java">public interface MongoDbFactory {
|
|
|
|
DB getDb() throws DataAccessException;
|
|
|
|
DB getDb(String dbName) throws DataAccessException;
|
|
|
|
}</programlisting>
|
|
|
|
<para>The most simple usage is shown below</para>
|
|
|
|
<programlisting>@Configuration
|
|
public class MongoConfiguration {
|
|
|
|
public @Bean MongoDbFactory mongoDbFactory() throws Exception {
|
|
return new SimpleMongoDbFactory(new Mongo(), "database");
|
|
}
|
|
|
|
}</programlisting>
|
|
|
|
<para>To define the username and password create an instance of
|
|
org.springframework.data.authentication.UserCredentials and pass it into
|
|
the constructor as shown below</para>
|
|
|
|
<programlisting>@Configuration
|
|
public class MongoConfiguration {
|
|
|
|
public @Bean MongoDbFactory mongoDbFactory() throws Exception {
|
|
UserCredentials userCredentials = new UserCredentials("joe", "secret");
|
|
return new SimpleMongoDbFactory(new Mongo(), "database", userCredentials);
|
|
}
|
|
}
|
|
</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Registering a Mongo instance using XML based metadata</title>
|
|
|
|
<para>The mongo namespace lets you create a MongoDbFactory instance
|
|
which is a convenient way to group together the a mongo instance, a
|
|
database name and an optional username and password. A simple usage is
|
|
shown below</para>
|
|
|
|
<programlisting language="xml"> <mongo:db-factory dbname="database" ></programlisting>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="mongo-template">
|
|
<title>Introduction to MongoTemplate</title>
|
|
|
|
<para>The class <classname>MongoTemplate</classname>, located in the
|
|
package <literal>org.springframework.data.document.mongodb</literal>, is
|
|
the central class of the Spring's MongoDB support providng a rich feature
|
|
set. The template offers convenience operations to create, update, delete
|
|
and query for MongoDB document and provide a mapping between your domain
|
|
objects and MongoDB documents.</para>
|
|
|
|
<note>
|
|
<para>Once configured, <classname>MongoTemplate</classname> is
|
|
thread-safe and can be reused across multiple instances.</para>
|
|
</note>
|
|
|
|
<para>The mapping between Mongo documents and domain classes is done by
|
|
delegating to an implementation of the interface
|
|
<interfacename>MongoConverter</interfacename>. Spring provides two
|
|
implementations, <classname>SimpleMappingConverter</classname> and
|
|
<classname>MongoMappingConverter</classname>, but you can also write your
|
|
own converter. Please refer to the section on MongoCoverters for more
|
|
detailed information.</para>
|
|
|
|
<para>The <classname>MongoTemplate</classname> class implements the
|
|
interface <interfacename>MongoOperations</interfacename>. In as much as
|
|
possible, the methods on <interfacename>MongoOperations</interfacename>
|
|
are named after methods available on the MongoDB driver
|
|
<classname>Collection</classname> object. For example, you will find
|
|
methods such as "find", "findAndModify", "findOne", "insert", "remove",
|
|
"save", "update" and "updateMulti". The design goal was to make it as easy
|
|
as possible to transition between the use of the base MongoDB driver and
|
|
<interfacename>MongoOperations</interfacename>. The difference in betwee
|
|
the two is that MongOperations can be passed domain objects instead of
|
|
<classname>DBObject</classname> and there are fluent APIs for
|
|
<classname>Query</classname>, <classname>Criteria</classname>, and
|
|
<classname>Update</classname> operations instead of
|
|
<classname>DBObject</classname>..</para>
|
|
|
|
<note>
|
|
<para>The preferred way to reference the operations on
|
|
<classname>MongoTemplate</classname> instance is via its interface
|
|
<interfacename>MongoOperations</interfacename>.</para>
|
|
</note>
|
|
|
|
<para>The default converter implementation used by
|
|
<classname>MongoTemplate</classname> is
|
|
<classname>SimpleMappingConverter</classname>, which as the name implies,
|
|
is simple. <classname>SimpleMapingConverter</classname> does not use any
|
|
additional mapping metadata to converter a domain object to a MongoDB
|
|
document. As such, it does not support functionality such as DBRefs or
|
|
creating indexes using annotations on domain classes. For a detailed
|
|
description of the MongoMappingConverter read the section on <link
|
|
linkend="mongo.mapping">Mapping Support</link>.</para>
|
|
|
|
<para>Another central feature of MongoTemplate is exception translation of
|
|
exceptions thrown in the Mongo Java driver into Spring's portable Data
|
|
Access Exception hierarchy. Refer to the section on <link
|
|
linkend="mongo.exception">exception translation</link> for more
|
|
information.</para>
|
|
|
|
<para>While there are many convenience methods on
|
|
<classname>MongoTemplate</classname> to help you easily perform common
|
|
tasks if you should need to access the Mongo driver API directly to access
|
|
functionality not explicitly exposed by the MongoTemplate you can use one
|
|
of several Execute callback methods. These will give you a reference to a
|
|
Mongo Collection or DB object. Please see the section <ulink
|
|
url="mongo.executioncallback">Execution Callbacks</ulink> for more
|
|
information.</para>
|
|
|
|
<para>Now let's look at a examples of how to work with the
|
|
<classname>MongoTemplate</classname> in the context of the Spring
|
|
container.</para>
|
|
|
|
<section>
|
|
<title>Instantiating MongoTemplate</title>
|
|
|
|
<para>You can use Java to create and register an instance of
|
|
MongoTemplate as shown below.</para>
|
|
|
|
<example>
|
|
<title>Registering a com.mongodb.Mongo object and enabling Spring's
|
|
exception translation support</title>
|
|
|
|
<programlisting language="java">@Configuration
|
|
public class AppConfig {
|
|
|
|
public @Bean Mongo mongo() throws Exception {
|
|
return new Mongo("localhost");
|
|
}
|
|
|
|
public @Bean MongoTemplate mongoTemplate() throws Exception {
|
|
return new MongoTemplate(mongo(), "mydatabase", "mycollection");
|
|
}
|
|
}
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>There are several overloaded constructors of MongoTemplate. These
|
|
are</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><emphasis role="bold">MongoTemplate </emphasis>
|
|
<literal>(Mongo mongo, String databaseName) </literal> - takes the
|
|
default database name to operate against</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis role="bold">MongoTemplate </emphasis>
|
|
<literal>(Mongo mongo, String databaseName, String
|
|
defaultCollectionName) </literal> - adds the default collection name
|
|
to operate against.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis role="bold">MongoTemplate </emphasis>
|
|
<literal>(Mongo mongo, String databaseName, String
|
|
defaultCollectionName, MongoConverter mongoConverter) </literal> -
|
|
override with a provided MongoConverter. Default is
|
|
SimpleMongoConverter</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>You can also configure a MongoTemplate using Spring's XML
|
|
<beans/> schema.</para>
|
|
|
|
<programlisting language="java"> <mongo:mongo host="localhost" port="27017"/>
|
|
|
|
<bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
|
|
<constructor-arg ref="mongo"/>
|
|
<constructor-arg name="databaseName" value="geospatial"/>
|
|
<constructor-arg name="defaultCollectionName" value="newyork"/>
|
|
</bean></programlisting>
|
|
|
|
<para>Other properties that you might like to set when creating a
|
|
MongTemplate are WriteResultCheckingPolicy and the default
|
|
WriteConcern.</para>
|
|
|
|
<note>
|
|
<para>The preferred way to reference the operations on
|
|
<classname>MongoTemplate</classname> instance is via its interface
|
|
<interfacename>MongoOperations</interfacename>.</para>
|
|
</note>
|
|
|
|
<section>
|
|
<title>WriteResultChecking Policy</title>
|
|
|
|
<para>When in development it is very handy to either log or throw an
|
|
exception if the WriteResult returned from any MongoDB operation
|
|
contains an error. It is quite common to forget to do this during
|
|
development and then end up with an application that looks like it ran
|
|
successfully but the database was not modified according to your
|
|
expectations. Setting the WriteResultChecking is an enum with the
|
|
following values, NONE, LOG, EXCEPTION.</para>
|
|
|
|
<para>The default is to use a WriteResultChecking of NONE.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>WriteConcern</title>
|
|
|
|
<para>You can set the WriteConcern property that the MongoTemplate
|
|
will use for write operations if it has not yet been specifid with the
|
|
driver. If not set, it will default to the one set in the MongoDB
|
|
driver's DB or Collection setting.</para>
|
|
|
|
<note>
|
|
<para>Setting the WriteConcern to different values when saving an
|
|
object will be provided in a future release. This will most likely
|
|
be handled using mapping metadata provided either in the form of
|
|
annotations on the domain object or by an external fluent
|
|
DSL.</para>
|
|
</note>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Configuring the MongoConverter</title>
|
|
|
|
<para>The SimpleMongoConverter is used by default but if you want to use
|
|
the more feature rich MappingMongoConverter there are a few steps.
|
|
Please refer to the <link
|
|
linkend="mongodb.mapping-configuration">mapping section</link> for more
|
|
information.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Saving, Updating, and Removing Documents</title>
|
|
|
|
<para><classname>MongoTemplate</classname> provides a simple way for you
|
|
to save, update, and delete your domain objects and map those objects to
|
|
documents stored in MongoDB.</para>
|
|
|
|
<para>Given a simple class such as Person</para>
|
|
|
|
<programlisting language="java">public class Person {
|
|
|
|
private String id;
|
|
private String firstName;
|
|
private int age;
|
|
|
|
// getters and setter omitted
|
|
|
|
}</programlisting>
|
|
|
|
<para>You can save, update and delete the object as shown below.</para>
|
|
|
|
<note>
|
|
<para><interfacename>MongoOperations</interfacename> is the interface
|
|
that <classname>MongoTemplate</classname> implements.</para>
|
|
</note>
|
|
|
|
<programlisting language="java">public class PersonExample {
|
|
|
|
private static final Log log = LogFactory.getLog(PersonExample.class);
|
|
|
|
@Autowired
|
|
private MongoOperations mongoOps;
|
|
|
|
public void doWork() {
|
|
|
|
Person p = new Person();
|
|
p.setFirstName("Sven");
|
|
p.setAge(22);
|
|
|
|
// Save
|
|
mongoOps.save(p);
|
|
log.debug("Saved: " + p);
|
|
|
|
// Find
|
|
p = mongoOps.findOne(query(whereId().is(p.getId())), Person.class);
|
|
log.debug("Found: " + p);
|
|
|
|
// Update age to 24 for Sven
|
|
mongoOps.updateFirst(query(where("firstName").is("Sven")), update("age", 24));
|
|
p = mongoOps.findOne(query(whereId().is(p.getId())), Person.class);
|
|
log.debug("Updated: " + p);
|
|
|
|
// Delete
|
|
mongoOps.remove(p);
|
|
|
|
// Check that deletion worked
|
|
List<Person> people = mongoOps.getCollection(Person.class);
|
|
log.debug("Number of people = : " + people.size());
|
|
|
|
}</programlisting>
|
|
|
|
<para>This would produce the following log output (including some debug
|
|
message from <classname>MongoTemplate</classname> itself)</para>
|
|
|
|
<programlisting>Saved: PersonWithIdPropertyOfTypeString [id=4d9e82ac94fa72c65a9e7d5f, firstName=Sven, age=22]
|
|
findOne using query: { "_id" : { "$oid" : "4d9e82ac94fa72c65a9e7d5f"}} in db.collection: database.personexample
|
|
Found: PersonWithIdPropertyOfTypeString [id=4d9e82ac94fa72c65a9e7d5f, firstName=Sven, age=22]
|
|
findOne using query: { "_id" : { "$oid" : "4d9e82ac94fa72c65a9e7d5f"}} in db.collection: database.personexample
|
|
Updated: PersonWithIdPropertyOfTypeString [id=4d9e82ac94fa72c65a9e7d5f, firstName=Sven, age=24]
|
|
remove using query: { "_id" : { "$oid" : "4d9e82ac94fa72c65a9e7d5f"}}
|
|
Number of people = : 0</programlisting>
|
|
|
|
<para>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.</para>
|
|
|
|
<note>
|
|
<para>This example is meant to show the use of save, update and remove
|
|
operations on MongoTemplate and not to show complex mapping
|
|
functionality</para>
|
|
</note>
|
|
|
|
<para>The query stynax used in the example is explained in more detail in
|
|
the section <link linkend="mongo.query">Querying Documents</link>.</para>
|
|
|
|
<section>
|
|
<title>How the '_id' field is handled in the mapping layer</title>
|
|
|
|
<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>
|
|
|
|
<para>The following outlines what property will be mapped to the '_id'
|
|
field:</para>
|
|
|
|
<para><itemizedlist>
|
|
<listitem>
|
|
<para>A property or 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 named <classname>id</classname> will be
|
|
mapped to the '_id' field.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>A property or field declared as a String in the Java class
|
|
will be converted to and stored as an ObjectId if possible
|
|
(conversions and rules would be handled by 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>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>A property or field declared as anything but a String in the
|
|
Java class will be stored as the type it is declared as, which
|
|
means it must be one of the basic types supported by the Mongo
|
|
Java driver.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<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 the <classname>JdbcTemplate</classname>
|
|
will use the converter to handle conversions of the
|
|
<classname>Query</classname> and <classname>Update</classname> objects
|
|
that correspond to the above rules for saving documents so field names
|
|
and types used in your queries will be able to match what is in your
|
|
domain classes.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Methods for saving and inserting documents</title>
|
|
|
|
<para>There are several convenient methods on MongoTemplate for saving
|
|
and inserting your objects. In addition to using a
|
|
<interfacename>MongoCoverter</interfacename> to converter your domain
|
|
object to the database, you can also use an implementation of the
|
|
<interfacename>MongoWriter</interfacename> interface to have very fine
|
|
grained control over the conversion process.</para>
|
|
|
|
<note>
|
|
<para>The difference between insert and save operations is that a save
|
|
operation will perform an insert if the object is not already
|
|
present.</para>
|
|
</note>
|
|
|
|
<para>The simple case of using the save operation is to pass in as an
|
|
argument only the object to save. In this case the default collection
|
|
assigned to the template will be used unless the converter overrides
|
|
this default through the use of more specific mapping metadata. You may
|
|
also call the save operation with a specific collection name.</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
|
|
such, for autogeneration of an ObjectId to succeed the type of the Id
|
|
property/field in your class must be either a
|
|
<classname>String</classname>, <classname>ObjectId</classname>, or
|
|
<classname>BigInteger</classname>.</para>
|
|
|
|
<para>Here is a basic example of using the save operation and retrieving
|
|
its contents.</para>
|
|
|
|
<example>
|
|
<title>Inserting and retrieving documents using the
|
|
MongoTemplate</title>
|
|
|
|
<programlisting language="java">import static org.springframework.data.document.mongodb.query.Criteria.where;
|
|
import static org.springframework.data.document.mongodb.query.Criteria.query;
|
|
|
|
...
|
|
|
|
Person p = new Person("Bob", 33);
|
|
mongoTemplate.insert("MyCollection", p);
|
|
|
|
Person qp = mongoTemplate.findOne("MyCollection", query(where("age").is(33)), Person.class);
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>The four save operations available to you are listed below.</para>
|
|
|
|
<para><itemizedlist>
|
|
<listitem>
|
|
<para><literal>void</literal> <emphasis role="bold">save
|
|
</emphasis> <literal>(Object objectToSave) </literal> Save the
|
|
object to the default collection.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void</literal> <emphasis role="bold">save
|
|
</emphasis> <literal>(String collectionName, Object objectToSave)
|
|
</literal> Save the object to the specified collection.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> void</literal> <emphasis role="bold">save
|
|
</emphasis> <literal>(T objectToSave, MongoWriter<T> writer)
|
|
</literal> Save the object into the default collection using the
|
|
provided writer.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> void</literal> <emphasis role="bold">save
|
|
</emphasis> <literal>(String collectionName, T objectToSave,
|
|
MongoWriter<T> writer) </literal> Save the object into the
|
|
specified collection using the provided writer.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para>A similar set of insert operations is listed below</para>
|
|
|
|
<para><itemizedlist>
|
|
<listitem>
|
|
<para><literal>void</literal> <emphasis
|
|
role="bold">insert</emphasis> <literal>(Object objectToSave)
|
|
</literal> Insert the object to the default collection.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void</literal> <emphasis role="bold">insert
|
|
</emphasis> <literal>(String collectionName, Object objectToSave)
|
|
</literal> Insert the object to the specified collection.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> void</literal> <emphasis
|
|
role="bold">insert </emphasis> <literal>(T objectToSave,
|
|
MongoWriter<T> writer) </literal> Insert the object into the
|
|
default collection using the provided writer.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> void</literal> <emphasis
|
|
role="bold">insert </emphasis> <literal>(String collectionName, T
|
|
objectToSave, MongoWriter<T> writer) </literal> Insert the
|
|
object into the specified collection using the provided
|
|
writer.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para>Unless and explicit MongoWriter is passed into the save or insert
|
|
method, the the template's MongoConverter will be used.</para>
|
|
|
|
<section>
|
|
<title>Saving using MongoWriter</title>
|
|
|
|
<para>The MongoWriter interface allows you to have lower level control
|
|
over the mapping of an object into a DBObject. The MongoWriter
|
|
interface is</para>
|
|
|
|
<programlisting language="java">/**
|
|
* A MongoWriter is responsible for converting an object of type T to the native MongoDB
|
|
* representation DBObject.
|
|
*
|
|
* @param <T> the type of the object to convert to a DBObject
|
|
*/
|
|
public interface MongoWriter<T> {
|
|
|
|
/**
|
|
* Write the given object of type T to the native MongoDB object representation DBObject.
|
|
*
|
|
* @param t The object to convert to a DBObject
|
|
* @param dbo The DBObject to use for writing.
|
|
*/
|
|
void write(T t, DBObject dbo);
|
|
|
|
}</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Inserting Lists of objects in batch</title>
|
|
|
|
<para>The MongoDB driver supports inserting a collection of documents
|
|
in one operation. The methods in the MongoOperations interface that
|
|
support this functionality are listed below</para>
|
|
|
|
<para><itemizedlist>
|
|
<listitem>
|
|
<para><literal>void</literal> <emphasis
|
|
role="bold">insertList</emphasis><literal> (List<? extends
|
|
Object> listToSave)</literal><literal> </literal> Insert a
|
|
list of objects into the default collection in a single batch
|
|
write to the database.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void</literal> <emphasis
|
|
role="bold">insertList</emphasis> <literal>(String
|
|
collectionName, List<? extends Object>
|
|
listToSave)</literal><literal> </literal>Insert a list of
|
|
objects into the specified collection in a single batch write to
|
|
the database.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> void</literal> <emphasis
|
|
role="bold">insertList</emphasis><literal> (List<? extends
|
|
T> listToSave, MongoWriter<T> writer)</literal>
|
|
<literal></literal> Insert the object into the default
|
|
collection using the provided writer.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> void</literal> <emphasis
|
|
role="bold">insertList</emphasis><literal>(String
|
|
collectionName, List<? extends T> listToSave,
|
|
MongoWriter<T> writer)</literal> Insert a list of objects
|
|
into the specified collection using the provided MongoWriter
|
|
instance</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="mongodb-template-update">
|
|
<title>Updating documents in a collection</title>
|
|
|
|
<para>For updates we can elect to update the first document found using
|
|
<interfacename>MongoOperation</interfacename>'s method
|
|
<literal>updateFirst</literal> or we can update all documents that were
|
|
found to match the query using the method
|
|
<literal>updateMulti</literal>. Here is an example of an update of all
|
|
SAVINGS accounts where we are adding a one time $50.00 bonus to the
|
|
balance using the <literal>$inc</literal> operator.</para>
|
|
|
|
<example>
|
|
<title>Updating documents using the MongoTemplate</title>
|
|
|
|
<programlisting language="java">import static org.springframework.data.document.mongodb.query.Criteria.where;
|
|
import static org.springframework.data.document.mongodb.query.Query.query;
|
|
import static org.springframework.data.document.mongodb.query.Update
|
|
|
|
...
|
|
|
|
WriteResult wr = mongoTemplate.updateMulti(query(where("accounts.accountType").is(Account.Type.SAVINGS)),
|
|
update.inc("accounts.$.balance", 50.00));
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>In addition to the <classname>Query</classname> discussed above we
|
|
provide the update definition using an <classname>Update</classname>
|
|
object. The <classname>Update</classname> class has methods that match
|
|
the update modifiers available for MongoDB.</para>
|
|
|
|
<para>As you can see most methods return the
|
|
<classname>Update</classname> object to provide a fluent style for the
|
|
API.</para>
|
|
|
|
<section>
|
|
<title>Methods for executing updates for documents</title>
|
|
|
|
<para><itemizedlist>
|
|
<listitem>
|
|
<para><literal>WriteResult</literal> <emphasis
|
|
role="bold">updateFirst </emphasis> <literal>(Query query,
|
|
Update update) </literal> Updates the first object that is found
|
|
in the default collection that matches the query document with
|
|
the provided updated document.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>WriteResult</literal> <emphasis
|
|
role="bold">updateFirst </emphasis> <literal>(String
|
|
collectionName, Query query, Update update) </literal> Updates
|
|
the first object that is found in the specified collection that
|
|
matches the query document criteria with the provided updated
|
|
document.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>WriteResult</literal> <emphasis
|
|
role="bold">updateMulti </emphasis> <literal>(Query query,
|
|
Update update) </literal> Updates all objects that are found in
|
|
the default collection that matches the query document criteria
|
|
with the provided updated document.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>WriteResult</literal> <emphasis
|
|
role="bold">updateMulti </emphasis> <literal>(String
|
|
collectionName, Query query, Update update) </literal> Updates
|
|
all objects that are found in the specified collection that
|
|
matches the query document criteria with the provided updated
|
|
document.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para></para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Methods for the Update class</title>
|
|
|
|
<para><itemizedlist>
|
|
<listitem>
|
|
<para><literal>Update</literal> <emphasis role="bold">addToSet
|
|
</emphasis> <literal>(String key, Object value) </literal>
|
|
Update using the <literal>$addToSet</literal> update
|
|
modifier</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Update</literal> <emphasis role="bold">inc
|
|
</emphasis> <literal>(String key, Number inc) </literal> Update
|
|
using the <literal>$inc</literal> update modifier</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Update</literal> <emphasis role="bold">pop
|
|
</emphasis> <literal>(String key, Update.Position pos)
|
|
</literal> Update using the <literal>$pop</literal> update
|
|
modifier</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Update</literal> <emphasis role="bold">pull
|
|
</emphasis> <literal>(String key, Object value) </literal>
|
|
Update using the <literal>$pull</literal> update modifier</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Update</literal> <emphasis role="bold">pullAll
|
|
</emphasis> <literal>(String key, Object[] values) </literal>
|
|
Update using the <literal>$pullAll</literal> update
|
|
modifier</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Update</literal> <emphasis role="bold">push
|
|
</emphasis> <literal>(String key, Object value) </literal>
|
|
Update using the <literal>$push</literal> update modifier</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Update</literal> <emphasis role="bold">pushAll
|
|
</emphasis> <literal>(String key, Object[] values) </literal>
|
|
Update using the <literal>$pushAll</literal> update
|
|
modifier</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Update</literal> <emphasis role="bold">rename
|
|
</emphasis> <literal>(String oldName, String newName) </literal>
|
|
Update using the <literal>$rename</literal> update
|
|
modifier</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Update</literal> <emphasis role="bold">set
|
|
</emphasis> <literal>(String key, Object value) </literal>
|
|
Update using the <literal>$set</literal> update modifier</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Update</literal> <emphasis role="bold">unset
|
|
</emphasis> <literal>(String key)</literal> Update using the
|
|
<literal>$unset</literal> update modifier</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para></para>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Methods for removing documents</title>
|
|
|
|
<para>You can use several overloaded methods to remove an object from
|
|
the database.</para>
|
|
|
|
<para><itemizedlist>
|
|
<listitem>
|
|
<para><literal>void</literal> <emphasis
|
|
role="bold">remove</emphasis> <literal>(Object object)</literal>
|
|
Remove the given object from the collection by Id</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void</literal> <emphasis
|
|
role="bold">remove</emphasis> <literal>(Query query)</literal>
|
|
Remove all documents from the default collection that match the
|
|
provided query document criteria.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void</literal> <emphasis role="bold">remove
|
|
</emphasis> <literal>(String collectionName, Query query)
|
|
</literal> Remove all documents from the specified collection that
|
|
match the provided query document criteria.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> void </literal><emphasis
|
|
role="bold">remove</emphasis> <literal>(Query query,
|
|
Class<T> targetClass)</literal> Same behavior as the
|
|
remove(Query) method but the Class parameter is used to help
|
|
convert the Id of the object if it is present in the query.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> void </literal><emphasis
|
|
role="bold">remove</emphasis> <literal>(String collectionName,
|
|
Query query, Class<T> targetClass)</literal>Same behavior as
|
|
remove(Query, Class) but the Class parameter is used to help
|
|
convert the Id of the object if it is present in the uqery</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para></para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="mongo.query">
|
|
<title>Querying Documents</title>
|
|
|
|
<para>You can express you queries using the Query and Criteria classes
|
|
which have method names that mirror the native MongoDB operator names such
|
|
as lt, lte, is, and others. The Query and Criteria classes follow a fluent
|
|
API style so that you can easily chain together multiple method criteria
|
|
and queries while having easy to understand code. Static imports in Java
|
|
are used to help remove the need to see the 'new' keyword for creating
|
|
Query and Criteria instances so as to improve readability.</para>
|
|
|
|
<para>GeoSpatial queries are also supported and are described more in the
|
|
section <link linkend="mongo.geospatial">GeoSpatial Queries</link>.</para>
|
|
|
|
<section id="mongodb-template-query">
|
|
<title>Querying documents in a collection</title>
|
|
|
|
<para>We saw how to retrieve a single document. We can also query for a
|
|
collection of documents to be returned as domain objects in a list.
|
|
Assuming that we have a number of Person objects with name and age
|
|
stored as documents in a collection and that each person has an embedded
|
|
account document with a balance. We can now run a query using the
|
|
following code.</para>
|
|
|
|
<example>
|
|
<title>Querying for documents using the MongoTemplate</title>
|
|
|
|
<programlisting language="java">import static org.springframework.data.document.mongodb.query.Criteria.where;
|
|
import static org.springframework.data.document.mongodb.query.Query.query;
|
|
|
|
...
|
|
|
|
List<Person> result = mongoTemplate.find(query(where("age").lt(50).and("accounts.balance").gt(1000.00d)),Person.class);
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>All find methods take a <classname>Query</classname> object as a
|
|
parameter. This object defines the criteria and options used to perform
|
|
the query. The criteria is specified using a
|
|
<classname>Criteria</classname> object that has a static factory method
|
|
named <classname>where</classname> used to instantiate a new
|
|
<classname>Criteria</classname> object. We recommend using a static
|
|
import for
|
|
<classname>org.springframework.data.document.mongodb.query.Criteria.where</classname>
|
|
and <literal>Query.query</literal> to make the query more
|
|
readable.</para>
|
|
|
|
<para>This query should return a list of Person objects that meet the
|
|
specified criteria. The Criteria class has the following methods that
|
|
correspond to the operators provided in MongoDB.</para>
|
|
|
|
<para>As you can see most methods return the
|
|
<classname>Criteria</classname> object to provide a fluent style for the
|
|
API.</para>
|
|
|
|
<section>
|
|
<title>Methods for the Criteria class</title>
|
|
|
|
<para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">all
|
|
</emphasis> <literal>(Object o)</literal>Creates a criterion
|
|
using the <literal>$all</literal> operator</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis
|
|
role="bold">elemMatch </emphasis> <literal>(Criteria c)
|
|
</literal>Creates a criterion using the
|
|
<literal>$elemMatch</literal> operator</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">exists
|
|
</emphasis> <literal>(boolean b) </literal>Creates a criterion
|
|
using the <literal>$exists</literal> operator</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">gt
|
|
</emphasis> <literal>(Object o)</literal>Creates a criterion
|
|
using the <literal>$gt</literal> operator</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">gte
|
|
</emphasis> <literal>(Object o)</literal>Creates a criterion
|
|
using the <literal>$gte</literal> operator</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">in
|
|
</emphasis> <literal>(Object... o) </literal>Creates a criterion
|
|
using the <literal>$in</literal> operator</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">is
|
|
</emphasis> <literal>(Object o)</literal>Creates a criterion
|
|
using the <literal>$is</literal> operator</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">lt
|
|
</emphasis> <literal>(Object o)</literal>Creates a criterion
|
|
using the <literal>$lt</literal> operator</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">lte
|
|
</emphasis> <literal>(Object o)</literal>Creates a criterion
|
|
using the <literal>$lte</literal> operator</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">mod
|
|
</emphasis> <literal>(Number value, Number
|
|
remainder)</literal>Creates a criterion using the
|
|
<literal>$mod</literal> operator</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">nin
|
|
</emphasis> <literal>(Object... o) </literal>Creates a criterion
|
|
using the <literal>$nin</literal> operator</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">not
|
|
</emphasis> <literal>()</literal>Creates a criterion using the
|
|
<literal>$not</literal> meta operator which affects the clause
|
|
directly following</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">regex
|
|
</emphasis> <literal>(String re) </literal>Creates a criterion
|
|
using a <literal>$regex</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">size
|
|
</emphasis> <literal>(int s)</literal>Creates a criterion using
|
|
the <literal>$size</literal> operator</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">type
|
|
</emphasis> <literal>(int t)</literal>Creates a criterion using
|
|
the <literal>$type</literal> operator</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">and
|
|
</emphasis> <literal>(String key) </literal>Adds a chained
|
|
<classname>Criteria</classname> with the specified
|
|
<literal>key</literal> to the current
|
|
<classname>Criteria</classname> and retuns the newly created
|
|
one</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
</section>
|
|
|
|
<para>There are also methods on the Criteria class for geospatial
|
|
queries. Here is al isting but look at the section on <link
|
|
linkend="mongo.geospatial">GeoSpatial Queries</link> to see them in
|
|
action.</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">withinCenter
|
|
</emphasis> <literal>(Circle circle)</literal>Creates a geospatial
|
|
criterion using <literal>$within $center</literal> operators</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis
|
|
role="bold">withinCenterSphere </emphasis> <literal>(Circle circle)
|
|
</literal>Creates a geospatial criterion using <literal>$within
|
|
$center</literal> operators. This is only available for Mongo 1.7
|
|
and higher.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">withinBox
|
|
</emphasis> <literal>(Box box)</literal>Creates a geospatial
|
|
criterion using a <literal>$within $box</literal> operation
|
|
<literal /></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">near
|
|
</emphasis> <literal>(Point point)</literal>Creates a geospatial
|
|
criterion using a <literal>$near </literal>operation</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Criteria</literal> <emphasis role="bold">nearSphere
|
|
</emphasis> <literal>(Point point) </literal>Creates a geospatial
|
|
criterion using <literal>$nearSphere$center</literal> operations.
|
|
This is only available for Mongo 1.7 and higher.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>The <classname>Query</classname> class has some additional methods
|
|
used to provide options for the query.</para>
|
|
|
|
<section>
|
|
<title>Methods for the Query class</title>
|
|
|
|
<para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal>Query</literal> <emphasis role="bold">addCriteria
|
|
</emphasis> <literal>(Criteria criteria)</literal> used to add
|
|
additional criteria to the query</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void</literal> <emphasis
|
|
role="bold">or</emphasis> <literal>(List<Query>
|
|
queries)</literal> Creates an or query using the
|
|
<literal>$or</literal> operator for all of the provided
|
|
queries</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Field</literal> <emphasis role="bold">fields
|
|
</emphasis> <literal>()</literal> used to define fields to be
|
|
included in the query results</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Query</literal> <emphasis role="bold">limit
|
|
</emphasis> <literal>(int limit)</literal> used to limit the
|
|
size of the returned results to the provided limit (used for
|
|
paging)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Query</literal> <emphasis role="bold">skip
|
|
</emphasis> <literal>(int skip)</literal> used to skip the
|
|
provided number of documents in the results (used for
|
|
paging)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Sort</literal> <emphasis role="bold">sort
|
|
</emphasis> <literal>()</literal> used to provide sort
|
|
definition for the results</para>
|
|
|
|
<para />
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Methods for querying for documents</title>
|
|
|
|
<para><itemizedlist>
|
|
<listitem>
|
|
<para><literal><T> List<T></literal> <emphasis
|
|
role="bold">getCollection </emphasis> <literal>(Class<T>
|
|
targetClass) </literal> Query for a list of objects of type T from
|
|
the default collection.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> List<T></literal> <emphasis
|
|
role="bold">getCollection </emphasis> <literal>(String
|
|
collectionName, Class<T> targetClass) </literal> Query for a
|
|
list of objects of type T from the specified collection.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> List<T></literal> <emphasis
|
|
role="bold">getCollection </emphasis> <literal>(String
|
|
collectionName, Class<T> targetClass, MongoReader<T>
|
|
reader) </literal> Query for a list of objects of type T from the
|
|
specified collection, mapping the DBObject using the provided
|
|
MongoReader.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> T</literal> <emphasis role="bold">findOne
|
|
</emphasis> <literal>(Query query, Class<T> targetClass)
|
|
</literal> Map the results of an ad-hoc query on the default
|
|
MongoDB collection to a single instance of an object of the
|
|
specified type.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> T</literal> <emphasis role="bold">findOne
|
|
</emphasis> <literal>(Query query, Class<T> targetClass,
|
|
MongoReader<T> reader) </literal> Map the results of an
|
|
ad-hoc query on the default MongoDB collection to a single
|
|
instance of an object of the specified type.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> T</literal> <emphasis role="bold">findOne
|
|
</emphasis> <literal>(String collectionName, Query query,
|
|
Class<T> targetClass) </literal> Map the results of an
|
|
ad-hoc query on the specified collection to a single instance of
|
|
an object of the specified type.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> T</literal> <emphasis role="bold">findOne
|
|
</emphasis> <literal>(String collectionName, Query query,
|
|
Class<T> targetClass, MongoReader<T> reader)
|
|
</literal> Map the results of an ad-hoc query on the specified
|
|
collection to a single instance of an object of the specified
|
|
type.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> List<T></literal> <emphasis
|
|
role="bold">find </emphasis> <literal>(Query query, Class<T>
|
|
targetClass) </literal> Map the results of an ad-hoc query on the
|
|
default MongoDB collection to a List of the specified type.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> List<T></literal> <emphasis
|
|
role="bold">find </emphasis> <literal>(Query query, Class<T>
|
|
targetClass, MongoReader<T> reader) </literal> Map the
|
|
results of an ad-hoc query on the default MongoDB collection to a
|
|
List of the specified type.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> List<T></literal> <emphasis
|
|
role="bold">find </emphasis> <literal>(String collectionName,
|
|
Query query, Class<T> targetClass) </literal> Map the
|
|
results of an ad-hoc query on the specified collection to a List
|
|
of the specified type.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> List<T></literal> <emphasis
|
|
role="bold">find </emphasis> <literal>(String collectionName,
|
|
Query query, Class<T> targetClass, CursorPreparer preparer)
|
|
</literal> Map the results of an ad-hoc query on the specified
|
|
collection to a List of the specified type.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> List<T></literal> <emphasis
|
|
role="bold">find </emphasis> <literal>(String collectionName,
|
|
Query query, Class<T> targetClass, MongoReader<T>
|
|
reader) </literal> Map the results of an ad-hoc query on the
|
|
specified collection to a List of the specified type.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> T</literal> <emphasis
|
|
role="bold">findAndRemove </emphasis> <literal>(Query query,
|
|
Class<T> targetClass) </literal> Map the results of an
|
|
ad-hoc query on the default MongoDB collection to a single
|
|
instance of an object of the specified type. The first document
|
|
that matches the query is returned and also removed from the
|
|
collection in the database.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> T</literal> <emphasis
|
|
role="bold">findAndRemove </emphasis> <literal>(Query query,
|
|
Class<T> targetClass, MongoReader<T> reader)
|
|
</literal> Map the results of an ad-hoc query on the default
|
|
MongoDB collection to a single instance of an object of the
|
|
specified type. The first document that matches the query is
|
|
returned and also removed from the collection in the
|
|
database.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> T</literal> <emphasis
|
|
role="bold">findAndRemove </emphasis> <literal>(String
|
|
collectionName, Query query, Class<T> targetClass)
|
|
</literal> Map the results of an ad-hoc query on the specified
|
|
collection to a single instance of an object of the specified
|
|
type. The first document that matches the query is returned and
|
|
also removed from the collection in the database.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> T</literal> <emphasis
|
|
role="bold">findAndRemove </emphasis> <literal>(String
|
|
collectionName, Query query, Class<T> targetClass,
|
|
MongoReader<T> reader) </literal> Map the results of an
|
|
ad-hoc query on the specified collection to a single instance of
|
|
an object of the specified type. The first document that matches
|
|
the query is returned and also removed from the collection in the
|
|
database.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para>The MongoReader can be used</para>
|
|
|
|
<section>
|
|
<title>Reading using MongoWriter</title>
|
|
|
|
<para>The MongoReader interface allows you to have lower level control
|
|
over the mapping of an DBObject into a Java object. This is similar to
|
|
the role of RowMapper in JdbcTemplate. The MongoReader interface
|
|
is</para>
|
|
|
|
<programlisting language="java">/**
|
|
* A MongoWriter is responsible for converting a native MongoDB DBObject to an object of type T.
|
|
*
|
|
* @param <T> the type of the object to convert from a DBObject
|
|
*/
|
|
public interface MongoReader<T> {
|
|
|
|
/**
|
|
* Ready from the native MongoDB DBObject representation to an instance of the class T.
|
|
* The given type has to be the starting point for marshalling the {@link DBObject}
|
|
* into it. So in case there's no real valid data inside {@link DBObject} for the
|
|
* given type, just return an empty instance of the given type.
|
|
*
|
|
* @param clazz the type of the return value
|
|
* @param dbo theDBObject
|
|
* @return the converted object
|
|
*/
|
|
<S extends T> S read(Class<S> clazz, DBObject dbo);
|
|
}</programlisting>
|
|
|
|
<para></para>
|
|
|
|
<para></para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="mongo.geospatial" lang="">
|
|
<title>GeoSpatial Queries</title>
|
|
|
|
<para>MongoDB supports GeoSpatial queries through the use of operators
|
|
such as <literal>$near</literal>, <literal>$within</literal>, and
|
|
<literal>$nearSphere</literal>. Methods specific to geospatial queries
|
|
are available on the <classname>Criteria</classname> class. There are
|
|
also a few shape classes, <classname>Box</classname>,
|
|
<classname>Circle</classname>, and <classname>Point</classname> that are
|
|
used in conjunction with geospatial related Criteria methods.</para>
|
|
|
|
<para>To understand how to perform GeoSpatial queries we will use the
|
|
following Venue class taken from the integration tests.which relies on
|
|
using the rich <classname>MappingMongoConverter</classname>.</para>
|
|
|
|
<programlisting language="java">@Document(collection="newyork")
|
|
public class Venue {
|
|
|
|
@Id
|
|
private String id;
|
|
private String name;
|
|
private double[] location;
|
|
|
|
@PersistenceConstructor
|
|
Venue(String name, double[] location) {
|
|
super();
|
|
this.name = name;
|
|
this.location = location;
|
|
}
|
|
|
|
public Venue(String name, double x, double y) {
|
|
super();
|
|
this.name = name;
|
|
this.location = new double[] { x, y };
|
|
}
|
|
|
|
public String getName() {
|
|
return name;
|
|
}
|
|
|
|
public double[] getLocation() {
|
|
return location;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "Venue [id=" + id + ", name=" + name + ", location="
|
|
+ Arrays.toString(location) + "]";
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>To find locations within a circle, the following query can be
|
|
used.</para>
|
|
|
|
<programlisting lang="" language="java">Circle circle = new Circle(-73.99171, 40.738868, 0.01);
|
|
List<Venue> venues =
|
|
template.find(new Query(Criteria.where("location").withinCenter(circle)), Venue.class);</programlisting>
|
|
|
|
<para>To find venues within a circle using Spherical coordinates the
|
|
following query can be used</para>
|
|
|
|
<programlisting lang="" language="java">Circle circle = new Circle(-73.99171, 40.738868, 0.003712240453784);
|
|
List<Venue> venues =
|
|
template.find(new Query(Criteria.where("location").withinCenterSphere(circle)), Venue.class);</programlisting>
|
|
|
|
<para>To find venues within a Box the following query can be used</para>
|
|
|
|
<programlisting language="java">//lower-left then upper-right
|
|
Box box = new Box(new Point(-73.99756, 40.73083), new Point(-73.988135, 40.741404));
|
|
List<Venue> venues =
|
|
template.find(new Query(Criteria.where("location").withinBox(box)), Venue.class);</programlisting>
|
|
|
|
<para>To find venues near a Point, the following query can be
|
|
used</para>
|
|
|
|
<programlisting language="java">Point point = new Point(-73.99171, 40.738868);
|
|
List<Venue> venues =
|
|
template.find(new Query(Criteria.where("location").near(point).maxDistance(0.01)), Venue.class);</programlisting>
|
|
|
|
<para>To find venues near a Point using Spherical coordines the
|
|
following query can be used</para>
|
|
|
|
<programlisting language="java">Point point = new Point(-73.99171, 40.738868);
|
|
List<Venue> venues =
|
|
template.find(new Query(
|
|
Criteria.where("location").nearSphere(point).maxDistance(0.003712240453784)),
|
|
Venue.class);
|
|
</programlisting>
|
|
|
|
<note>
|
|
<para>Support for the GeoNear command will be provided in the RC
|
|
release.</para>
|
|
</note>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Index and Collection managment</title>
|
|
|
|
<para>MongoTemplate provides a few methods for managing indexes and
|
|
collections.</para>
|
|
|
|
<section>
|
|
<title>Methods for creating an Index</title>
|
|
|
|
<para>We can create an index on a collection to improve query
|
|
performance.</para>
|
|
|
|
<example>
|
|
<title>Creating an index using the MongoTemplate</title>
|
|
|
|
<programlisting language="java">mongoTemplate.ensureIndex("MyCollection", new Index().on("name",Order.ASCENDING)); </programlisting>
|
|
</example>
|
|
|
|
<para><itemizedlist>
|
|
<listitem>
|
|
<para><literal>void</literal> <emphasis role="bold">ensureIndex
|
|
</emphasis> <literal>(IndexDefinition indexDefintion) </literal>
|
|
Ensure that an index for the provided IndexDefinition exists for
|
|
the default collection.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void</literal> <emphasis role="bold">ensureIndex
|
|
</emphasis> <literal>(String collectionName, IndexDefinition
|
|
indexSpecification) </literal> Ensure that an index for the
|
|
provided IndexDefinition exists.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para>You can create both standard indexes and geospatial indexes using
|
|
the classes <classname>IndexDefinition</classname> and
|
|
<classname>GeoSpatialIndex</classname> respectfully. For example, given
|
|
the Venue class defined in a previous section, you would declare a
|
|
geospatial query as shown below</para>
|
|
|
|
<programlisting language="java">mongoTemplate.ensureIndex(new GeospatialIndex("location"));</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Methods for working with a Collection</title>
|
|
|
|
<para>It's time to look at some code examples showing how to use the
|
|
<classname>MongoTemplate</classname>. First we look at creating our
|
|
first collection.</para>
|
|
|
|
<example>
|
|
<title>Working with collections using the MongoTemplate</title>
|
|
|
|
<programlisting language="java">DBCollection collection = null;
|
|
if (!mongoTemplate.getCollectionNames().contains("MyNewCollection")) {
|
|
collection = mongoTemplate.createCollection("MyNewCollection");
|
|
}
|
|
|
|
mongoTemplate.dropCollection("MyNewCollection"); </programlisting>
|
|
</example>
|
|
|
|
<para><itemizedlist>
|
|
<listitem>
|
|
<para><literal>Set<String></literal> <emphasis
|
|
role="bold">getCollectionNames </emphasis> <literal>()</literal> A
|
|
set of collection names.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>boolean</literal> <emphasis
|
|
role="bold">collectionExists </emphasis> <literal>(String
|
|
collectionName) </literal> Check to see if a collection with a
|
|
given name exists.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>DBCollection</literal> <emphasis
|
|
role="bold">createCollection </emphasis> <literal>(String
|
|
collectionName) </literal> Create an uncapped collection with the
|
|
provided name.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>DBCollection</literal> <emphasis
|
|
role="bold">createCollection </emphasis> <literal>(String
|
|
collectionName, CollectionOptions collectionOptions) </literal>
|
|
Create a collect with the provided name and options.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void</literal> <emphasis role="bold">dropCollection
|
|
</emphasis> <literal>(String collectionName) </literal> Drop the
|
|
collection with the given name.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>DBCollection</literal> <emphasis
|
|
role="bold">getCollection </emphasis> <literal>(String
|
|
collectionName) </literal> Get a collection by name, creating it
|
|
if it doesn't exist.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>DBCollection</literal> <emphasis
|
|
role="bold">getDefaultCollection </emphasis> <literal>()</literal>
|
|
The default collection used by this template.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>String</literal> <emphasis
|
|
role="bold">getDefaultCollectionName </emphasis>
|
|
<literal>()</literal> The default collection name used by this
|
|
template.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para></para>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Executing Commands</title>
|
|
|
|
<para>You can also get at the Mongo driver's collection.command( ) method
|
|
using the executeCommand methods on MongoTemplate. These will also perform
|
|
exception translation into Spring's Data Access Exception
|
|
hierarchy.</para>
|
|
|
|
<section>
|
|
<title>Methods for executing commands</title>
|
|
|
|
<para><itemizedlist>
|
|
<listitem>
|
|
<para><literal>CommandResult</literal> <emphasis
|
|
role="bold">executeCommand </emphasis> <literal>(DBObject command)
|
|
</literal> Execute a MongoDB command.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>CommandResult</literal> <emphasis
|
|
role="bold">executeCommand </emphasis> <literal>(String
|
|
jsonCommand) </literal> Execute the a MongoDB command expressed as
|
|
a JSON string.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para></para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="mongodb.mapping-usage.events">
|
|
<title>Lifecycle Events</title>
|
|
|
|
<para>Built into the MongoDB mapping framework are several
|
|
<classname>org.springframework.context.ApplicationEvent</classname> events
|
|
that your application can respond to by registering special beans in the
|
|
<code>ApplicationContext</code>. By being based off Spring's
|
|
ApplicationContext event infastructure this enables other products, such
|
|
as Spring Integration, to easily receive these events as they are a well
|
|
known eventing mechanism in Spring based applications.</para>
|
|
|
|
<para>To intercept an object before it goes through the conversion process
|
|
(which turns your domain object into a
|
|
<classname>com.mongodb.DBObject</classname>), you'd register a subclass of
|
|
<classname>org.springframework.data.document.mongodb.mapping.event.AbstractMappingEventListener</classname>
|
|
that overrides the <code>onBeforeConvert</code> method. When the event is
|
|
dispatched, your listener will be called and passed the domain object
|
|
before it goes into the converter.</para>
|
|
|
|
<example>
|
|
<programlisting language="java">
|
|
public class BeforeConvertListener<BeforeConvertEvent, Person> extends AbstractMappingEventListener {
|
|
@Override
|
|
public void onBeforeConvert(Person p) {
|
|
... does some auditing manipulation, set timestamps, whatever ...
|
|
}
|
|
}
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>To intercept an object before it goes into the database, you'd
|
|
register a subclass of
|
|
<classname>org.springframework.data.document.mongodb.mapping.event.AbstractMappingEventListener</classname>
|
|
that overrides the <code>onBeforeSave</code> method. When the event is
|
|
dispatched, your listener will be called and passed the domain object and
|
|
the converted <classname>com.mongodb.DBObject</classname>.</para>
|
|
|
|
<example>
|
|
<programlisting language="java">
|
|
public class BeforeSaveListener<BeforeSaveEvent, Person> extends AbstractMappingEventListener {
|
|
@Override
|
|
public void onBeforeSave(Person p, DBObject dbo) {
|
|
... change values, delete them, whatever ...
|
|
}
|
|
}
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>Simply declaring these beans in your Spring ApplicationContext will
|
|
cause them to be invoked whenever the event is dispatched.</para>
|
|
|
|
<para>The list of callback methods that are present in
|
|
AbstractMappingEventListener are</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><methodname>onBeforeConvert</methodname> - called in
|
|
MongoTemplate insert, insertList and save operations before the object
|
|
is converted to a DBObject using a MongoConveter.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><methodname>onBeforeSave</methodname> - called in MongoTemplate
|
|
insert, insertList and save operations <emphasis>before</emphasis>
|
|
inserting/saving the DBObject in the database.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><methodname>onAfterSave</methodname> - called in MongoTemplate
|
|
insert, insertList and save operations <emphasis>after</emphasis>
|
|
inserting/saving the DBObject in the database.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><methodname>onAfterLoad</methodname> - called in MongoTempnlate
|
|
find, findAndRemove, findOne and getCollection methods after the
|
|
DBObject is retrieved from the database.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><methodname>onAfterConvert</methodname> - called in
|
|
MongoTempnlate find, findAndRemove, findOne and getCollection methods
|
|
after the DBObject retrieved from the database was converted to a
|
|
POJO.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section id="mongo.exception" label="">
|
|
<title>Exception Translation</title>
|
|
|
|
<para>The Spring framework provides exception translation for a wide
|
|
variety of database and mapping technologies. This has traditionally been
|
|
for JDBC and JPA. The Spring support for Mongo extends this feature to the
|
|
MongoDB Database by providing an implementation of the
|
|
<classname>org.springframework.dao.support.PersistenceExceptionTranslator</classname>
|
|
interface.</para>
|
|
|
|
<para>The motivation behind mapping to Spring's <ulink
|
|
url="http://static.springsource.org/spring/docs/3.0.x/reference/dao.html#dao-exceptions">consistent
|
|
data access exception hierarchy</ulink> is that you are then able to write
|
|
portable and descriptive exception handling code without resorting to
|
|
coding against <ulink
|
|
url="http://www.mongodb.org/display/DOCS/Error+Codes">MongoDB error
|
|
codes</ulink>. All of Spring's data access exceptions are inherited from
|
|
the root <classname>DataAccessException</classname> class so you can be
|
|
sure that you will be able to catch all database related exception within
|
|
a single try-catch block. Note, that not all exceptions thrown by the
|
|
MongoDB driver inherit from the MongoException class. The inner exception
|
|
and message are preserved so no information is lost.</para>
|
|
|
|
<para>Some of the mappings performed by the MongoExceptionTranslator are:
|
|
com.mongodb.Network to DataAccessResourceFailureException and
|
|
MongoException error codes 1003, 12001, 12010, 12011, 12012 to
|
|
InvalidDataAccessApiUsageException. Look into the implementation for more
|
|
details on the mapping.</para>
|
|
</section>
|
|
|
|
<section id="mongo.executioncallback">
|
|
<title>Execution Callback</title>
|
|
|
|
<para>One common design feature of all Spring template classes is that all
|
|
functionality is routed into one of the templates execute callback
|
|
methods. This helps ensure that exceptions and any resource management
|
|
that maybe required are performed consistency. While this was of much
|
|
greater need in the case of JDBC and JMS than with MongoDB, it still
|
|
offers a single spot for exception translation and logging to occur. As
|
|
such, using thexe execute callback is the preferred way to access the
|
|
Mongo driver's DB and Collection objects to perform uncommon operations
|
|
that were not exposed as methods on
|
|
<classname>MongoTemplate</classname>.</para>
|
|
|
|
<para>Here is a list of execute callback methods.</para>
|
|
|
|
<para><itemizedlist>
|
|
<listitem>
|
|
<para><literal><T> T</literal> <emphasis role="bold">execute
|
|
</emphasis> <literal>(CollectionCallback<T> action) </literal>
|
|
Executes the given CollectionCallback on the default
|
|
collection.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> T</literal> <emphasis role="bold">execute
|
|
</emphasis> <literal>(String collectionName,
|
|
CollectionCallback<T> action) </literal> Executes the given
|
|
CollectionCallback on the collection of the given name.update using
|
|
the $addToSet update modifier</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> T</literal> <emphasis role="bold">execute
|
|
</emphasis> <literal>(DbCallback<T> action) </literal>
|
|
Executes a DbCallback translating any exceptions as
|
|
necessary.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><T> T</literal> <emphasis
|
|
role="bold">executeInSession </emphasis>
|
|
<literal>(DbCallback<T> action) </literal> Executes the given
|
|
DbCallback within the same connection to the database so as to
|
|
ensure consistency in a write heavy environment where you may read
|
|
the data that you wrote.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para>Here is an example that uses the CollectionCallback to return
|
|
information about an index.</para>
|
|
|
|
<programlisting language="java"> boolean hasIndex = template.execute("geolocation", new CollectionCallback<Boolean>() {
|
|
public Boolean doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
|
List<DBObject> indexes = collection.getIndexInfo();
|
|
for (DBObject dbo : indexes) {
|
|
if ("location_2d".equals(dbo.get("name"))) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
});</programlisting>
|
|
</section>
|
|
</chapter>
|