Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way of handling entities inheritance in Spring Data JPA

I've three JPA entity classes A, B and C with the following hierarchy:

    A
    |
+---+---+
|       |
C       B

That is:

@Entity
@Inheritance
public abstract class A { /* ... */ }

@Entity
public class B extends A { /* ... */ }

@Entity
public class C extends A { /* ... */ }

Using Spring Data JPA, what is the best way to write repositories classes for such entities?

I know that I can write these:

public interface ARespository extends CrudRepository<A, Long> { }

public interface BRespository extends CrudRepository<B, Long> { }

public interface CRespository extends CrudRepository<C, Long> { }

but if in the class A there is a field name and I add this method in the ARepository:

public A findByName(String name);

I've to write such method also in the other two repositories, and this is a bit annoying.. Is there a better way to handle such situation?

Another point I would like to have is that ARespository should be a read-only repository (i.e. extend the Repository class) while the other two repositories should expose all the CRUD operations.

Let me know possible solutions.

like image 879
Andrea Avatar asked Dec 18 '14 09:12

Andrea


1 Answers

I used the solution also described in this post from Netgloo's blog.

The idea is to create a generic repository class like the following:

@NoRepositoryBean
public interface ABaseRepository<T extends A> 
extends CrudRepository<T, Long> {
  // All methods in this repository will be available in the ARepository,
  // in the BRepository and in the CRepository.
  // ...
}

then I can write the three repositories in this way:

@Transactional
public interface ARepository extends ABaseRepository<A> { /* ... */ }

@Transactional
public interface BRepository extends ABaseRepository<B> { /* ... */ }

@Transactional
public interface CRepository extends ABaseRepository<C> { /* ... */ }

Moreover, to obtain a read-only repository for ARepository I can define the ABaseRepository as read-only:

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

and from BRepository extend also the Spring Data JPA's CrudRepository to achieve a read/write repository:

@Transactional
public interface BRepository 
extends ABaseRepository<B>, CrudRepository<B, Long> 
{ /* ... */ }
like image 131
Andrea Avatar answered Oct 21 '22 16:10

Andrea