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.
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>
{ /* ... */ }