DATAJPA-88 - Minor improvements to documentation.
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
|
||||
<para>Implementing a data access layer of an application has been
|
||||
cumbersome for quite a while. Too much boilerplate code had to be written.
|
||||
Domain classes were anemic and haven't been designed in a real object
|
||||
Domain classes were anemic and not designed in a real object
|
||||
oriented or domain driven manner.</para>
|
||||
|
||||
<para>Using both of these technologies makes developers life a lot easier
|
||||
@@ -30,10 +30,10 @@
|
||||
<interfacename>Repository</interfacename> (probably not that much of a
|
||||
surprise). It is typeable to the domain class to manage as well as the id
|
||||
type of the domain class. This interface mainly acts as marker interface
|
||||
to capture the types to deal with and helps us discovering interface that
|
||||
extend this one. Beyond that there's
|
||||
to capture the types to deal with and help us when discovering interfaces
|
||||
that extend this one. Beyond that there's
|
||||
<interfacename>CrudRepository</interfacename> which provides some
|
||||
sophisticated functionality around CRUD for the entity managed.</para>
|
||||
sophisticated functionality around CRUD for the entity being managed.</para>
|
||||
|
||||
<example id="repositories.repository">
|
||||
<title>Repository interface</title>
|
||||
@@ -53,7 +53,7 @@
|
||||
<area coords="15" id="repository.exists" />
|
||||
</areaspec>
|
||||
|
||||
<programlisting language="java">public interface CrudRepository<T, ID extends Serializable>
|
||||
<programlisting language="java">public interface CrudRepository<T, ID extends Serializable>
|
||||
extends Repository<T, ID> {
|
||||
|
||||
T save(T entity);
|
||||
@@ -101,7 +101,7 @@
|
||||
|
||||
<para>Usually we will have persistence technology specific sub-interfaces
|
||||
to include additional technology specific methods. We will now ship
|
||||
implementations for a variety of Spring Data modules that implement that
|
||||
implementations for a variety of Spring Data modules that implement this
|
||||
interface.</para>
|
||||
|
||||
<para>On top of the <interfacename>CrudRepository</interfacename> there is
|
||||
@@ -129,14 +129,14 @@ Page<User> users = repository.findAll(new PageRequest(1, 20);</programlist
|
||||
<section id="repositories.query-methods">
|
||||
<title>Query methods</title>
|
||||
|
||||
<para>Next to standard CRUD functionality repositories are usually query
|
||||
<para>Next to standard CRUD functionality repositories are usually queries on
|
||||
the underlying datastore. With Spring Data declaring those queries becomes
|
||||
a four-step process.</para>
|
||||
a four-step process:</para>
|
||||
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para>Declare an interface extending
|
||||
<interfacename>Repository</interfacename> or one of it's
|
||||
<interfacename>Repository</interfacename> or one of its
|
||||
sub-interfaces and type it to the domain class it shall handle.</para>
|
||||
|
||||
<programlisting language="java">public interface PersonRepository extends Repository<User, Long> { … }</programlisting>
|
||||
@@ -156,7 +156,7 @@ Page<User> users = repository.findAll(new PageRequest(1, 20);</programlist
|
||||
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.springframework.org/schema/data/jpa
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/data/jpa
|
||||
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
|
||||
@@ -182,14 +182,14 @@ Page<User> users = repository.findAll(new PageRequest(1, 20);</programlist
|
||||
|
||||
<para>At this stage we barely scratched the surface of what's possible
|
||||
with the repositories but the general approach should be clear. Let's go
|
||||
through each of these steps and and figure out details and various options
|
||||
through each of these steps and figure out details and various options
|
||||
that you have at each stage.</para>
|
||||
|
||||
<section id="repositories.definition">
|
||||
<title>Defining repository interfaces</title>
|
||||
|
||||
<para>As a very first step you define a domain class specific repository
|
||||
interface to start with. It's got to extend
|
||||
interface. It's got to extend
|
||||
<interfacename>Repository</interfacename> and be typed to the domain
|
||||
class and an ID type. If you want to expose CRUD methods for that domain
|
||||
type, extend <interfacename>CrudRepository</interfacename> instead of
|
||||
@@ -206,8 +206,8 @@ Page<User> users = repository.findAll(new PageRequest(1, 20);</programlist
|
||||
annotate your repository interface with
|
||||
<interfacename>@RepositoryDefinition</interfacename>. Extending
|
||||
<interfacename>CrudRepository</interfacename> will expose a complete
|
||||
set of methods to manipulate your entities. If you rather want to be
|
||||
selective about the methods being expose simply copy the ones you want
|
||||
set of methods to manipulate your entities. If you would rather be
|
||||
selective about the methods being exposed, simply copy the ones you want
|
||||
to expose from <interfacename>CrudRepository</interfacename> into your
|
||||
domain repository.</para>
|
||||
|
||||
@@ -244,19 +244,19 @@ interface UserRepository extends MyBaseRepository<User, Long> {
|
||||
<title>Query lookup strategies</title>
|
||||
|
||||
<para>The next thing we have to discuss is the definition of query
|
||||
methods. There's roughly two main ways how the repository proxy is
|
||||
generally able to come up with the store specific query from the
|
||||
method name. The first option is to derive the quer from the method
|
||||
methods. There are two main ways that the repository proxy is
|
||||
able to come up with the store specific query from the
|
||||
method name. The first option is to derive the query from the method
|
||||
name directly, the second is using some kind of additionally created
|
||||
query. What detailed options are available pretty much depends on the
|
||||
actual store. However there's got to be some algorithm the decision
|
||||
which actual query to is made.</para>
|
||||
actual store, however, there's got to be some algorithm that decides
|
||||
what actual query is created.</para>
|
||||
|
||||
<para>There's three strategies for the repository infrastructure to
|
||||
<para>There are three strategies available for the repository infrastructure to
|
||||
resolve the query. The strategy to be used can be configured at the
|
||||
namespace through the <code>query-lookup-strategy</code> attribute.
|
||||
However might be the case that some of the strategies are not
|
||||
supported for the specific datastore. Here are your options:</para>
|
||||
However, It might be the case that some of the strategies are not
|
||||
supported for specific datastores. Here are your options:</para>
|
||||
|
||||
<simplesect>
|
||||
<title>CREATE</title>
|
||||
@@ -273,7 +273,7 @@ interface UserRepository extends MyBaseRepository<User, Long> {
|
||||
|
||||
<para>This strategy tries to find a declared query which will be
|
||||
used for execution first. The query could be defined by an
|
||||
annotation somwhere or declared by other means. Please consult the
|
||||
annotation somewhere or declared by other means. Please consult the
|
||||
documentation of the specific store to find out what options are
|
||||
available for that store. If the repository infrastructure does not
|
||||
find a declared query for the method at bootstrap time it will
|
||||
@@ -283,13 +283,14 @@ interface UserRepository extends MyBaseRepository<User, Long> {
|
||||
<simplesect>
|
||||
<title>CREATE_IF_NOT_FOUND (default)</title>
|
||||
|
||||
<para>This strategy is actually a combination of the both mentioned
|
||||
above. It will try to lookup a declared query first but create a
|
||||
<para>This strategy is actually a combination of <code>CREATE</code>
|
||||
and <code>USE_DECLARED_QUERY</code>.
|
||||
It will try to lookup a declared query first but create a
|
||||
custom method name based query if no declared query was found. This
|
||||
is default lookup strategy and thus will be used if you don't
|
||||
is the default lookup strategy and thus will be used if you don't
|
||||
configure anything explicitly. It allows quick query definition by
|
||||
method names but also custom tuning of these queries by introducing
|
||||
declared queries for those who need explicit tuning.</para>
|
||||
declared queries as needed.</para>
|
||||
</simplesect>
|
||||
</section>
|
||||
|
||||
@@ -297,7 +298,7 @@ interface UserRepository extends MyBaseRepository<User, Long> {
|
||||
<title>Query creation</title>
|
||||
|
||||
<para>The query builder mechanism built into Spring Data repository
|
||||
infrastructue is useful to build constraining queries over entities of
|
||||
infrastructure is useful to build constraining queries over entities of
|
||||
the repository. We will strip the prefixes <code>findBy</code>,
|
||||
<code>find</code>, <code>readBy</code>, <code>read</code>,
|
||||
<code>getBy</code> as well as <code>get</code> from the method and
|
||||
@@ -315,11 +316,11 @@ interface UserRepository extends MyBaseRepository<User, Long> {
|
||||
</example>
|
||||
|
||||
<para>The actual result of parsing that method will of course depend
|
||||
on the persistence store we create the query for. However there are
|
||||
some general things to notice. The expression are usually property
|
||||
on the persistence store we create the query for, however, there are
|
||||
some general things to notice. The expressions are usually property
|
||||
traversals combined with operators that can be concatenated. As you
|
||||
can see in the example you can combine property expressions with And
|
||||
and Or. Beyond that you will get support for various operators like
|
||||
and Or. Beyond that you also get support for various operators like
|
||||
<literal>Between</literal>, <literal>LessThan</literal>,
|
||||
<literal>GreaterThan</literal>, <literal>Like</literal> for the
|
||||
property expressions. As the operators supported can vary from
|
||||
@@ -330,10 +331,10 @@ interface UserRepository extends MyBaseRepository<User, Long> {
|
||||
<title>Property expressions</title>
|
||||
|
||||
<para>Property expressions can just refer to a direct property of
|
||||
the managed entity (as you just saw in the example above. On query
|
||||
the managed entity (as you just saw in the example above). On query
|
||||
creation time we already make sure that the parsed property is at a
|
||||
property of the managed domain class. However you can also traverse
|
||||
nested properties to define constraints on. Assume
|
||||
property of the managed domain class. However, you can also define
|
||||
constraints by traversing nested properties. Assume
|
||||
<classname>Person</classname>s have <classname>Address</classname>es
|
||||
with <classname>ZipCode</classname>s. In that case a method name
|
||||
of</para>
|
||||
@@ -353,9 +354,9 @@ interface UserRepository extends MyBaseRepository<User, Long> {
|
||||
does not match we move the split point to the left
|
||||
(<literal>Address</literal>, <literal>ZipCode</literal>).</para>
|
||||
|
||||
<para>Now although this should work for most cases, there might be
|
||||
<para>Although this should work for most cases, there might be
|
||||
cases where the algorithm could select the wrong property. Suppose
|
||||
our <classname>Person</classname> class has a
|
||||
our <classname>Person</classname> class has an
|
||||
<code>addressZip</code> property as well. Then our algorithm would
|
||||
match in the first split round already and essentially choose the
|
||||
wrong property and finally fail (as the type of
|
||||
@@ -373,7 +374,7 @@ interface UserRepository extends MyBaseRepository<User, Long> {
|
||||
<title>Special parameter handling</title>
|
||||
|
||||
<para>To hand parameters to your query you simply define method
|
||||
parameters as already seen in in examples above. Besides that we will
|
||||
parameters as already seen in the examples above. Besides that we will
|
||||
recognizes certain specific types to apply pagination and sorting to
|
||||
your queries dynamically.</para>
|
||||
|
||||
@@ -390,7 +391,7 @@ List<User> findByLastname(String lastname, Pageable pageable);</programlis
|
||||
<para>The first method allows you to pass a <code>Pageable</code>
|
||||
instance to the query method to dynamically add paging to your
|
||||
statically defined query. <code>Sorting</code> options are handed via
|
||||
the <interfacename>Pageable</interfacename> instance, too. If you only
|
||||
the <interfacename>Pageable</interfacename> instance too. If you only
|
||||
need sorting, simply add a <code>Sort</code> parameter to your method.
|
||||
As you also can see, simply returning a
|
||||
<interfacename>List</interfacename> is possible as well. We will then
|
||||
@@ -418,13 +419,13 @@ List<User> findByLastname(String lastname, Pageable pageable);</programlis
|
||||
<para>The easiest way to do so is by using the Spring namespace that
|
||||
is shipped with each Spring Data module that supports the repository
|
||||
mechanism. Each of those includes a repositories element that allows
|
||||
you to simply define a base packge Spring shall scan for you.</para>
|
||||
you to simply define a base package that Spring will scan for you.</para>
|
||||
|
||||
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.springframework.org/schema/data/jpa
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/data/jpa
|
||||
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
|
||||
@@ -434,18 +435,18 @@ List<User> findByLastname(String lastname, Pageable pageable);</programlis
|
||||
</beans:beans></programlisting>
|
||||
|
||||
<para>In this case we instruct Spring to scan
|
||||
<package>com.acme.repositories</package> and all it's sub packages for
|
||||
<package>com.acme.repositories</package> and all its sub packages for
|
||||
interfaces extending <interfacename>Repository</interfacename> or one
|
||||
of its sub-interfaces. For each interface found it will register the
|
||||
presistence technology specific
|
||||
persistence technology specific
|
||||
<interfacename>FactoryBean</interfacename> to create the according
|
||||
proxies that handle invocations of the query methods. Each of these
|
||||
beans will be registered under a bean name that is derived from the
|
||||
interface name, so an interface of
|
||||
<interfacename>UserRepository</interfacename> would be registered
|
||||
under <code>userRepository</code>. The <code>base-package</code>
|
||||
attribute allows to use wildcards, so that you can have a pattern of
|
||||
packages parsed.</para>
|
||||
attribute allows the use of wildcards, so that you can have a pattern of
|
||||
scanned packages.</para>
|
||||
|
||||
<simplesect>
|
||||
<title>Using filters</title>
|
||||
@@ -454,7 +455,7 @@ List<User> findByLastname(String lastname, Pageable pageable);</programlis
|
||||
persistence technology specific
|
||||
<interfacename>Repository</interfacename> sub-interface located
|
||||
underneath the configured base package and create a bean instance
|
||||
for it. However, you might want to gain finer grained control over
|
||||
for it. However, you might want finer grained control over
|
||||
which interfaces bean instances get created for. To do this we
|
||||
support the use of <code><include-filter /></code> and
|
||||
<code><exclude-filter /></code> elements inside
|
||||
@@ -476,7 +477,7 @@ List<User> findByLastname(String lastname, Pageable pageable);</programlis
|
||||
</repositories>
|
||||
</programlisting>
|
||||
|
||||
<para>This would exclude all interface ending on
|
||||
<para>This would exclude all interfaces ending in
|
||||
<interfacename>SomeRepository</interfacename> from being
|
||||
instantiated.</para>
|
||||
</example>
|
||||
@@ -502,7 +503,7 @@ List<User> findByLastname(String lastname, Pageable pageable);</programlis
|
||||
<para>You can also use the repository infrastructure outside of a
|
||||
Spring container usage. You will still need to have some of the Spring
|
||||
libraries on your classpath but you can generally setup repositories
|
||||
programatically as well. The Spring Data modules providing repository
|
||||
programmatically as well. The Spring Data modules providing repository
|
||||
support ship a persistence technology specific
|
||||
<classname>RepositoryFactory</classname> that can be used as
|
||||
follows:</para>
|
||||
@@ -524,7 +525,7 @@ UserRepository repository = factory.getRepository(UserRepository.class);</progra
|
||||
<title>Adding behaviour to single repositories</title>
|
||||
|
||||
<para>Often it is necessary to provide a custom implementation for a few
|
||||
repository methods. Spring Data repositories easily allow provide custom
|
||||
repository methods. Spring Data repositories easily allow you to provide custom
|
||||
repository code and integrate it with generic CRUD abstraction and query
|
||||
method functionality. To enrich a repository with custom functionality
|
||||
you have to define an interface and an implementation for that
|
||||
@@ -549,7 +550,7 @@ UserRepository repository = factory.getRepository(UserRepository.class);</progra
|
||||
// Your custom implementation
|
||||
}
|
||||
}</programlisting>Note that the implementation itself does not depend on
|
||||
Spring Data and can be a regular Spring bean. So you can either use
|
||||
Spring Data and can be a regular Spring bean. So you can use
|
||||
standard dependency injection behaviour to inject references to other
|
||||
beans, take part in aspects and so on.</para>
|
||||
</example>
|
||||
@@ -598,11 +599,11 @@ UserRepository repository = factory.getRepository(UserRepository.class);</progra
|
||||
<title>Manual wiring</title>
|
||||
|
||||
<para>The approach above works perfectly well if your custom
|
||||
implementation uses annotation based configuration and autowring
|
||||
entirely as will be trated as any other Spring bean. If your customly
|
||||
implemented bean needs some special wiring you simply declare the bean
|
||||
and name it after the conventions just descibed. We will then pick up
|
||||
the custom bean by name rather than creating an own instance.</para>
|
||||
implementation uses annotation based configuration and autowiring
|
||||
entirely as it will be treated as any other Spring bean. If your custom
|
||||
implementation bean needs some special wiring you simply declare the bean
|
||||
and name it after the conventions just described. We will then pick up
|
||||
the custom bean by name rather than creating an instance.</para>
|
||||
|
||||
<example>
|
||||
<title>Manual wiring of custom implementations (I)</title>
|
||||
@@ -651,7 +652,7 @@ UserRepository repository = factory.getRepository(UserRepository.class);</progra
|
||||
<example>
|
||||
<title>An interface declaring custom shared behaviour</title>
|
||||
|
||||
<para><programlisting language="java">public interface MyRepository<T, ID extends Serializable>
|
||||
<para><programlisting language="java">public interface MyRepository<T, ID extends Serializable>
|
||||
extends JpaRepository<T, ID> {
|
||||
|
||||
void sharedCustomMethod(ID id);
|
||||
@@ -667,9 +668,9 @@ UserRepository repository = factory.getRepository(UserRepository.class);</progra
|
||||
<note>
|
||||
<para>If you're using automatic repository interface detection using
|
||||
the Spring namespace using the interface just as is will cause Spring
|
||||
trying to create an instance of
|
||||
to create an instance of
|
||||
<interfacename>MyRepository</interfacename>. This is of course not
|
||||
desired as it just acts as indermediate between
|
||||
desired as it just acts as intermediary between
|
||||
<interfacename>Repository</interfacename> and the actual repository
|
||||
interfaces you want to define for each entity. To exclude an interface
|
||||
extending <interfacename>Repository</interfacename> from being
|
||||
@@ -680,17 +681,17 @@ UserRepository repository = factory.getRepository(UserRepository.class);</progra
|
||||
<example>
|
||||
<title>Custom repository base class</title>
|
||||
|
||||
<programlisting language="java">public class MyRepositoryImpl<T, ID extends Serializable>
|
||||
<programlisting language="java">public class MyRepositoryImpl<T, ID extends Serializable>
|
||||
extends SimpleJpaRepository<T, ID> implements MyRepository<T, ID> {
|
||||
|
||||
public void sharedCustomMethod(ID id) {
|
||||
// implementation goes here
|
||||
}
|
||||
}
|
||||
}</programlisting>
|
||||
</example>
|
||||
|
||||
<para>The last step to get this implementation used as base class for
|
||||
Spring Data repositores is replacing the standard
|
||||
Spring Data repositories is replacing the standard
|
||||
<classname>RepositoryFactoryBean</classname> with a custom one using a
|
||||
custom <classname>RepositoryFactory</classname> that in turn creates
|
||||
instances of your <classname>MyRepositoryImpl</classname> class.</para>
|
||||
@@ -698,7 +699,7 @@ UserRepository repository = factory.getRepository(UserRepository.class);</progra
|
||||
<example>
|
||||
<title>Custom repository factory bean</title>
|
||||
|
||||
<programlisting language="java">public class MyRepositoryFactoryBean<T extends JpaRepository<?, ?>
|
||||
<programlisting language="java">public class MyRepositoryFactoryBean<T extends JpaRepository<?, ?>
|
||||
extends JpaRepositoryFactoryBean<T> {
|
||||
|
||||
protected RepositoryFactorySupport getRepositoryFactory(…) {
|
||||
@@ -726,7 +727,7 @@ UserRepository repository = factory.getRepository(UserRepository.class);</progra
|
||||
<example>
|
||||
<title>Using the custom factory with the namespace</title>
|
||||
|
||||
<programlisting language="xml"><repositories base-package="com.acme.repository"
|
||||
<programlisting language="xml"><repositories base-package="com.acme.repository"
|
||||
factory-class="com.acme.MyRepositoryFactoryBean" /></programlisting>
|
||||
</example>
|
||||
</section>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
trigger auto detection<footnote>
|
||||
<para>see <xref linkend="config.autoconfig" /></para>
|
||||
</footnote> of repository instances. Attributes defined for
|
||||
<code><repositories /></code> act are propagated to contained
|
||||
<code><repositories /></code> are propagated to contained
|
||||
<code><repository /></code> elements but can be overridden of
|
||||
course.</para>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user