SGF-82, SGF-83 - Initial draft of repository integration.
Added support for annotation based entity mapping (@Region, @Id, @PersistenceConstructor). Added support for Spring Data repositories (query execution, query derivation).
This commit is contained in:
@@ -13,6 +13,11 @@
|
||||
<surname>Leau</surname>
|
||||
<affiliation>SpringSource, a division of VMware</affiliation>
|
||||
</author>
|
||||
<author>
|
||||
<firstname>Oliver</firstname>
|
||||
<lastname>Gierke</lastname>
|
||||
<affiliation>SpringSource, a division of VMware</affiliation>
|
||||
</author>
|
||||
</authorgroup>
|
||||
|
||||
|
||||
@@ -41,6 +46,11 @@
|
||||
<xi:include href="reference/bootstrap.xml"/>
|
||||
<xi:include href="reference/data.xml"/>
|
||||
<xi:include href="reference/serialization.xml"/>
|
||||
<xi:include href="reference/mapping.xml"/>
|
||||
<xi:include href="https://github.com/SpringSource/spring-data-commons/raw/master/src/docbkx/repositories.xml">
|
||||
<xi:fallback href="../../../../../../spring-data-commons/src/docbkx/repositories.xml" />
|
||||
</xi:include>
|
||||
<xi:include href="reference/repositories.xml"/>
|
||||
<xi:include href="reference/samples.xml"/>
|
||||
</part>
|
||||
|
||||
|
||||
84
docs/src/reference/docbook/reference/mapping.xml
Normal file
84
docs/src/reference/docbook/reference/mapping.xml
Normal file
@@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<chapter version="5.0" xml:id="mapping" xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xmlns:ns5="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ns4="http://www.w3.org/2000/svg"
|
||||
xmlns:ns3="http://www.w3.org/1998/Math/MathML"
|
||||
xmlns:ns="http://docbook.org/ns/docbook">
|
||||
<title>POJO mapping</title>
|
||||
|
||||
<section xml:id="mapping.entities">
|
||||
<title>Entity mapping</title>
|
||||
|
||||
<para>Spring Data Gemfire provides support to map entities to be stored in
|
||||
a Gemfire grid. The mapping metadata is define by using annotations at the
|
||||
domain classes just like this: </para>
|
||||
|
||||
<example>
|
||||
<title>Mapping a domain class to Gemfire</title>
|
||||
|
||||
<programlisting language="java">@Region("myRegion")
|
||||
public class Person {
|
||||
|
||||
@Id Long id;
|
||||
String firstname;
|
||||
String lastname;
|
||||
|
||||
@PersistenceConstructor
|
||||
public Person(String firstname, String lastname) {
|
||||
// …
|
||||
}
|
||||
|
||||
…
|
||||
} </programlisting>
|
||||
</example>
|
||||
|
||||
<para>The first thing you see here is the
|
||||
<interfacename>@Region</interfacename> annotation that can be used to
|
||||
customize the region instances of the <classname>Person</classname> class
|
||||
are stored in. The <interfacename>@Id</interfacename> annotation can be
|
||||
used to annotate the property that shall be used as cache key. The
|
||||
<interfacename>@PersistenceConstructor</interfacename> annotation actually
|
||||
helps disambiguing multiple potentially available constructors taking
|
||||
parameters and explicitly marking the one annotated as the one to be used
|
||||
to create entities. With none or only a single constructor you can omit
|
||||
the annotation.</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="mapping.pdx-serializer">
|
||||
<title>Mapping PDX serializer</title>
|
||||
|
||||
<para>Spring Data Gemfire provides a custom
|
||||
<interfacename>PDXSerializer</interfacename> implementation that uses the
|
||||
mapping information to customize entity serialization. Beyond that it
|
||||
allows customizing the entity instantiation by using the Spring Data
|
||||
<interfacename>EntityInstantiator</interfacename> abstraction. By default
|
||||
the serializer uses a <classname>ReflectionEntityInstantiator</classname>
|
||||
that will use the persistence constructor of the mapped entity (either the
|
||||
single declared one or explicitly annoted with
|
||||
<interfacename>@PersistenceConstructor</interfacename>). To provide values
|
||||
for constructor parameters it will read fields with name of the
|
||||
constructor parameters from the <interfacename>PDXReader</interfacename>
|
||||
supplied.</para>
|
||||
|
||||
<example>
|
||||
<title>Using @Value on entity constructor parameters</title>
|
||||
|
||||
<programlisting language="java">public class Person {
|
||||
|
||||
public Person(@Value("#root.foo") String firstname, @Value("bean") String lastname) {
|
||||
// …
|
||||
}
|
||||
|
||||
…
|
||||
} </programlisting>
|
||||
</example>
|
||||
|
||||
<para>The entity annotated as such will get the field <code>foo</code>
|
||||
read from the <interfacename>PDXReader</interfacename> and handed as
|
||||
constructor parameter value for <code>firstname</code>. The value for
|
||||
<code>lastname</code> will be the Spring bean with name
|
||||
<code>bean</code>.</para>
|
||||
</section>
|
||||
</chapter>
|
||||
218
docs/src/reference/docbook/reference/repositories.xml
Normal file
218
docs/src/reference/docbook/reference/repositories.xml
Normal file
@@ -0,0 +1,218 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<chapter version="5.0" xml:id="gemfire-repositories"
|
||||
xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xmlns:ns5="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ns4="http://www.w3.org/2000/svg"
|
||||
xmlns:ns3="http://www.w3.org/1998/Math/MathML"
|
||||
xmlns:ns="http://docbook.org/ns/docbook">
|
||||
<title>Gemfire Repositories</title>
|
||||
|
||||
<section>
|
||||
<title xml:id="gemfire-repositories.intro">Introduction</title>
|
||||
|
||||
<para>Spring Data Gemfire provides support to use the Spring Data
|
||||
repository abstraction to easily persist entities into Gemfire and execute
|
||||
queries. A general introduction into the repository programmin model has
|
||||
been provided in <xref linkend="repositories" />.</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="gemfire-repositories.spring-configuration">
|
||||
<title>Spring configuration</title>
|
||||
|
||||
<para>To bootstrap Spring Data repositories you use the
|
||||
<code><repositories /></code> element from the Gemfire
|
||||
namespace:</para>
|
||||
|
||||
<example>
|
||||
<title>Bootstrap Gemfire repositories</title>
|
||||
|
||||
<programlisting language="xml"><beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:gf="http://www.springframework.org/schema/gemfire"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/gemfire
|
||||
http://www.springframework.org/schema/gemfire/spring-gemfire.xsd>
|
||||
|
||||
<gf:repositories base-package="com.acme.repository" />
|
||||
|
||||
</beans></programlisting>
|
||||
</example>
|
||||
|
||||
<para>This configuration snippet will look for interfaces below the
|
||||
configured base package and create repository instances for those
|
||||
interfaces backed by a <classname>SimpleGemfireRepository</classname>.
|
||||
Note that you have to have your domain classes correctly mapped to
|
||||
configured regions as the bottstrap process will fail otherwise.</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="gemfire-repositories.executing-queries">
|
||||
<title>Executing OQL queries</title>
|
||||
|
||||
<para>The Gemfire repositories allow the definition of query methods to
|
||||
easily execute OQL queries against the Region the managed entity is mapped
|
||||
to.</para>
|
||||
|
||||
<example>
|
||||
<title>Sample repository</title>
|
||||
|
||||
<programlisting language="java">@Region("myRegion")
|
||||
public class Person { … }</programlisting>
|
||||
|
||||
<programlisting language="java">public interface PersonRepository extends CrudRepository<Person, Long> {
|
||||
|
||||
Person findByEmailAddress(String emailAddress);
|
||||
|
||||
Collection<Person> findByFirstname(String firstname);
|
||||
|
||||
@Query("SELECT * FROM /Person p WHERE p.firstname = $1")
|
||||
Collection<Person> findByFirstnameAnnotated(String firstname);
|
||||
|
||||
@Query("SELECT * FROM /Person p WHERE p.firstname IN SET $1")
|
||||
Collection<Person> findByFirstnamesAnnotated(Collection<String> firstnames);
|
||||
}</programlisting>
|
||||
</example>
|
||||
|
||||
<para>The first method listed here will cause the following query to be
|
||||
derived: <code>SELECT x FROM /myRegion x WHERE x.emailAddress = $1</code>.
|
||||
The second method works the same way except it's returning all entities
|
||||
found whereas the first one expects a single result value. In case the
|
||||
supported keywords are not sufficient to declare your query or the method
|
||||
name gets to verbose you can annotate the query methods with
|
||||
<interfacename>@Query</interfacename> as seen for methods 3 and 4.</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>x.age > $1</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>GreaterThanEqual</literal></entry>
|
||||
|
||||
<entry><methodname>findByAgeGreaterThanEqual(int
|
||||
age)</methodname></entry>
|
||||
|
||||
<entry><code>x.age >= $1</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>LessThan</literal></entry>
|
||||
|
||||
<entry><methodname>findByAgeLessThan(int
|
||||
age)</methodname></entry>
|
||||
|
||||
<entry><code>x.age < $1</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>LessThanEqual</literal></entry>
|
||||
|
||||
<entry><methodname>findByAgeLessThanEqual(int
|
||||
age)</methodname></entry>
|
||||
|
||||
<entry><code>x.age <= $1</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>IsNotNull</literal>,
|
||||
<literal>NotNull</literal></entry>
|
||||
|
||||
<entry><methodname>findByFirstnameNotNull()</methodname></entry>
|
||||
|
||||
<entry><code>x.firstname =! NULL</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>IsNull</literal>,
|
||||
<literal>Null</literal></entry>
|
||||
|
||||
<entry><methodname>findByFirstnameNull()</methodname></entry>
|
||||
|
||||
<entry><code>x.firstname = NULL</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>In</literal></entry>
|
||||
|
||||
<entry><methodname>findByFirstnameIn(Collection<String>
|
||||
x)</methodname></entry>
|
||||
|
||||
<entry><code>x.firstname IN SET $1</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>NotIn</literal></entry>
|
||||
|
||||
<entry><methodname>findByFirstnameNotIn(Collection<String>
|
||||
x)</methodname></entry>
|
||||
|
||||
<entry><code>x.firstname NOT IN SET $1</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>(No keyword)</entry>
|
||||
|
||||
<entry><methodname>findByFirstname(String
|
||||
name)</methodname></entry>
|
||||
|
||||
<entry><code>x.firstname = $1</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>Not</literal></entry>
|
||||
|
||||
<entry><methodname>findByFirstnameNot(String
|
||||
name)</methodname></entry>
|
||||
|
||||
<entry><code>x.firstname != $1</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>IsTrue</literal>,
|
||||
<literal>True</literal></entry>
|
||||
|
||||
<entry><code>findByActiveIsTrue()</code></entry>
|
||||
|
||||
<entry><code>x.active = true</code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>IsFalse</literal>,
|
||||
<literal>False</literal></entry>
|
||||
|
||||
<entry><code>findByActiveIsFalse()</code></entry>
|
||||
|
||||
<entry><code>x.active = false</code></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table></para>
|
||||
</section>
|
||||
</chapter>
|
||||
Reference in New Issue
Block a user