title: How to declare repositories based on entity interfaces?
body: <p>In a new project we would like to use Spring Data JPA and define interfaces for all JPA entities, e.g. like this:</p>
  
  <pre><code>public interface Person extends Serializable {
  
    void setId(Long id);
  
    Long getId();
  
    void setLastName(String lastName);
  
    String getLastName();
  
    void setFirstName(String firstName);
  
    String getFirstName();
  
    // ...
  
  }
  
  @Entity
  @Table(name = "t_persons")
  public class PersonEntity implements Person {
  
    private static final long serialVersionUID = 1L;
  
    @Id
    @Column
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
  
    @Column
    private String firstName;
  
    @Column
    private String lastName;
  
    // ...
  }
  </code></pre>
  
  <p>However, when declaring a Spring Data repository based on the interface like</p>
  
  <pre><code>public interface PersonRepository extends JpaRepository&lt;Person, Long&gt; {
  
  }
  </code></pre>
  
  <p>The Spring context fails to initialize with an exception whose cause is</p>
  
  <pre><code>Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'personRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not an managed type: interface com.example.Person
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1513)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
      at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
      at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
      at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
      at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)
      at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:917)
      at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:860)
      at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:775)
      at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:489)
      ... 24 more
  Caused by: java.lang.IllegalArgumentException: Not an managed type: interface com.example.Person
      at org.hibernate.ejb.metamodel.MetamodelImpl.managedType(MetamodelImpl.java:171)
      at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.&lt;init&gt;(JpaMetamodelEntityInformation.java:70)
      at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getMetadata(JpaEntityInformationSupport.java:65)
      at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:146)
      at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:84)
      at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:67)
      at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:150)
      at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:224)
      at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:210)
      at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:84)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1572)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1510)
      ... 34 more
  </code></pre>
  
  <p>I haven't found any example of Repository relying on the interface instead of the concrete type so is this possible at all? And if yes, how?</p>
  
  <p>It seems that if we cannot use the interface to declare the repositories, then it will be very difficult to use those interfaces at all since we will end up with explicit casts everywhere in our services, and even unchecked casts as soon as we deal with generics (<code>List</code>, <code>Iterable</code>…).</p>