Handling entities inheritance with Spring Data JPA

Suppose to have three JPA entities, say User, Person and Company, where the last two extends (inherits by) the first one:

  |           |
Person     Company

that is:

public abstract class User { 
  private long id;

  private String email;

  // ...

public class Person extends User { /* ... */ }

public class Company extends User { /* ... */ }

We want to write three Repository classes (aka DAO), one for each entity, following the hierarchy structure so all repository’s methods referring the base class User (for example a method findByEmail) are available on all repositories but written only once.

So, we start writing a generic user repository class:

public interface UserBaseRepository<T extends User> 
extends CrudRepository<T, Long> {

  public T findByEmail(String email);

All methods in this repository will be available in the UserRepository, in the PersonRepository and in the CompanyRepository.

Then we define repositories for the three entities:

public interface UserRepository extends UserBaseRepository<User> { /* ... */ }

public interface PersonRepository extends UserBaseRepository<Person> { /* ... */ }

public interface CompanyRepository extends UserBaseRepository<Company> { /* ... */ }

That’s all!

Some Tips

Referring the right entity type in the base repository

In the base repository you can referring the actual entity type inside a custom query (@Query annotation) using the #{#entityName} SpEL variable, for example:

public interface UserBaseRepository 
extends CrudRepository<T, Long> {

  @Query("select u from #{#entityName} as u where u.email = ?1 ")
  T findByEmail(String email);


The value of #{#entityName} will be the entity type T.

Read-only repository for User class

To obtain a read-only repository for the User class we can define the UserBaseRepository as read-only:

public interface UserBaseRepository<T> 
extends Repository<T, Long> {
  T findOne(Long id);
  Iterable<T> findAll();
  Iterable<T> findAll(Sort sort);
  Page<T> findAll(Pageable pageable);

and from PersonRepository (and CompanyRepository) extend also the Spring Data JPA’s CrudRepository to achieve a read/write repository:

public interface PersonRepository 
extends UserBaseRepository<B>, CrudRepository<B, Long> 
{ /* ... */ }

Try yourself

Get a working example using the code described above from our GitHub repository here:



  • mrts

    Thanks for sharing!

  • Augusto Santos

    Thanks, it’s a perfect tutorial. I have a question. Can I replace CrudRepository by JpaRepository in the UserBaseRepository class? What’s the difference between them?


Category BootstrapCategory CoffeescriptCategory DrupalCategory GravCategory HTMLCategory JavascriptCategory JoomlaCategory jQueryCategory LaravelCategory MagentoCategory PHPCategory SharePointCategory SpringCategory ThymeleafCategory WordPressCategory Workflow


Developed and designed by Netgloo
© 2017 Netgloo