title: How to have multiple base classes for Spring Data JPA repositories?
body: <p>I develop an application to store different time series, e.g. temperature, pressure, etc. So I have a base class for all these measurements: </p>
  
  <pre><code>@MappedSuperclass
  public abstract class Entity {
  
      @Id
      @Column(name = "f_id")
      private UUID id = UUID.randomUUID();
  
      @Column(name = "f_location_id")
      private UUID locationId;
  
      @Column(name = "f_time")
      private long time;
  
      // getters and setters  
  }
  </code></pre>
  
  <p>I need a common repository method to get one measurement, which is prevous to passed time, like:</p>
  
  <pre><code>public T getPrevious(T entity) {
     "SELECT e FROM " + entity.getClass().getSimpleName() + " e WHERE e.time &lt;= :time "
     // only query example here to get you an idea.
  }
  </code></pre>
  
  <p>I followed Spring docs: <a href="https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-behaviour-for-all-repositories" rel="nofollow noreferrer">https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-behaviour-for-all-repositories</a></p>
  
  <p>However, that section tells us how to make <strong>all</strong> repositories to have that method, but I don't need <strong>all</strong> (I defenityle don't want my LocationRepository to have that method). I don't want to implement that method for each measurement entity either.</p>
  
  <p>What should I do?</p>
  
  <h2>Answer</h2>
  
  <p>Accepted answer is correct, but I want to publish all my code as it shows how to autowire <code>EntityManager</code> and how to get needed repository by entity class in runtime.</p>
  
  <pre><code>public interface TemperatureRepository extends TimeSeriesCrudRepository&lt;Temperature&gt; {}
  
  public class TemperatureRepositoryImpl extends TimeSeriesRepositoryImpl&lt;Temperature&gt; {
      public TemperatureRepositoryImpl(EntityManager entityManager) {
          super(entityManager);
      }
  }
  
  // this interface is needed to use any TimeSeries repository in common way
  @NoRepositoryBean // annotation important
  public interface TimeSeriesCrudRepository&lt;T extends TimeSeriesEntity&gt; extends TimeSeriesRepository&lt;T&gt;, CrudRepository&lt;T, UUID&gt; {}
  
  public interface TimeSeriesRepository&lt;T extends TimeSeriesEntity&gt; {
      void getPrevious(T entity);
  }
  
  public class TimeSeriesRepositoryImpl&lt;T extends TimeSeriesEntity&gt;  implements TimeSeriesRepository&lt;T&gt; {
  
      private final EntityManager entityManager;
  
      public TimeSeriesRepositoryImpl(EntityManager entityManager) {
          this.entityManager = entityManager;
      }
  
      public void getPrevious(T entity) {
          // impl
      }
  }
  
  @Service
  public class RepositoriesService {
  
      private Repositories repositories = null;
  
      @Autowired
      public RepositoriesService(WebApplicationContext appContext) {
          repositories = new Repositories(appContext);
      }
  
      // this explains why we need TimeSeriesCrudRepository - to return generic interface with both common CRUD and custom meth
      &lt;T extends TimeSeriesEntity&gt; TimeSeriesCrudRepository&lt;T&gt; getRepository(T entity) {
          //noinspection unchecked
          return (TimeSeriesCrudRepository&lt;T&gt;) repositories.getRepositoryFor(entity.getClass());
      }
  
  }
  </code></pre>