JPA ASSOCIATIONS : Il existe plusieurs type d’associations entre entités :
• One to One (1:1) -Unidirectionnelle / Bidirectionnelle
• One to Many (1:N) -Unidirectionnelle / Bidirectionnelle
• Many to One (N:1) -Unidirectionnelle / Bidirectionnelle
• Many to Many (N:M) -Unidirectionnelle / Bidirectionnelle
– TP : Mise en oeuvre des différentes associations


JPA ASSOCIATIONS :
• One To One entre T_FORMATION et T_FORMATION_DETAIL (Clé étrangère formationdetail_formation_id).
• La Formation a un ensemble de détails (une seule ligne dans la table T_FORMATION_DETAIL). Le détail d’une formation est liée à une seule Formation.
• Many To Many : T_FORMATION et T_TP (Table d’association T_FORMATION_TP).
• La Formation a plusieurs TPs(TP1, TP2, …). Un même TP peut être lié à plusieurs formations (Maven, JPA, EJB, JSF).
• One To Many : T_TP et T_TP_CORRECTION (Table d’association T_TP_TC).
• Le TP peut avoir plusieurs Corrections (Avec Maven / Sans Maven, Avec Hibernate / Avec EclipseLink, …). Une Correction n’est liée qu’à un TP.
• Si l’association Many To One était utilisée entre T_TP et T_TP_CORRECTION, à la place de One To Many, quel changement dans le diagramme ci-dessus ?
JPA ASSOCIATIONS : Place à la pratique, pour créer vous-même toutes ces associations :
• One To One : La Formation a un ensemble de détails (une seule ligne dans la table T_FORMATION_DETAIL). Le détail d’une formation est liée à une seule Formation.
• Unidirectionnelle : La Formation connait le détail (contient un attribut de type Formation_Detail), alors que le détail n’a aucune information sur la Formation auquel il est associé.

1.1. One To One Unidirectionnelle
@Entity
@Table(name= "T_FORMATION")
public class Formation implements Serializable{
private static final long serialVersionUID= 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="FORMATION_ID")
private Long id; // Identifiant formation (Clé primaire)
@Column(name="FORMATION_THEME")
private String theme; // Thèmeformation
@OneToOne
private FormationDetail formationDetail;
// Constructeurs, getters, setters
@Entity
@Table(name="T_FORMATION_DETAIL")
public class FormationDetail implements Serializable{
private static final long serialVersionUID= 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="FD_ID")
private Long fdId;
@Column(name="FD_TABLE_MATIERE")
private String fdTableMatiere;
@Column(name="FD_SUPPORT_PDF")
private String fdSupportPDF;
// Constructeurs, getters, setters
Comme résultat :

1.2. One To One Bidirectionnelle
• One To One : La Formation a un ensemble de détails (une seule ligne dans la table T_FORMATION_DETAIL). Le détail d’une formation est liée à une seule Formation.
• Bidirectionnelle : l’Entité «Formation» contient un attribut de type «Formation_Detail» et l’Entité «Formation_Detail» contient un attribut de type «Formation».
• C’est l’attribut «mappedBy» qui crée le caractère bidirectionnel de la relation et qui permet de définir les deux bouts de l’association «Parent / Child».
• Au niveau des Entités Java, c’est le fils qui contient l’attribut «mappedBy».
• En base de données, c’est le Parent qui contiendra la Clé étrangère qui pointera vers le Child.

@Entity
@Table(name= "T_FORMATION")
public class Formation implements Serializable{
private static final long serialVersionUID= 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="FORMATION_ID")
private Long id; // Identifiant formation (Clé primaire)
@Column(name="FORMATION_THEME")
private String theme; // Thèmeformation
@OneToOne
private FormationDetail formationDetail;
// Constructeurs, getters, setters
@Entity
@Table(name="T_FORMATION_DETAIL")
public class FormationDetail implements Serializable{
private static final long serialVersionUID= 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="FD_ID")
private Long fdId;
@Column(name="FD_TABLE_MATIERE")
private String fdTableMatiere;
@Column(name="FD_SUPPORT_PDF")
private String fdSupportPDF;
@OneToOne(mappedBy="formationDetail")
private Formation formation;
// Constructeurs, getters, setters
Comme resultat :

2.1. One To Many Unidirectionnelle
• One To Many : Le TP peut avoir plusieurs Corrections (Avec Maven / Sans Maven, Avec Hibernate / Avec EclipseLink, …). Une Correction n’est liée qu’à un TP.
• Unidirectionnelle TP -> Correction : Le TP connait les corrections, alors que La Correction n’a aucune information sur le TP dont elle est la Solution.

@Entity
@Table(name= "T_TP")
public class TravauxPratiques implements Serializable{
private static final long serialVersionUID= 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="TP_ID")
Long tpId;
@Column(name="TP_SUJET")
String tpSujet;
@Column(name="TP_DUREE")
Long tpDuree;
@OneToMany(cascade = CascadeType.ALL)
private Set<TpCorrection> TpCorrections;
// Constructeurs, getters, setters
@Entity
@Table(name="T_TP_CORRECTION")
public class TpCorrection implements Serializable{
private static final long serialVersionUID= 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="TC_ID")
private Long tcId;
@Column(name="TC_CORRECTION")
private String tcCorrection;
// Constructeurs, getters, setters
Comme Resultat :

2.2. One To Many Bidirectionnelle
• One To Many Bidirectionnelle = Many To One Bidirectionnelle :
• Voir Slide Many To One Bidirectionnelle dans la suite du cours
• Many To One : un TP peut avoir plusieurs Corrections. Chaque Correction est liée à un unique TP.
• Unidirectionnelle: Chaque Correction de TP a l’information concernant le TP (attribut TravauxPratiquesdans l’Entité TP_Correction, Clé étrangère dans la table T_TP_CORRECTION), alors que le TP n’a aucune information sur ses «Corrections».

@Entity
@Table(name="T_TP_CORRECTION")
public class TpCorrection implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="TC_ID")
private Long tcId;
@Column(name="TC_CORRECTION")
@ManyToOne(cascade = CascadeType.ALL)
private String tcCorrection;
TravauxPratiquestravauxPratiques;
// Constructeurs, getters, setters
@Entity
@Table(name= "T_TP")
public class TravauxPratiques implements Serializable{
private static final long serialVersionUID= 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="TP_ID")
Long tpId;
@Column(name="TP_SUJET")
String tpSujet;
@Column(name="TP_DUREE")
Long tpDuree;
// Constructeurs, getters, setters
Comme résultat :

3.1. Many To One Unidirectionnelle
• Many To One : un TP peut avoir plusieurs Corrections. Chaque Correction est liée à un unique TP.
• Unidirectionnelle : Chaque Correction de TP a l’information concernant le TP (attribut TravauxPratiquesdans l’Entité TP_Correction, Clé étrangère dans la table T_TP_CORRECTION), alors que le TP n’a aucune information sur ses «Corrections».

@Entity
@Table(name="T_TP_CORRECTION")
public class TpCorrection implements Serializable{
private static final long serialVersionUID= 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="TC_ID")
private Long tcId;
@Column(name="TC_CORRECTION")
private String tcCorrection; @ManyToOne(cascade = CascadeType.ALL)
TravauxPratiques travauxPratiques;
// Constructeurs, getters, setters
@Entity
@Table(name= "T_TP")
public class TravauxPratiques implements Serializable{
private static final long serialVersionUID= 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="TP_ID")
Long tpId;
@Column(name="TP_SUJET")
String tpSujet;
@Column(name="TP_DUREE")
Long tpDuree;
// Constructeurs, getters, setters
Comme résultat :

3.2. Many To One Bidirectionnelle
• Many To One : Un TP peut avoir plusieurs Correction. Une Correction est liée à un seul TP.
• Bidirectionnelle: Le TP connait ses Corrections. Chaque Correction connait elle aussi le TP dont elle est la Solution.

L’attribut mappedBy est défini pour l’annotation @OneToMany, mais pas pour l’annotation @ManyToOne, car elle est toujours liée au «Child».
@Entity
@Table(name="T_TP_CORRECTION")
public class TpCorrection implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="TC_ID")
private Long tcId;
@Column(name="TC_CORRECTION")
private String tcCorrection;
@ManyToOne
TravauxPratiques travauxPratiques;
// Constructeurs, getters, setters
@Entity
@Table(name= "T_TP")
public class TravauxPratiques implements Serializable{
private static final long serialVersionUID= 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="TP_ID")
Long tpId;
@Column(name="TP_SUJET")
String tpSujet;
@Column(name="TP_DUREE")
Long tpDuree;
@OneToMany(cascade = CascadeType.ALL, mappedBy="travauxPratiques")
privateSet<TpCorrection> TpCorrections;
// Constructeurs, getters, setters
Comme résultat :

4.1. Many To Many Unidirectionnelle
• Many To Many : La Formation a plusieurs TPs(TP1, TP2, …). Un même TP peut être lié à plusieurs formations (Maven, JPA, EJB, JSF).
• Unidirectionnelle: La formation a plusieurs TPset les connait. Mais, le TP n’a aucune information sur «les Formations» auxquelles il est associé.

@Entity
@Table(name= "T_FORMATION")
public class Formation implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="FORMATION_ID")
private Long id; // Identifiant formation (Clé primaire)
@Column(name="FORMATION_THEME")
private String theme; // Thèmeformation
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="FK_FD_ID")
private FormationDetail formationDetail;
@ManyToMany(cascade = CascadeType.ALL)
private Set<TravauxPratiques> formationTps;
// Constructeurs, getters, setters
@Entity
@Table(name= "T_TP")
public class TravauxPratiques implements Serializable{
private static final long serialVersionUID= 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="TP_ID")
Long tpId;
@Column(name="TP_SUJET")
String tpSujet;
@Column(name="TP_DUREE")
Long tpDuree;
// Constructeurs, getters, setters
Comme resultat :

4.2. Many To Many Bidirectionnelle
• Many To Many: La Formation a plusieurs TPs (TP1, TP2, …). Un même TP peut être lié à plusieurs formations (Maven, JPA, EJB, JSF).
• Bidirectionnelle: La formation a plusieurs TPs et les connait. Chaque TP est associé à plusieurs Formations, et les connait aussi.

@Entity
@Table(name= "T_FORMATION")
public class Formation implements Serializable{
private static final long serialVersionUID= 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="FORMATION_ID")
private Long id; // Identifiant formation (Clé primaire)
@Column(name="FORMATION_THEME")
private String theme; // Thèmeformation
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="FK_FD_ID")
private FormationDetailformationDetail;
@ManyToMany(cascade = CascadeType.ALL)
private Set<TravauxPratiques> formationTps;
// Constructeurs, getters, setters
@Entity
@Table(name= "T_TP")
public class TravauxPratiques implements Serializable{
private static final long serialVersionUID= 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="TP_ID")
Long tpId;
@Column(name="TP_SUJET")
String tpSujet;
@Column(name="TP_DUREE")
Long tpDuree;
@ManyToMany(mappedBy="formationTps", cascade = CascadeType.ALL)
privateSet<Formation> formations;
// Constructeurs, getters, setters
Comme résultat :

! Association Many-To-Many Porteuse de Données
• Une association ManyToMany est dite porteuse de données si la classe associative comporte des données autres que sa clé primaire.
• Exemple : Une tâche est caractérisée par un projet, un chercheur et un nom.

• Définition de la Clé primaire :


Si vous avez des questions, n’hésitez pas à nous contacter via les commentaires 😉
Lire aussi : Solution for : Why hibernate does not insert into child table ?