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:
Oliver Gierke
2011-02-03 14:28:28 +00:00
parent e2146bf997
commit 3ecad1cfd2
3 changed files with 266 additions and 270 deletions

View File

@@ -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>

View 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&lt;Person, Long&gt; {
}</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">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
&lt;mongo:repositories base-package="com.acme.*.repositories"
mongo-template-ref="myMongoTemplate" /&gt;
&lt;/beans&gt;</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&lt;Person&gt; 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&lt;Person, Long&gt; {
List&lt;Person&gt; findByLastname(String lastname);
Page&lt;Person&gt; 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>

View File

@@ -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&lt;Person, Long&gt; {
}</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">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
&lt;mongo:repositories base-package="com.acme.*.repositories"
mongo-template-ref="myMongoTemplate" /&gt;
...
&lt;/beans&gt;</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&lt;T, ID extends Serializable&gt; {
T findById(ID id);
List&lt;T&gt; findAll();
T save(T entity);
List&lt;T&gt; findAll(Sort sort);
Page&lt;T&gt; 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&lt;Person&gt; 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&lt;Person, Long&gt; {
List&lt;Person&gt; findByLastname(String lastname);
Page&lt;Person&gt; 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>