web-dev-qa-db-fra.com

Meilleur moyen de gérer l'héritage d'entités dans Spring Data JPA

J'ai trois entité JPA classes A, B et C avec la hiérarchie suivante:

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

C'est:

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

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

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

En utilisant Spring Data JPA, quelle est la meilleure façon d'écrire référentiels des classes pour de telles entités?

Je sais que je peux les écrire:

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

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

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

mais si dans la classe A il y a un champ name et j'ajoute cette méthode dans le ARepository:

public A findByName(String name);

Je dois écrire une telle méthode également dans les deux autres dépôts, et c'est un peu ennuyeux. Y a-t-il une meilleure façon de gérer une telle situation?

Un autre point que j'aimerais avoir est que ARespository devrait être un référentiel en lecture seule (c'est-à-dire étendre la classe Repository) tandis que les deux autres référentiels devraient exposer toutes les opérations CRUD.

Faites-moi savoir les solutions possibles.

42
Andrea

J'ai utilisé la solution également décrite dans cet article du blog de Netgloo.

L'idée est de créer une classe de référentiel générique comme suit:

@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.
  // ...
}

alors je peux écrire les trois dépôts de cette façon:

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

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

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

De plus, pour obtenir un référentiel en lecture seule pour ARepository je peux définir le ABaseRepository en lecture seule:

@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);
}

et à partir de BRepository étendre également le CrudRepository de Spring Data JPA pour obtenir un référentiel en lecture/écriture:

@Transactional
public interface BRepository 
extends ABaseRepository<B>, CrudRepository<B, Long> 
{ /* ... */ }
53
Andrea