Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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
shiver-me-timbers authored April 27, 2012 olivergierke committed April 27, 2012

Showing 1 changed file with 73 additions and 29 deletions. Show diff stats Hide diff stats

  1. 102  src/docbkx/repositories.xml
102  src/docbkx/repositories.xml
@@ -23,6 +23,15 @@
23 23
     interfaces of Spring Data repositories in general for detailled
24 24
     information on the specific features of a particular store consult the
25 25
     later chapters of this document.</para>
  26
+
  27
+    <note>
  28
+      <para>As this part of the documentation is pulled in from Spring Data
  29
+      Commons we have to decide for a particular module to be used as example.
  30
+      The configuration and code samples in this chapter are using the JPA
  31
+      module. Make sure you adapt e.g. the XML namespace declaration, types to
  32
+      be extended to the equivalents of the module you're actually
  33
+      using.</para>
  34
+    </note>
26 35
   </section>
27 36
 
28 37
   <section id="repositories.core-concepts">
@@ -664,7 +673,8 @@ UserRepository repository = factory.getRepository(UserRepository.class);</progra
664 673
       <example>
665 674
         <title>An interface declaring custom shared behaviour</title>
666 675
 
667  
-        <para><programlisting language="java">public interface MyRepository&lt;T, ID extends Serializable&gt;
  676
+        <para><programlisting language="java">
  677
+public interface MyRepository&lt;T, ID extends Serializable&gt;
668 678
   extends JpaRepository&lt;T, ID&gt; {
669 679
 
670 680
   void sharedCustomMethod(ID id);
@@ -672,59 +682,93 @@ UserRepository repository = factory.getRepository(UserRepository.class);</progra
672 682
       </example>
673 683
 
674 684
       <para>Now your individual repository interfaces will extend this
675  
-      intermediate interface to include the functionality declared. The second
676  
-      step is to create an implementation of this interface that extends the
677  
-      persistence technology specific repository base class which will act as
678  
-      custom base class for the repository proxies then.</para>
  685
+      intermediate interface instead of the
  686
+      <interfacename>Repository</interfacename> interface to include the
  687
+      functionality declared. The second step is to create an implementation
  688
+      of this interface that extends the persistence technology specific
  689
+      repository base class which will then act as a custom base class for the
  690
+      repository proxies.</para>
679 691
 
680 692
       <note>
681  
-        <para>If you're using automatic repository interface detection using
682  
-        the Spring namespace using the interface just as is will cause Spring
683  
-        to create an instance of <interfacename>MyRepository</interfacename>.
684  
-        This is of course not desired as it just acts as intermediary between
685  
-        <interfacename>Repository</interfacename> and the actual repository
686  
-        interfaces you want to define for each entity. To exclude an interface
687  
-        extending <interfacename>Repository</interfacename> from being
688  
-        instantiated as repository instance annotate it with
689  
-        <interfacename>@NoRepositoryBean</interfacename>.</para>
  693
+        <para>The default behaviour of the Spring <code>&lt;repositories
  694
+        /&gt;</code> namespace is to provide an implementation for all
  695
+        interfaces that fall under the <code>base-package</code>. This means
  696
+        that if left in it's current state, an implementation instance of
  697
+        <interfacename>MyRepository</interfacename> will be created by Spring.
  698
+        This is of course not desired as it is just supposed to act as an
  699
+        intermediary between <interfacename>Repository</interfacename> and the
  700
+        actual repository interfaces you want to define for each entity. To
  701
+        exclude an interface extending
  702
+        <interfacename>Repository</interfacename> from being instantiated as a
  703
+        repository instance it can either be annotate it with
  704
+        <interfacename>@NoRepositoryBean</interfacename> or moved out side of
  705
+        the configured <code>base-package</code>.</para>
690 706
       </note>
691 707
 
692 708
       <example>
693 709
         <title>Custom repository base class</title>
694 710
 
695  
-        <programlisting language="java">public class MyRepositoryImpl&lt;T, ID extends Serializable&gt;
  711
+        <programlisting language="java">
  712
+public class MyRepositoryImpl&lt;T, ID extends Serializable&gt;
696 713
   extends SimpleJpaRepository&lt;T, ID&gt; implements MyRepository&lt;T, ID&gt; {
697 714
 
  715
+  private EntityManager entityManager;
  716
+
  717
+  // There are two constructors to choose from, either can be used.
  718
+  public MyRepositoryImpl(Class&lt;T&gt; domainClass, EntityManager entityManager) {
  719
+    super(domainClass, entityManager);
  720
+
  721
+    // This is the recommended method for accessing inherited class dependencies.
  722
+    this.entityManager = entityManager;
  723
+  }
  724
+
698 725
   public void sharedCustomMethod(ID id) {
699 726
     // implementation goes here
700 727
   }
701 728
 }</programlisting>
702 729
       </example>
703 730
 
704  
-      <para>The last step to get this implementation used as base class for
705  
-      Spring Data repositories is replacing the standard
706  
-      <classname>RepositoryFactoryBean</classname> with a custom one using a
707  
-      custom <classname>RepositoryFactory</classname> that in turn creates
708  
-      instances of your <classname>MyRepositoryImpl</classname> class.</para>
  731
+      <para>The last step is to create a custom repository factory to replace
  732
+      the default <classname>RepositoryFactoryBean</classname> that will in
  733
+      turn produce a custom <classname>RepositoryFactory</classname>. The new
  734
+      repository factory will then provide your
  735
+      <classname>MyRepositoryImpl</classname> as the implementation of any
  736
+      interfaces that extend the <interfacename>Repository</interfacename>
  737
+      interface, replacing the <classname>SimpleJpaRepository</classname>
  738
+      implementation you just extended.</para>
709 739
 
710 740
       <example>
711 741
         <title>Custom repository factory bean</title>
712 742
 
713  
-        <programlisting language="java">public class MyRepositoryFactoryBean&lt;T extends JpaRepository&lt;?, ?&gt;
714  
-  extends JpaRepositoryFactoryBean&lt;T&gt; {
  743
+        <programlisting language="java">
  744
+public class MyRepositoryFactoryBean&lt;R extends JpaRepository&lt;T, I&gt;, T, I extends Serializable&gt;
  745
+  extends JpaRepositoryFactoryBean&lt;R, T, I&gt; {
  746
+
  747
+  protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
715 748
 
716  
-  protected RepositoryFactorySupport getRepositoryFactory(…) {
717  
-    return new MyRepositoryFactory(…);
  749
+    return new MyRepositoryFactory(entityManager);
718 750
   }
719 751
 
720  
-  private static class MyRepositoryFactory extends JpaRepositoryFactory{
  752
+  private static class MyRepositoryFactory&lt;T, I extends Serializable&gt; extends JpaRepositoryFactory {
721 753
 
722  
-    public MyRepositoryImpl getTargetRepository(…) {
723  
-      return new MyRepositoryImpl(…);
  754
+    private EntityManager entityManager;
  755
+
  756
+    public MyRepositoryFactory(EntityManager entityManager) {
  757
+      super(entityManager);
  758
+
  759
+      this.entityManager = entityManager;
  760
+    }
  761
+
  762
+    protected Object getTargetRepository(RepositoryMetadata metadata) {
  763
+
  764
+      return new MyRepositoryImpl&lt;T, I&gt;((Class&lt;T&gt;) metadata.getDomainClass(), entityManager);
724 765
     }
725 766
 
726  
-    public Class&lt;? extends RepositorySupport&gt; getRepositoryClass() {
727  
-      return MyRepositoryImpl.class;
  767
+    protected Class&lt;?&gt; getRepositoryBaseClass(RepositoryMetadata metadata) {
  768
+
  769
+      // The RepositoryMetadata can be safely ignored, it is used by the JpaRepositoryFactory
  770
+      //to check for QueryDslJpaRepository's which is out of scope.
  771
+      return MyRepository.class;
728 772
     }
729 773
   }
730 774
 }</programlisting>

0 notes on commit a0bec0f

Please sign in to comment.
Something went wrong with that request. Please try again.