2017-04-11 1 views
3

J'ai une classe abstraite annotée avec @MappedSuperClass. Il y a environ 15 entités qui étendent cette classe abstraite (ayant 15 tables correspondantes dans la base de données). Les 15 entités ont toutes les mêmes attributs hérités de la super classe abstraite.Spring Data JPA inheritance dans des référentiels

J'ai créé un référentiel comme ci-dessous pour la classe abstraite:

@NoRepositoryBean 
public interface AbstractRepository <T extends AbstractClass, E extends Serializable> 
            extends PagingAndSortingRepository<T, Serializable> { 
    .....some methods here 
} 

Les 15 entités/tables stockent des données (données relatives à 15 équipements distincts). En fonction de l'équipement sélectionné, les données de cette table doivent être récupérées. Devrai-je créer 15 dépôts distincts pour les 15 entités concrètes ou existe-t-il un moyen d'obtenir l'entité spécifique pour l'équipement sélectionné en utilisant uniquement le référentiel abstrait? Si des référentiels doivent être créés pour chaque entité concrète, comment obtenir le bon référentiel pour l'appel d'équipement spécifique? (stocker le nom de table et la classe de référentiel dans une carte créée au démarrage de l'application peut-être?)

Répondre

1

Vous devrez créer un référentiel pour chaque classe. Cependant, vous pouvez garder vos méthodes dans l'abstrait. Vous devrez fournir @Query sur chacune des méthodes et utiliser SpeL (Spring Expression Language) pour ajouter le type aux requêtes.

@NoRepositoryBean 
public interface AbstractRepository 
     extends CrudRepository<T extends AbstractEquipment,Long>{ 

@Query("select e from #{#entityName} as e from equipment where e.name = equipmentName") 
T findEquipmentByName(String equipmentName); 

} 

Prolongez ensuite comme le

@Transactional 
public interface SpecialEquipmentRepo extends AbstractRepository<SpecialEquipment,Long>{ 

} 
+0

Merci @Joseph pour la clarification. Puisque des référentiels pour chaque équipement devront être créés, quelle est la meilleure façon d'obtenir l'instance de référentiel pour un équipement spécifique?Une façon est de lier automatiquement tous les 15 dépôts et un boîtier de commutation pour utiliser l'instance référentiel approprié en fonction de l'équipement passé (quelque chose comme une usine pour retourner le dépôt correct) –

+0

j'éviter d'utiliser un commutateur car cela devrait être maintenu , vous pouvez '@ Autowire' une carte où la clé est le type, et la valeur est le type de référentiel. –

2

suivant Idéalement, la configuration suivante devrait fonctionner:

classes d'entité

@Entity 
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 
public abstract class Equipment { ... } 

@Entity 
public class Crane extends Equipment {} 

@Entity 
public class Excavator extends Equipment {} 

interface Repository

public interface EquipmentRepository<T extends Equipment> extends CrudRepository<T> {} 

consommation Repository

@Service 
public class SomeService { 
    @Autowired 
    private EquipmentRepository<Crane> craneRepository; 

    @Autowired 
    private EquipmentRepository<Excavator> excavatorRepository; 
} 

J'ai mis en place un exemple de projet on Github pour démontrer cela en action. Exécuter des tests Maven comme l'un des suivants montrera des tests de passage pour démontrer que l'installation fonctionne comme prévu.

mvn test -Dspring.profiles.active="default,eclipselink" 

mvn test -Dspring.profiles.active="default,openjpa" 

Cela dit, cette configuration ne fonctionne pas avec Hibernate, qui est ce que je soupçonne que vous utilisez. Hibernate ne prend pas en charge les colonnes d'identificateur auto-incrémenté avec l'héritage TABLE_PER_CLASS. Par conséquent, tenter d'exécuter l'installation ci-dessus avec Hibernate lèvera une exception. Cela peut être vérifié en exécutant ce qui suit sur l'exemple lié ci-dessus.

mvn test -Dspring.profiles.active="default,hibernate"