JPA Associations

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

Digramme de Classes (sans cardinalité)
MCD PHPMYADMIN

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 ?

JPA wiki

Laisser un commentaire