0% ont trouvé ce document utile (0 vote)
29 vues32 pages

Java Entreprise Edition: Pr. Aimad QAZDAR

Transféré par

mehdi7jbali
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
29 vues32 pages

Java Entreprise Edition: Pr. Aimad QAZDAR

Transféré par

mehdi7jbali
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Département Génie Informatique

Java Entreprise Edition


Pr. Aimad QAZDAR
[email protected]

28 octobre 2024
JPA - Mapping des
Associations
Les annotations ORM
● Un des fondements du modèle de données relationnelles repose sur les relations qui
peuvent intervenir entre les tables.
● Les relations utilisables dans le monde relationnel et le monde objet sont cependant
différentes:
− Les relations du monde objets :
• Elles sont réalisées via des références entre objets
• Elles peuvent mettre en œuvre l'héritage et le polymorphisme
− Les relations du monde relationnel :
• Elles sont gérées par des clés étrangères et des jointures entre tables
● Hibernate supporte plusieurs types de relations :
− relation de type 1 - 1 (one-to-one)
− relation de type 1 - n (one-to-many)
− relation de type n - 1 (many-to-one)
− relation de type n - n (many-to-many)

184
Direction d’une associations
● Les associations permettent de manifester les liens entre les classes du modèle
de persistance.
● Une association possède deux rôles, un à chacune de ses extrémités.
● La cardinalité d’une association dépend de la cardinalité de ces deux rôles.

185
Navigabilité
● Capacité d’une instance de C1 (resp. C2) à accéder aux instances de C2 (resp. C1)
● Bidirectional (Par défaut) : Navigabilité dans les deux sens, les objets peuvent traverser
les deux côtés de la relation:
− C1 a un attribut de type C2 et C2 a un attribut de type C1
● Unidirectional : Spécification de la navigabilité, Orientation de la navigabilité, les objets
peuvent uniquement traverser d'un côté de la relation, par exemple:
− C1 a un attribut du type de C2, mais pas l’inverse

186
Mapping des associations
Bidirectional, exemple:
● Compte et Transaction sont propriétaires de l’association
− Etant donné un objet Compte, il peut obtenir ses objets Transaction.
− Etant donné un objet Transaction, il peut obtenir son propre objet Compte.

187
Mapping des associations
Unidirectional, exemple:
● Compte : propriétaire de l’association
− Etant donné un objet Compte, il peut obtenir ses objets Transaction.
− Etant donné un objet Transaction, il ne peut pas obtenir son propre objet Compte.

● Transaction: propriétaire de l’association


− Etant donné un objet Transaction, il peut obtenir son objet Compte.
− Etant donné un objet Compte, il ne peut pas obtenir ses propres objets Transaction

188
Annotations

Classe 1 Classe 2
@annotation multi2 multi1 @annotation
Classe2 maClasse2 Classe1 maClasse1

Classe 1 Classe 2
@ maClasse 2 multi1 multi2 @ maClasse 1
One To One 0..1 0..1 One To One
One To One | Not Null 1..1 1..1 One To One | Not Null
Many To One 0..1 0..* One To Many
Many To One | Not Null 1..1 1..* One To Many | Not Null
One To Many 0..* 0..1 Many To One
One To Many | Not Null 1..* 1..1 Many To One | Not Null
Many To Many 0..* 0..* Many To Many
Many To Many | Not Null 1..* 1..* Many To Many | Not Null
189
Direction d’une associations
● La réduction de la portée de l'association est souvent réalisée en phase d'implémentation.
● C’est le développeur qu’est responsable de la gestion de la navigabilité des objets, c’est
dire les deux bouts de l’association.
● Un des bouts est le propriétaire de l'association (Master-Slave):
− Pour les associations autres que M-N, ce bout correspond à la table qui contient la clé
étrangère qui traduit l’association.
− Pour les associations M-N, le développeur choisit le bout propriétaire (de manière arbitraire).
− L’autre bout (non propriétaire) est qualifié par l’attribut mappedBy qui donne le nom de
l’association correspondante dans le bout propriétaire:
• @annotation( mappedBy= "ObjetAutreBout").

190
Direction d’une associations

Compte Transaction
@ManyToOne
@OneToMeny(mappedBy= "compte" ) 0..1 0..* @JoinColumn(name="code_cpt")
private Set<Transaction> transactions;
private Compte compte;

Compte Transaction
@OneToMeny
@JoinColumn(name="code_cpt")
0..1 0..*
private Set<Transaction> transactions;

Compte Transaction
@ManyToOne
0..1 0..* @JoinColumn(name="code_cpt")
private Compte compte;

191
Direction d’une associations

Voiture
Agent
0..1 0..1
@OneToOne
@OneToOne(mappedBy= "agent" )
@JoinColumn(name="Num_Ag")
private Voiture voiture;
private Agent agent;

Agent Voiture
0..1 0..1 @OneToOne
@JoinColumn(name="Num_Ag")
private Agent agent;

193
Récupération d'associations
● Vous avez la possibilité de récupérer les entités associées:
− soit immédiatement ("eager"),
− soit à la demande ("lazy").
● Le paramètre fetch peut être positionné à FetchType.LAZY ou à FetchType.EAGER
● FetchType.LAZY : indique que la relation doit être chargée à la demande ;
● FetchType.EAGER : indique que la relation doit être chargée en même temps que l'entité
qui la porte.
@Entity @Entity
public class Agence { public class Agence {
@Id @Id
private String code; private String code;
private String libelle; private String libelle;
@ManyToMany(fetch=FetchType.LAZY) @ManyToMany(fetch=FetchType.EAGER)
private Set<Client> clients = new private Set<Client> clients = new
HashSet<>(); HashSet<>();
… …
} }
194
Les composants (component)
● Une entité existe par elle-même indépendamment de toute autre entité, et peut être
rendue persistante par insertion dans la base de données, avec un identifiant propre.
● Un composant est un objet sans identifiant, qui ne peut être persistant que par
rattachement à une entité.
● La notion de composant résulte du constat qu’une ligne dans une base de données
peut parfois être décomposée en plusieurs sous-ensemble dotés chacun d’une logique
autonome.
● Cette décomposition mène à une granularité fine de la représentation objet, dans laquelle
on associe plusieurs objets à une ligne de la table.
● @Embedded nous indique que ce composant est embarqué.
● @Embeddable nous indique que cette classe sera utilisée comme composant.

195
Les composants (component)
@Embeddable
Agence
1..1 0..1 Adresse
@Embedded
private Adresse adresse;

@Entity @Embeddable
public class Agence { public class Adresse {
@Id private String ville;
private String code;
private String libelle;
private String pays;
private int codePostal;
@Embedded
private Adresse adresse; public Adresse() {}

public Agence() { } public Adresse(String ville,


public Agence(String code, String libelle, String pays, int codePostal) {
Adresse adresse) { super();
super();
this.code = code;
this.ville = ville;
this.libelle = libelle; this.pays = pays;
this.adresse = adresse; this.codePostal = codePostal;
} }
//getters et setters // getters et setters
} }

196
Clé composée
● Les clefs primaires composées utilisent une classe embarquée comme représentation de
la clef primaire,
● 3 possibilités:
− @Id et @Embeddable: un seul attribut Id dans la classe entité
− @IdClass: correspond à plusieurs attributs Id dans la classe entité
− @EmbeddedId un seul attribut Id dans la classe entité
● Dans les trois cas, la clé doit être représentée par une classe Java:
− les attributs correspondent aux composants de la clé
− la classe doit être publique
− la classe doit avoir un constructeur sans paramètre
− la classe doit être sérialisable.
− La classe doit redéfinir equals() et hashcode().

197
Clé composée
Une Clé composée : @IdClass( ClassePK.class )

@Entity public class CommandePK implements Serializable {


@IdClass(CommandePK.class)
public class Commande { private int num;
private int code;
@Id
private int num;
@Id public CommandePK() {}
private int code; // les gettrs et les setters
public int hashCode() {
private int quantite; …
private double prix; }
public Commande() {}
public boolean equals(Object obj) {
// les getters et les setters …
}
} }

198
Clé composée
Une Clé composée : @Id et @Embeddable

@Embeddable
@Entity public class CommandePK implements Serializable {
public class Commande {
private int num;
@Id private int code;
private CommandePK pk;
public CommandePK() {}
private int quantite; // les gettrs et les setters
private double prix; public int hashCode() {

public Commande() {} }
// les getters et les setters public boolean equals(Object obj) {

} }
}

199
Clé composée
Une Clé composée : @EmbeddedId

@Entity public class CommandePK implements Serializable {


public class Commande {
private int num;
@EmbeddedId private int code;
private CommandePK pk;
public CommandePK() {}
private int quantite; // les gettrs et les setters
private double prix; public int hashCode() {

public Commande() {} }
// les getters et les setters public boolean equals(Object obj) {

} }
}

200
Exemple : Gestion d’école

coordonnees
Id_Crd (auto) etudiant
avoir noter matiere
Email_Crd Apogee_Etd
(1,1) (1,1) (1,*) (0,*) Code_Mat
Tel_Crd Nom_Etd
note Libelle_Mat
Adresse_Crd Prenom_Etd
Ville_Crd
(1,*)

enseigant
departement affecter enseigner
Code_Ens (auto)
Code_Dep (1,*) (1,1) (1,*)
Nom_Ens
Libelle_Dep
Prenom_Ens

201
Association un-à-plusieurs
● Associations 1-N et N-1 : les associations “un à plusieurs” et “plusieurs à un”
● Annotations @OneToMany et @ManyToOne
● Représentée par une clé étrangère dans la table qui correspond au côté propriétaire
(obligatoirement le côté Many)
● Exemple : Enseignant-Département, cette association peut se représenter de 3 manières :
− dans un Enseignant, on place un lien vers le Département (unidirectionnel); @ManyToOne
− dans un Département, on place des liens vers les Enseignants qu’il lui sont affectés
(unidirectionnel); @OneToMany
− Ou bien, on représente les liens des deux côtés (bidirectionnel).mappedBy
● Généralement, dans une base relationnelle, une association représentée par une clé

202
@ManyToOne
@Entity
● Association Unidirectionnelle. @Table(name="enseignant")
public class Enseignant {
➔ Enseignant est le maître de l’association @Id
● Dans la classe Enseignant, @ManyToOne @GeneratedValue(strategy=GenerationType.
IDENTITY)
nous indique qu’un objet lié nommé
@Column(name="Code_Ens")
departement (clé étrangère) est de la classe private int code;
Departement. @Column(name="Nom_Ens", length=30)
private String nom;
● L’annotation @JoinColumn indique la clé @Column(name="Prenom_Ens", length=30)
étrangère dans la table Enseignant qui permet private String prenom;
de rechercher le Département concerné @ManyToOne
@JoinColumn(name="Code_Dep")
private Departement departement;
public Enseignant() {}
public Departement getDepartement() {
return departement;}
public void setDepartement(Departement
departement) {this.departement =
departement;}
// les getters et les setters
}
203
@ManyToOne

public class MappingTest {


public static void main(String[] args) {
EntityManagerFactory emf
=Persistence.createEntityManagerFactory("myDB");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Departement dep=new Departement("GINFO","Génie
Département
Informatique");
Column Type Null Primary em.persist(dep);
Code_Dep varchar(6) No yes Enseignant ens=new Enseignant("Aimad", "QAZDAR",dep);
Libelle_Dep varchar(50) Yes em.persist(ens);
em.getTransaction().commit();
}
Enseignant
}
Column Type Null Primary

Code_Ens int(11) No AUTO_INCREMENT

Nom_Ens varchar(30) Yes

Prenom_Ens varchar(30) Yes

Code_Dep varchar(6) Yes FK

204
Association plusieurs-à-plusieurs
● Quand on représente une association plusieurs-plusieurs en relationnel, l’association
devient une table dont la clé est la concaténation des clés des deux entités de
l’association.
● La valeur par défaut du nom de la table association est la concaténation des 2 tables,
séparées par _
● Annotation @ManyToMany est représentée par une table association
● Deux cas se présentent :
− l’association n’est pas porteuse d’aucun attribut.
− l’association est porteuse des attributs (traitée comme @OneToMany dans les deux côtés de
l’association).
● Dans notre exemple:
− un enseignant enseigne plusieurs matières.
− une matière est enseignée par plusieurs enseignants.

207
@ManyToMany
@Entity
● Association Unidirectionnelle.
@Table(name="matiere")
➔ Matière est le maître de public class Matiere {
l’association @Id
@Column(name="Code_Mat", length=6)
● Dans la classe Matière, private String code;
@ManyToMany nous indique que la @Column(name="Libelle_Mat", length=100)
private String libelle;
collection des objets liés nommé @ManyToMany
enseignants, est de la classe private Set<Enseignant> enseignants=new HashSet<>();
Enseignant. public Set<Enseignant> getEnseignants() {
return enseignants;
}
public void setEnseignants(Set<Enseignant>
enseignants) {
this.enseignants = enseignants;
}
public void ajouterEnseigant(Enseignant ens){
this.enseignants.add(ens);}

//les getters et les setters


}
208
@ManyToMany
public class MappingTest2 {
public static void main(String[] args) {
EntityManagerFactory emf
=Persistence.createEntityManagerFactory("myDB");
Enseignant
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Column Type Null Primary
Departement dep=new Departement("GINFO","Génie
Code_Ens int(11) No PK
Informatique");
Nom_Ens varchar(30) Yes NULL
Enseignant ens1=new Enseignant("Aimad","QAZDAR",dep);
Prenom_Ens varchar(30) Yes NULL
em.persist(ens1);
matiere_enseignant
Matiere mat1=new Matiere("JEE","Java Entreprise
Column Type Null Primary
Edition");
mat1.ajouterEnseigant(ens1);
Matiere_Code_Mat varchar(6) No FK
Matiere mat2=new Matiere("SOA","Architecture Orientée
enseignants_Code_Ens int(11) No FK
Services");
Matière mat2.ajouterEnseigant(ens1);
Column Type Null Primary em.persist(mat1);
Code_Mat varchar(6) No PK em.persist(mat2);
Libelle_Mat varchar(100) Yes NULL em.getTransaction().commit();
}
}

209
Clé composée
● Clé composé :
− Table existante avec clé multi-attributs
− Association N-M (Many-to-Many)
● 3 possibilités:
− @Id et @Embeddable: un seul attribut Id dans la classe entité
− @IdClass: correspond à plusieurs attributs Id dans la classe
entité
− @EmbeddedId un seul attribut Id dans la classe entité
● Dans les trois cas, la clé doit être représentée par une classe
Java:
− les attributs correspondent aux composants de la clé
− la classe doit être publique
− la classe doit avoir un constructeur sans paramètre
− la classe doit être sérializable et redéfinir equals et hashcode.

210
Clé composite : @Id et @Embeddable
● Correspond au cas où la classe entité @Embeddable
comprend un seul attribut annoté @Id public class Noter_PK implements
Serializable{
● La classe clé primaire est annotée par private static final long serialVersionUID
@Embeddable = 1L;
@Entity @Column(name="Code_Mat")
@Table(name="noter") private String codeMat;
public class Noter { @Column(name="Apogee_Etd")
@Id private int apogeeEtd;
private Noter_PK pk; public Noter_PK(String codeMat, int
private double note; apogeeEtd) {this.codeMat = codeMat;
public Noter() {super();} this.apogeeEtd = apogeeEtd;}
public Noter(int apogee, String matiere, public Noter_PK() {super();}
double note) {this.pk = new public String getCodeMat() {
Noter_PK(matiere,apogee); return codeMat;}
this.note = note;} public void setCodeMat(String codeMat) {
public Noter_PK getPk() {return pk;} this.codeMat = codeMat;}
public void setPk(Noter_PK pk) {this.pk = public int getApogeeEtd() {
pk;} return apogeeEtd;}
public double getNote() {return note;} public void setApogeeEtd(int apogeeEtd) {
public void setNote(double note) {this.note = this.apogeeEtd = apogeeEtd;}
note;} }
211
Clé composite : @Id et @Embeddable

public class MappingTest3 {


public static void main(String[] args) {
// TODO Auto-generated method stub
EntityManagerFactory emf
=Persistence.createEntityManagerFactory("myDB");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Noter note1=new Noter(2300, "JEE", 16.75);
em.persist(note1);
Noter note2=new Noter(5376, "JEE", 18.00);
em.persist(note2);
em.getTransaction().commit();
}
}

212
Association un-à-un
● Annotation @OneToOne représente l’association 1-1
● Dans l'exemple ci-dessous, chaque « étudiant » ne peut avoir qu'une seule
«Coordonnées» et une « coordonnées » ne peut appartenir que à un seul « étudiant ».

● Cette relation peut se traduire de plusieurs manières dans la base de données :


− Une seule table qui contient les données de l’étudiant et ses coordonnés.
− Deux tables, une pour les étudiants et une pour les coordonnés avec une clé primaire
partagée
− Deux tables, une pour les étudiants et une pour les coordonnés avec une seule clé étrangère
● Il y a plusieurs façons de traiter ce cas avec une ou deux tables dans la base de données:
− Deux tables et une relation One-to-One
− Une seule table avec un Component

214
@OneToOne
● L’annotation @Embedded & @Embeddable
@Entity
● Une seul table avec un Component
@Table(name="etudiant")
● Dans la classe Etudiant, @Embedded nous public class Etudiant {
indique que ce composant est embarqué @Id
(@Embeddable). @Column(name="Apogee_Etd")
private int apogee;
@Column(name="Nom_Etd", length=30)
private String nom;
@Column(name="Nom_Prenom", length=30)
private String prenom;

@Embedded
private Coordonnees coordonnées;

// Constructeurs
// getters et setters
}

215
@OneToOne
● L'annotation @Embeddable permet de
@Embeddable
préciser que la classe sera utilisée comme
public class Coordonnees {
un component. Un tel élément n'a pas @Column(name="adresse_Crd")
d'identifiant puisque celui utilisé sera celui private String adresse;
de l'entité englobant. @Column(name="ville_Crd")
private String ville;
@Entity @Column(name="email_Crd")
@Table(name="etudiant")
public class Etudiant {
private String email;
@Id @Column(name="tel_Crd")
@GeneratedValue(strategy=GenerationType.IDENTITY) private String tel;
@Column(name="Apogee_Etd") public Coordonnees() {}
private int apogee;
@Column(name="Nom_Etd", length=30) public Coordonnees(String adresse,
private String nom; String ville, String tel, String email)
@Column(name="Nom_Prenom", length=30) {
private String prenom;
@Embedded
this.adresse = adresse;
private Coordonnees coordonnées; this.ville = ville;
this.tel = tel;
// Constructeurs this.email = email;
// getters et setters
} }
}

216
@OneToOne

public class MappingTest4 {


public static void main(String[] args) {
EntityManagerFactory emf
=Persistence.createEntityManagerFactory("myDB");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Coordonnees crd=new Coordonnees("ENSA-agadir", "Agadir",
"0525008800",
"[email protected]");
etudiant Etudiant etd1=new Etudiant(3322,"Ahmed", "RABII",crd);
Column Type Null Default em.persist(etd1);
Apogee_Etd int(11) No
adresse_Crd varchar(255) Yes NULL em.getTransaction().commit();
email_Crd varchar(255) Yes NULL
}
tel_Crd varchar(255) Yes NULL
}
ville_Crd varchar(255) Yes NULL
Nom_Etd varchar(30) Yes NULL
Nom_Prenom varchar(30) Yes NULL

217

Vous aimerez peut-être aussi