DATADOC-30 - Improvements to reference documentation.
Included core repository documentation from Spring Data Commons. Polished documents and restructured them a little.
This commit is contained in:
@@ -25,7 +25,6 @@
|
||||
<author>
|
||||
<firstname>Costin</firstname>
|
||||
<surname>Leau</surname>
|
||||
<affiliation>SpringSource</affiliation>
|
||||
</author>
|
||||
</authorgroup>
|
||||
|
||||
@@ -48,13 +47,15 @@
|
||||
<xi:include href="introduction/why-sd-doc.xml"/>
|
||||
<xi:include href="introduction/requirements.xml"/>
|
||||
<xi:include href="introduction/getting-started.xml"/>
|
||||
<xi:include href="https://github.com/SpringSource/spring-data-commons/raw/master/src/docbkx/repositories.xml" />
|
||||
</part>
|
||||
|
||||
<part id="reference">
|
||||
<title>Reference Documentation</title>
|
||||
<part id="mongodb">
|
||||
<title>Mongo DB</title>
|
||||
|
||||
<xi:include href="reference/introduction.xml"/>
|
||||
<xi:include href="reference/mongodb.xml"/>
|
||||
<xi:include href="reference/mongo-repositories.xml"/>
|
||||
</part>
|
||||
|
||||
</book>
|
||||
242
src/docbkx/reference/mongo-repositories.xml
Normal file
242
src/docbkx/reference/mongo-repositories.xml
Normal file
@@ -0,0 +1,242 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<chapter>
|
||||
<title>Mongo repositories</title>
|
||||
|
||||
<abstract>
|
||||
<para>This chapter will point out the specialties for repository support
|
||||
for MongoDB. This builds on the core repository support explained in <xref
|
||||
linkend="repositories" />. So make sure you've got a sound understanding
|
||||
of the basic concepts explained there.</para>
|
||||
</abstract>
|
||||
|
||||
<para>To access domain entities stored in a MongoDB you can leverage our
|
||||
sophisticated repository support that eases implementing those quite
|
||||
significantly. To do so, simply create an interface for your
|
||||
repository:</para>
|
||||
|
||||
<example>
|
||||
<title>Sample Person entity</title>
|
||||
|
||||
<programlisting language="java">public class Person {
|
||||
|
||||
private ObjectId id;
|
||||
private String firstname;
|
||||
private String lastname;
|
||||
|
||||
// … getters and setters omitted
|
||||
}</programlisting>
|
||||
</example>
|
||||
|
||||
<para>We have a quite simple domain object here. Note that it has a property
|
||||
named <code>id</code> of type <classname>ObjectId</classname>. The default
|
||||
serialization mechanism used in <classname>MongoTemplate</classname> (which
|
||||
is backing the repository support) regards properties named id as document
|
||||
id. Currently we support <classname>String</classname>,
|
||||
<classname>ObjectId</classname> and <classname>BigInteger</classname> as
|
||||
id-types.</para>
|
||||
|
||||
<example>
|
||||
<title>Basic repository interface to persist Person entities</title>
|
||||
|
||||
<programlisting>public interface PersonRepository extends MongoRepository<Person, Long> {
|
||||
|
||||
}</programlisting>
|
||||
</example>
|
||||
|
||||
<para>The central MongoDB CRUD repository interface is
|
||||
<interfacename>MongoRepository</interfacename>. Right now this interface
|
||||
simply serves typing purposes but we will add additional methods to it
|
||||
later. In your Spring configuration simply add</para>
|
||||
|
||||
<example>
|
||||
<title>General mongo repository Spring configuration</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:mongo="http://www.springframework.org/schema/data/mongo"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/data/mongo
|
||||
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<mongo:repositories base-package="com.acme.*.repositories"
|
||||
mongo-template-ref="myMongoTemplate" />
|
||||
|
||||
…
|
||||
|
||||
</beans></programlisting>
|
||||
</example>
|
||||
|
||||
<para>This namespace element will cause the base packages to be scanned for
|
||||
interfaces extending <interfacename>MongoRepository</interfacename> and
|
||||
create Spring beans for each of them found. By default the repositories will
|
||||
get a <classname>MongoTemplate</classname> Spring bean wired that is called
|
||||
<code>mongoTemplate</code>, so you only need to configure
|
||||
<code>mongo-template-ref</code> explicitly if you deviate from this
|
||||
convention. </para>
|
||||
|
||||
<para><interfacename>MongoRepository</interfacename> extends
|
||||
<interfacename>PagingAndSortingRepository</interfacename> which you can read
|
||||
about in <xref linkend="repositories.repository" />. In general it provides
|
||||
you with CRUD operations as well as methods for paginated and sorted access
|
||||
to the entities. Working with the repository instance is just a matter of
|
||||
dependency injecting it into a client. So accessing the second page of
|
||||
<classname>Person</classname>s at a page size of 10 would simply look
|
||||
something like this:</para>
|
||||
|
||||
<example>
|
||||
<title>Paging access to Person entities</title>
|
||||
|
||||
<programlisting>@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
class PersonRepositoryTests {
|
||||
|
||||
@Autowired PersonRepository repository;
|
||||
|
||||
@Test
|
||||
public void readsFirstPageCorrectly() {
|
||||
|
||||
Page<Person> persons = repository.findAll(new PageRequest(0, 10));
|
||||
assertThat(persons.isFirstPage(), is(true));
|
||||
}
|
||||
}</programlisting>
|
||||
</example>
|
||||
|
||||
<para>The sample creates an application context with Spring's unit test
|
||||
support which will perform annotation based dependency injection into test
|
||||
cases. Inside the test method we simply use the repository to query the
|
||||
datastore. We hand the repository a <classname>PageRequest</classname>
|
||||
instance that requests the first page of persons at a page size of
|
||||
10.</para>
|
||||
|
||||
<section id="mongodb.repositories.queries">
|
||||
<title>Query methods</title>
|
||||
|
||||
<para>Most of the data access operations you usually trigger on a
|
||||
repository result a query being executed against the Mongo databases.
|
||||
Defining such a query is just a matter of declaring a method on the
|
||||
repository interface</para>
|
||||
|
||||
<example>
|
||||
<title>PersonRepository with query methods</title>
|
||||
|
||||
<programlisting>public interface PersonRepository extends MongoRepository<Person, Long> {
|
||||
|
||||
List<Person> findByLastname(String lastname);
|
||||
|
||||
Page<Person> findByFirstname(String firstname, Pageable pageable);
|
||||
}</programlisting>
|
||||
</example>
|
||||
|
||||
<para>The first method shows a query for all people with the given
|
||||
lastname. The query will be derived parsing the method name for
|
||||
constraints which can be concatenated with <literal>And</literal> and
|
||||
<literal>Or</literal>. Thus the method name will result in a query
|
||||
expression of <code>{"lastname" : lastname}</code>. The second example
|
||||
shows how pagination is applied to a query. Just equip your method
|
||||
signature with a <interfacename>Pageable</interfacename> parameter and let
|
||||
the method return a <interfacename>Page</interfacename> instance and we
|
||||
will automatically page the query accordingly.</para>
|
||||
|
||||
<para><table>
|
||||
<title>Supported keywords for query methods</title>
|
||||
|
||||
<tgroup cols="3">
|
||||
<colspec colwidth="1*" />
|
||||
|
||||
<colspec colwidth="2*" />
|
||||
|
||||
<colspec colwidth="2*" />
|
||||
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Keyword</entry>
|
||||
|
||||
<entry>Sample</entry>
|
||||
|
||||
<entry>Logical result</entry>
|
||||
</row>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><literal>GreaterThan</literal></entry>
|
||||
|
||||
<entry><methodname>findByAgeGreaterThan(int
|
||||
age)</methodname></entry>
|
||||
|
||||
<entry><code>{"age" : {"$gt" : age}}</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>LessThan</literal></entry>
|
||||
|
||||
<entry><methodname>findByAgeLessThan(int
|
||||
age)</methodname></entry>
|
||||
|
||||
<entry><code>{"age" : {"$lt" : age}}</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>Between</literal></entry>
|
||||
|
||||
<entry><methodname>findByAgeBetween(int from, int
|
||||
to)</methodname></entry>
|
||||
|
||||
<entry><code>{"age" : {"$gt" : from, "$lt" : to}}</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>IsNotNull</literal>,
|
||||
<literal>NotNull</literal></entry>
|
||||
|
||||
<entry><methodname>findByFirstnameNotNull()</methodname></entry>
|
||||
|
||||
<entry><code>{"age" : {"$ne" : null}}</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>IsNull</literal>,
|
||||
<literal>Null</literal></entry>
|
||||
|
||||
<entry><methodname>findByFirstnameNull()</methodname></entry>
|
||||
|
||||
<entry><code>{"age" : null}</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>Like</literal></entry>
|
||||
|
||||
<entry><methodname>findByFirstnameLike(String
|
||||
name)</methodname></entry>
|
||||
|
||||
<entry><code>{"age" : age}</code> (<varname>age</varname> as
|
||||
regex)</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>(No keyword)</entry>
|
||||
|
||||
<entry><methodname>findByFirstname(String
|
||||
name)</methodname></entry>
|
||||
|
||||
<entry><code>{"age" : name}</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>Not</literal></entry>
|
||||
|
||||
<entry><methodname>findByFirstnameNot(String
|
||||
name)</methodname></entry>
|
||||
|
||||
<entry><code>{"age" : {"$ne" : name}}</code></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table></para>
|
||||
</section>
|
||||
</chapter>
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
|
||||
<chapter id="mongodb">
|
||||
<title>MongoDB support</title>
|
||||
<chapter id="mongo.core" xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<title>Core support</title>
|
||||
|
||||
<para>One of the document stores supported by DATADOC is <ulink
|
||||
url="http://www.mongodb.org/">MongoDB</ulink>. To quote the project home
|
||||
@@ -24,27 +24,18 @@
|
||||
<para>The MongoDB support provides several components:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<emphasis>Configuration Factory</emphasis>
|
||||
<listitem><emphasis>Configuration Factory</emphasis> - for configuring
|
||||
and handling communication with MongoDB via its Java driver</listitem>
|
||||
|
||||
- for configuring and handling communication with MongoDB via its Java driver
|
||||
</listitem>
|
||||
<listitem><emphasis>Template implemenattion</emphasis> - providing a
|
||||
generified, user friendly template classes for interacting with MongoDB.
|
||||
<xref linkend="mongodb:template" /> explains the abstraction builds on
|
||||
top of the low-level MongoDB Java API to handle the storage and
|
||||
retrieval of documents plus mapping between documents and domain
|
||||
classes.</listitem>
|
||||
|
||||
<listitem>
|
||||
<emphasis>Template implemenattion</emphasis>
|
||||
|
||||
- providing a generified, user friendly template classes for interacting with MongoDB.
|
||||
|
||||
<xref linkend="mongodb:template" />
|
||||
|
||||
explains the abstraction builds on top of the low-level MongoDB Java API to handle the storage and retrieval of documents plus mapping between documents and domain classes.
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<emphasis>Support Classes</emphasis>
|
||||
|
||||
- that offer reusable components such as mapping support and exception translation.
|
||||
</listitem>
|
||||
<listitem><emphasis>Support Classes</emphasis> - that offer reusable
|
||||
components such as mapping support and exception translation.</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>For most tasks, the higher-level abstractions and support services
|
||||
@@ -162,14 +153,17 @@ public class AppConfig {
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><interfacename>Collection
|
||||
Operations</interfacename></entry>
|
||||
<entry>
|
||||
<interfacename>Collection Operations</interfacename>
|
||||
</entry>
|
||||
|
||||
<entry>MongoDB document operations</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><interfacename>Document Operations</interfacename></entry>
|
||||
<entry>
|
||||
<interfacename>Document Operations</interfacename>
|
||||
</entry>
|
||||
|
||||
<entry>MongoDB collection operations</entry>
|
||||
</row>
|
||||
@@ -184,247 +178,6 @@ public class AppConfig {
|
||||
Java-based default converter for most of its operations...</para>
|
||||
</section>
|
||||
|
||||
<section id="mongodb.repositories">
|
||||
<title>Repositories</title>
|
||||
|
||||
<para>To access domain entities stored in a MongoDB you can leverage our
|
||||
sophisticated repository support that eases implementing those quite
|
||||
significantly. To do so, simply create an interface for your
|
||||
repository:</para>
|
||||
|
||||
<example>
|
||||
<title>Sample Person entity</title>
|
||||
|
||||
<programlisting language="java">public class Person {
|
||||
|
||||
private String firstname;
|
||||
private String lastname;
|
||||
}</programlisting>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<title>Basic repository interface to persist Person entities</title>
|
||||
|
||||
<programlisting>public interface PersonRepository extends MongoRepository<Person, Long> {
|
||||
|
||||
}</programlisting>
|
||||
</example>
|
||||
|
||||
<para>Right now this interface simply serves typing purposes but we will
|
||||
add additional methods to it later. In your Spring configuration simply
|
||||
add</para>
|
||||
|
||||
<example>
|
||||
<title>General mongo repository Spring configuration</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:mongo="http://www.springframework.org/schema/data/mongo"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/data/mongo
|
||||
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<mongo:repositories base-package="com.acme.*.repositories"
|
||||
mongo-template-ref="myMongoTemplate" />
|
||||
|
||||
...
|
||||
|
||||
</beans></programlisting>
|
||||
</example>
|
||||
|
||||
<para>This namespace element will cause the base packages to be scanned
|
||||
for interfaces extending <interfacename>MongoRepository</interfacename>
|
||||
and create Spring beans for each of them found. These Spring beans are
|
||||
backed by a generic repository implementation that provides you a variety
|
||||
of useful methods to work with <classname>Person</classname>
|
||||
entities.</para>
|
||||
|
||||
<example>
|
||||
<title>Generic repository interface</title>
|
||||
|
||||
<programlisting language="java">public interface Repository<T, ID extends Serializable> {
|
||||
|
||||
T findById(ID id);
|
||||
|
||||
List<T> findAll();
|
||||
|
||||
T save(T entity);
|
||||
|
||||
List<T> findAll(Sort sort);
|
||||
|
||||
Page<T> findAll(Pageable pageable);
|
||||
|
||||
// further methods omitted
|
||||
}</programlisting>
|
||||
</example>
|
||||
|
||||
<para>We've just listed a brief excerpt of the methods here. As you can
|
||||
see you get access to basic CRUD operations as well as some more
|
||||
sophisicated ones that allow programmatic sorting and pagination over the
|
||||
entities handled by the repository. Working with the repository instance
|
||||
is just a matter of dependency injecting it into a client. So accessing
|
||||
the second page of <classname>Person</classname>s at a page size of 10
|
||||
would simply look something like this:</para>
|
||||
|
||||
<example>
|
||||
<title>Paging access to Person entities</title>
|
||||
|
||||
<programlisting>@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
class PersonRepositoryTests {
|
||||
|
||||
@Autowired PersonRepository repository;
|
||||
|
||||
@Test
|
||||
public void readsFirstPageCorrectly() {
|
||||
|
||||
Page<Person> persons = repository.findAll(new PageRequest(0, 10));
|
||||
assertThat(persons.isFirstPage(), is(true));
|
||||
}
|
||||
}</programlisting>
|
||||
</example>
|
||||
|
||||
<para>The sample creates an application context with Spring's unit test
|
||||
support which will perform annotation based dependency injection into test
|
||||
cases. Inside the test method we simply use the repository to query the
|
||||
datastore. We hand the repository a <classname>PageRequest</classname>
|
||||
instance that requests the first page of persons at a page size of
|
||||
10.</para>
|
||||
|
||||
<section id="mongodb.repositories.queries">
|
||||
<title>Query methods</title>
|
||||
|
||||
<para>Most of the data access operations you usually trigger on a
|
||||
repository result a query being executed against the Mongo databases.
|
||||
Defining such a query is just a matter of declaring a method on the
|
||||
repository interface</para>
|
||||
|
||||
<example>
|
||||
<title>PersonRepository with query methods</title>
|
||||
|
||||
<programlisting>public interface PersonRepository extends MongoRepository<Person, Long> {
|
||||
|
||||
List<Person> findByLastname(String lastname);
|
||||
|
||||
Page<Person> findByFirstname(String firstname, Pageable pageable);
|
||||
}</programlisting>
|
||||
</example>
|
||||
|
||||
<para>The first method shows a query for all people with the given
|
||||
lastname. The query will be derived parsing the method name for
|
||||
constraints which can be concatenated with <literal>And</literal> and
|
||||
<literal>Or</literal>. Thus the method name will result in a query
|
||||
expression of <code>{"lastname" : lastname}</code>. The second example
|
||||
shows how pagination is applied to a query. Just equip your method
|
||||
signature with a <interfacename>Pageable</interfacename> parameter and
|
||||
let the method return a <interfacename>Page</interfacename> instance and
|
||||
we will automatically page the query accordingly.</para>
|
||||
|
||||
<para><table>
|
||||
<title>Supported keywords for query methods</title>
|
||||
|
||||
<tgroup cols="3">
|
||||
<colspec colwidth="1*" />
|
||||
|
||||
<colspec colwidth="2*" />
|
||||
|
||||
<colspec colwidth="2*" />
|
||||
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Keyword</entry>
|
||||
|
||||
<entry>Sample</entry>
|
||||
|
||||
<entry>Logical result</entry>
|
||||
</row>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><literal>GreaterThan</literal></entry>
|
||||
|
||||
<entry><methodname>findByAgeGreaterThan(int
|
||||
age)</methodname></entry>
|
||||
|
||||
<entry><code>{"age" : {"$gt" : age}}</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>LessThan</literal></entry>
|
||||
|
||||
<entry><methodname>findByAgeLessThan(int
|
||||
age)</methodname></entry>
|
||||
|
||||
<entry><code>{"age" : {"$lt" : age}}</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>Between</literal></entry>
|
||||
|
||||
<entry><methodname>findByAgeBetween(int from, int
|
||||
to)</methodname></entry>
|
||||
|
||||
<entry><code>{"age" : {"$gt" : from, "$lt" :
|
||||
to}}</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>IsNotNull</literal>,
|
||||
<literal>NotNull</literal></entry>
|
||||
|
||||
<entry><methodname>findByFirstnameNotNull()</methodname></entry>
|
||||
|
||||
<entry><code>{"age" : {"$ne" : null}}</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>IsNull</literal>,
|
||||
<literal>Null</literal></entry>
|
||||
|
||||
<entry><methodname>findByFirstnameNull()</methodname></entry>
|
||||
|
||||
<entry><code>{"age" : null}</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>Like</literal></entry>
|
||||
|
||||
<entry><methodname>findByFirstnameLike(String
|
||||
name)</methodname></entry>
|
||||
|
||||
<entry><code>{"age" : age}</code> (<varname>age</varname> as
|
||||
regex)</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>(No keyword)</entry>
|
||||
|
||||
<entry><methodname>findByFirstname(String
|
||||
name)</methodname></entry>
|
||||
|
||||
<entry><code>{"age" : name}</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>Not</literal></entry>
|
||||
|
||||
<entry><methodname>findByFirstnameNot(String
|
||||
name)</methodname></entry>
|
||||
|
||||
<entry><code>{"age" : {"$ne" : name}}</code></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table></para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id="mongodb:future">
|
||||
<title>Roadmap ahead</title>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user