Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

DATACMNS-159 - Improve reference documentation on repository extensions.

Updated section covering adding custom behavior to all repositories to better match what is in the actual code base.
  • Loading branch information...
commit a0bec0fce04af8c798aa269e61eafaa63541601c 1 parent 6a461c0
Karl Bennett authored olivergierke committed
Showing with 73 additions and 29 deletions.
  1. +73 −29 src/docbkx/repositories.xml
View
102 src/docbkx/repositories.xml
@@ -23,6 +23,15 @@
interfaces of Spring Data repositories in general for detailled
information on the specific features of a particular store consult the
later chapters of this document.</para>
+
+ <note>
+ <para>As this part of the documentation is pulled in from Spring Data
+ Commons we have to decide for a particular module to be used as example.
+ The configuration and code samples in this chapter are using the JPA
+ module. Make sure you adapt e.g. the XML namespace declaration, types to
+ be extended to the equivalents of the module you're actually
+ using.</para>
+ </note>
</section>
<section id="repositories.core-concepts">
@@ -664,7 +673,8 @@ UserRepository repository = factory.getRepository(UserRepository.class);</progra
<example>
<title>An interface declaring custom shared behaviour</title>
- <para><programlisting language="java">public interface MyRepository&lt;T, ID extends Serializable&gt;
+ <para><programlisting language="java">
+public interface MyRepository&lt;T, ID extends Serializable&gt;
extends JpaRepository&lt;T, ID&gt; {
void sharedCustomMethod(ID id);
@@ -672,59 +682,93 @@ UserRepository repository = factory.getRepository(UserRepository.class);</progra
</example>
<para>Now your individual repository interfaces will extend this
- intermediate interface to include the functionality declared. The second
- step is to create an implementation of this interface that extends the
- persistence technology specific repository base class which will act as
- custom base class for the repository proxies then.</para>
+ intermediate interface instead of the
+ <interfacename>Repository</interfacename> interface to include the
+ functionality declared. The second step is to create an implementation
+ of this interface that extends the persistence technology specific
+ repository base class which will then act as a custom base class for the
+ repository proxies.</para>
<note>
- <para>If you're using automatic repository interface detection using
- the Spring namespace using the interface just as is will cause Spring
- to create an instance of <interfacename>MyRepository</interfacename>.
- This is of course not 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
- instantiated as repository instance annotate it with
- <interfacename>@NoRepositoryBean</interfacename>.</para>
+ <para>The default behaviour of the Spring <code>&lt;repositories
+ /&gt;</code> namespace is to provide an implementation for all
+ interfaces that fall under the <code>base-package</code>. This means
+ that if left in it's current state, an implementation instance of
+ <interfacename>MyRepository</interfacename> will be created by Spring.
+ This is of course not desired as it is just supposed to act as an
+ 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 instantiated as a
+ repository instance it can either be annotate it with
+ <interfacename>@NoRepositoryBean</interfacename> or moved out side of
+ the configured <code>base-package</code>.</para>
</note>
<example>
<title>Custom repository base class</title>
- <programlisting language="java">public class MyRepositoryImpl&lt;T, ID extends Serializable&gt;
+ <programlisting language="java">
+public class MyRepositoryImpl&lt;T, ID extends Serializable&gt;
extends SimpleJpaRepository&lt;T, ID&gt; implements MyRepository&lt;T, ID&gt; {
+ private EntityManager entityManager;
+
+ // There are two constructors to choose from, either can be used.
+ public MyRepositoryImpl(Class&lt;T&gt; domainClass, EntityManager entityManager) {
+ super(domainClass, entityManager);
+
+ // This is the recommended method for accessing inherited class dependencies.
+ this.entityManager = entityManager;
+ }
+
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 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>
+ <para>The last step is to create a custom repository factory to replace
+ the default <classname>RepositoryFactoryBean</classname> that will in
+ turn produce a custom <classname>RepositoryFactory</classname>. The new
+ repository factory will then provide your
+ <classname>MyRepositoryImpl</classname> as the implementation of any
+ interfaces that extend the <interfacename>Repository</interfacename>
+ interface, replacing the <classname>SimpleJpaRepository</classname>
+ implementation you just extended.</para>
<example>
<title>Custom repository factory bean</title>
- <programlisting language="java">public class MyRepositoryFactoryBean&lt;T extends JpaRepository&lt;?, ?&gt;
- extends JpaRepositoryFactoryBean&lt;T&gt; {
+ <programlisting language="java">
+public class MyRepositoryFactoryBean&lt;R extends JpaRepository&lt;T, I&gt;, T, I extends Serializable&gt;
+ extends JpaRepositoryFactoryBean&lt;R, T, I&gt; {
+
+ protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
- protected RepositoryFactorySupport getRepositoryFactory(…) {
- return new MyRepositoryFactory(…);
+ return new MyRepositoryFactory(entityManager);
}
- private static class MyRepositoryFactory extends JpaRepositoryFactory{
+ private static class MyRepositoryFactory&lt;T, I extends Serializable&gt; extends JpaRepositoryFactory {
- public MyRepositoryImpl getTargetRepository(…) {
- return new MyRepositoryImpl(…);
+ private EntityManager entityManager;
+
+ public MyRepositoryFactory(EntityManager entityManager) {
+ super(entityManager);
+
+ this.entityManager = entityManager;
+ }
+
+ protected Object getTargetRepository(RepositoryMetadata metadata) {
+
+ return new MyRepositoryImpl&lt;T, I&gt;((Class&lt;T&gt;) metadata.getDomainClass(), entityManager);
}
- public Class&lt;? extends RepositorySupport&gt; getRepositoryClass() {
- return MyRepositoryImpl.class;
+ protected Class&lt;?&gt; getRepositoryBaseClass(RepositoryMetadata metadata) {
+
+ // The RepositoryMetadata can be safely ignored, it is used by the JpaRepositoryFactory
+ //to check for QueryDslJpaRepository's which is out of scope.
+ return MyRepository.class;
}
}
}</programlisting>
Please sign in to comment.
Something went wrong with that request. Please try again.