Ressource
En OO il est naturel d’avoir des classes qui héritent les unes des autres, tandis qu’en base de données relationnelle une table ne va pas hériter d’une autre table; Problème d’Impedance mismatch
Héritage d’entité
@Entity
public class User {
@Id
private int id
private String name;
}
@Entity
public class Employee extends User {
// Pas besoin de id, elle est hérité
private int salary
}3 stratégies de mapping
- Héritage avec une table par classe
TABLE_PER_CLASS
Employee : ID | Name | Salary
User : ID | Name
- Héritage avec une seule table
SINGLE_TABLE
User : ID | Name | Salary
- Héritage avec jointure (relation 1:1 une employee depend d’un user pour existé)
JOINED- L’ID dans User et Employee seront les mêmes pour un employee
User : ID | Name
Employee : ID | Salary
Stratégie TABLE_PER_CLASS
Ressource
Pour les opérations CRUD aucun problème :
em.persist(...)suivant le type enregistrera dans la bonne tableem.find(User.class, 1)suivant la valeur du premier paramètre SELECT dans la bonne tableuser.setName(...)de même aucun problème, le type de l’objet est précisem.remove(user)on connaît également le type
Stratégie SINGLE_TABLE
Ressource
Nous allons avoir une table unique pour ces deux entités, avec l’ensemble des colonnes de User et Employee
User : ID | Name | Salary
- Si on met des instances de
Useralors on utilisera que les deux premières colonnes - Si on met des instances de
Employeealors on utilisera les trois colonnes
On rencontre déjà un premier problème, car avec JPA on peut mettre @Column(nullable = false) int salary or les user auront ce champ à NULL.
Par conséquent, en choisissant la stratégie SINGLE_TABLE on ne pourra pas utiliser nullable sur les entités qui étendent l’entité de base
em.persist(...)même table donc aucun problèmeem.find(User.class, 1)- Est-ce que le User qui a l’id 1 est réellement un User ?
- La seule façon de s’en sortir est d’ajouter une colonne technique
DTYPEqui sera complété lors de l’insertion et qui préciseraUserouEmployee
employee.setSalary(10000)aucun problème car on a le type de l’objetem.remove(employee)on sait que l’instance est une instance d’employee donc aucun problème
Stratégie JOINED
Ressource
Une entité qui étend une autre entité est en relation 1:1 avec cette entité
User : ID | Name
Employee : ID | Salary
L’ID dans User et Employee seront les mêmes pour un employee
em.persist(employee)deux requêtesINSERTnécessaires, une pour la table User et une autre pour Employeeem.find(Employee, 2)il nous faudra une jointure sur les deux tablesemployee.setSalary(10000)aucun problème avec la mise à jour car la propriété salaire est dans la classeEmployeequi elle met est associée à une table précise ⇒ un seul update en baseem.remove(employee)deux requêtesDELETEnécessaires
L’annotation @Inheritance
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class User {
}