Académique Documents
Professionnel Documents
Culture Documents
Présupposé
Département
numéro : int Une classe
nom : String
lieu : String
Une association
La base de données relationnelle manipulée ajouterEmployé(Employe) : void
1 +contient
Une classe-
par une application objet peut déjà exister au association
Agrégation
moment de la conception de l’application objet +subordonné Participation
appartient
Unidirectionnel 0..* 0..* fonctionP : String Multiplicité
Le cours qui suit suppose plutôt que la base hierarchie
Employe
matricule : int
n’existe pas 0..1
nom : String
poste : String
Projet
0..* 0..* codeP : String
dateEmbauche : date
Si ça n’est pas le cas, les adaptations à une +supérieur
salaire : double +participe
nomP : String
ajouterEmploye(Employe)
base existante sont le plus souvent pris en Rôle pour
getSuperieur()
setSuperieur(Employe)
getMatricule()
charge par les outils de mapping, au prix l’association
quelquefois d'un mapping un peu plus Héritage
complexe Commercial
commission : double
Directeur Administratif
setCommission(double)
R. Grin Mapping objet-relationnel page 3 R. Grin Mapping objet-relationnel page 4
1
Problème de base
Plan
Un objet a une structure complexe qui peut
être représentée par un graphe 1. Exemple simple de traduction d’une classe
Le plus souvent ce graphe est un arbre dont la en une table
racine correspond à l’objet et les fils 2. Identification
correspondent aux valeurs des variables 3. Traduction des associations
d’instance qui sont persistantes
4. Traduction de l’héritage
Il faut « aplatir » ce graphe pour le ranger dans
5. Récupération des objets associés à un objet
la base de données relationnelle sous une
forme tabulaire
2
Identification dans le monde Objet Identification dans le monde relationnel
Tout objet est identifiable simplement dans Seules les valeurs des colonnes peuvent servir
les langages objets (adresse de à identifier une ligne
l’emplacement mémoire), indépendamment Si 2 lignes ont les mêmes valeurs, il est
des données qu’il contient impossible de les différencier
2 objets distincts peuvent avoir exactement Toute table devrait donc comporter une clé
les mêmes valeurs pour leurs propriétés primaire pour identifier une ligne parmi toutes
les autres lignes de la même table
3
Pour éviter des duplications Objets « insérés »
En mémoire, un objet « cache » (nommé
« unité de travail » par Fowler) conserve une Le modèle objet peut avoir une granularité plus
référence vers les objets utilisés fine que le modèle relationnel
Lors d’une navigation ou d’une recherche dans Les instances de certaines classes peuvent
la base, le cache intervient : être sauvegardées dans la même table qu’une
n Si l’objet est référencé par le cache, celui-ci autre classe
le fournit Ces instances sont appelées des objets
n Sinon, l’objet est créé avec les données insérés (embedded) et ne nécessitent pas
récupérées dans la base, et ajouté au cache d’identificateur « clé primaire »
Cette fonction est remplie par les sessions de
Hibernate et les gestionnaires d’entités de JPA
R. Grin Mapping objet-relationnel page 19 R. Grin Mapping objet-relationnel page 20
Exemple
Une classe Adresse peut ne pas avoir de
correspondance sous la forme d’une table
séparée dans le modèle relationnel
Les attributs de la classe Adresse sont
Traduction des associations
insérées dans la table qui représente la
classe Client
Les objets de la classe Adresse n’ont pas
d’identification liée à la base de données
4
Association en relationnel Exemple pour
une association 1:N
Dans le monde relationnel, une association peut
être représentée par create table DEPT ( . . .)
n une ou plusieurs clés étrangères (associations create table EMPLOYE (
1:1, N:1 ou 1:N) . . .
num_dept integer references DEPT)
n une table association (associations M:N le plus
souvent)
5
Exemples de classes – solution 1 Solution 1 – variante avec Map
class Employé { class Projet {
private Collection<Projet> projets; private Map<Integer, Employé> employés;
. . . . . .
} }
class Projet { La clé peut, par exemple, représenter le
private Collection<Employé> employés; matricule d’un employé
. . .
} La variante avec map permet un accès rapide à
un des employés participant à un projet
La classe Projet reste identique à la première
variante
R. Grin Mapping objet-relationnel page 31 R. Grin Mapping objet-relationnel page 32
6
En objet
En relationnel
class Participation {
private Employé employé;
private Projet projet; PARTICIPATION(matr, codeP, fonctionP)
private String fonction; En SQL :
. . . create table participation (
} matr integer references emp,
codeP varchar(2) references projet,
fonctionP varchar(15),
primary key(matr, codeP))
7
Exemple d’association de degré > 2 Représentation par une classe
Une réservation dans une compagnie class Reservation {
aérienne peut être considérée comme une private Vol vol;
private Passager passager;
association entre les avions, les passagers et private int siège;
les numéros de siège . . .
En effet, un passager peut occuper plusieurs }
sièges (problème de santé par exemple)
8
Gestion automatique de Objet dépendant
l’ « autre bout » d’une association
Certains framework (EJB 2 par exemple), Un objet dont le cycle de vie dépend du cycle
automatisent une partie de la gestion des de vie d’un autre objet auquel il est associé,
associations appelé objet propriétaire
Aucun autre objet que le propriétaire ne doit
Ainsi, si le champ « dept » d’un employé est
modifié, l’employé est passé avoir de référence directe vers un objet
automatiquement de la collection des dépendant
employés du département d’origine dans En ce cas, la suppression de l’objet
celle du nouveau département propriétaire doit déclencher la suppression
D’autres frameworks comme Hibernate ou
des objets qui en dépendent (déclenchement
EJB 3/JPA préfèrent ne rien automatiser « en cascade »)
R. Grin Mapping objet-relationnel page 49 R. Grin Mapping objet-relationnel page 50
Exemple
Une ligne de facture ne peut exister
qu’associée à une (en-tête de) facture
Si on supprime une facture, toutes les lignes
de la facture doivent être supprimées Traduction de l’héritage
Tous les outils de mapping, comme JPA,
offrent la possibilité d’automatiser les
suppressions en cascade d’objets
dépendants
Exemple Exemple
Classe
abstraite
Pour fixer les idées, et ;-) pour reprendre des n Sportifs qui peuvent
dessins du très bon livre de Martin Fowler être des footballeurs
cité dans la bibliographie, on travaillera sur ou des joueurs de
l’exemple suivant tiré du monde anglophone : cricket
n des sportifs qui peuvent être des
footballeurs ou des joueurs de crickets
n parmi les joueurs de crickets, les joueurs
qui lancent la balle s’appellent les bowlers n Les joueurs de
cricket qui lancent la
Pour en savoir plus sur le cricket :
balle : les bowlers
http://fr.wikipedia.org/wiki/Cricket
9
Plusieurs méthodes de traduction Accessibilité des variables (1)
Représenter toutes les classes d’une Cette remarque est valable quelle que soit la
arborescence d’héritage par une seule table méthode de traduction de l’héritage et pour
relationnelle d’autre partie de ce cours
Représenter chaque classe instanciable Les variables d’instance ne sont pas le plus
(concrète) par une table souvent accessibles de l’extérieur de la
Représenter chaque classe, même les classes
classe
abstraites, par une table
Pour différencier
les types de joueurs
10
Inconvénients Une table par classe
Colonne
optionnelle
11
Inconvénient Une table par classe concrète
12
Solution Inconvénients (2)
Pas possible d’assurer simplement l’unicité
On devra lancer plusieurs selects (un pour
des identificateurs pour tous les sportifs (ils
chaque sous-classe concrète) et utiliser une
sont répartis sur plusieurs tables distinctes)
union de ces selects
Le select sera donc plus complexe et sans
doute moins performant
Héritage multiple
13
2 stratégies pour les associations Une situation
Lorsqu’un objet est créé à partir des données Recherche dans la base de données d’une
récupérées dans la base de données, 2 facture qui vérifie un certain critère
stratégies vis-à-vis des objets associés à cet Un objet de la classe Facture qui correspond
objet : à cette facture est créé
n récupération immédiate et création des Est-ce que les objets LigneFacture associés
objets associés à cette facture doivent aussi être créés ?
n les objets associés ne sont pas créés tout Et si la réponse est positive, faut-il créer aussi
de suite, mais seulement lorsque les objets Produit correspondants à chaque
l’application en a vraiment besoin ligne de facture ?
Et si la réponse est positive, …
R. Grin Mapping objet-relationnel page 79 R. Grin Mapping objet-relationnel page 80
Quand un objet est créé à partir des données Le code recherche la facture de numéro 456
enregistrées dans la BD, les objets associés Un objet f de la classe Facture est créé
ne sont pas immédiatement créés Les objets correspondants aux lignes de la
Ils sont remplacés par des objets « proxy » qui facture f sont remplacés par des objets d’une
ne contiennent que l’information nécessaire classe « proxy »
(clé primaire) pour retrouver les « vrais » Ces objets « proxy » ne contiennent que la
objets associés clé primaire des lignes de la facture dans la
Les « vrais » objets ne seront créés par la table LIGNE_FACTURE
suite que si c’est vraiment indispensable
14
Exemple (2) Problème des « N + 1 selects »
Si le programme contient ensuite le code Choisir une bonne stratégie pour récupérer
f.getLigne(i).getQuantite() les données n’est pas facile
L’objet LigneFacture correspondant à la En effet, en voulant éviter de récupérer trop
ième ligne de facture est créé en allant de données on peut tomber sur le problème
chercher les informations sur la ligne dans la des « N + 1 selects »
base de données
Le message « getQuantite() » lui est
envoyé
15
Code avec JPA Code avec Hibernate
List results = session.createCriteria(Item.class)
String texteQuery = .add( Expression.eq("item.seller", user) )
.setFetchMode("bids", FetchMode.EAGER).list();
"select f from Facture f "
// évite duplication de résultats (due au outer join)
+ " join fetch f.lignes " Iterator items = new HashSet(results).iterator();
+ " where f.date > '1/1/06'"; List maxAmounts = new ArrayList();
Query query = em.createQuery(texteQuery); while (items.hasNext()) {
List<Facture> liste = Item item = (Item) items.next();
(List<Facture>)query.getResultList(); BigDecimal max = new BigDecimal("0");
System.out.println(liste.get(0).getLigne(0)); Iterator b = item.getBids().iterator();
while (b.hasNext()) {
Bid bid = (Bid) b.next();
Ne générera aucune if ( bid.getAmount().compareTo(max) == 1 )
max = bid.getAmount();
requête SQL }
maxAmounts.add(new MaxAmount(item.getId(), max));
}
R. Grin Mapping objet-relationnel page 91 R. Grin Mapping objet-relationnel page 92
16