16 Base de
données objet
27/02/22 © Robert Godin. Tous droits réser vés.
2
16.1 Le langage de définition de données ODL
Basé sur IDL (CORBA/OMG)
Non supporté
– association n-aire n>2
– classe associative
Types littéraux (valeurs)/objets
Exemple UML
Personne nom : String
prénom : String
setNomPrénom(n : String, p : String)
Mem bre
téléphoneRésidence : String
$ nbMaxPrêts : Integer = 5
$ duréeMaxPrêts : Integer = 7 nbRetards() : Integer
PrêtEnCours retour(date : Date) PrêtArchivé
dateRetour : Date
{dateRetour >= datePrêt}
{statut = "prêté" ssi PrêtEn Cours de l'Exemplaire est non vide}
{Le nombre de PrêtEnCours d'un Membre <= nbMaxPrêts}
Employé {UNIQUE : codeMatricule}
codeMatricule : String
catégorieEmployé : enum(bibliothécaire, commis) catégorieUtilisateur
Catégorie
{UNIQUE: code} enfant Auteur
Editeur {UNIQUE: nomEditeur}
nomEditeur : String ville : String
Livre {UNIQUE: ISBN}
ISBN : String titre : String
annéeParution : TypeDonnéesAnnée nbExemplairesDisponibles() : Integer
1 ** 1 1..*
1..* 1..*
1..*
1
1..*
1
1..*
Exemplaire {UNIQUE: idExem plaire}
idExem plaire : String dateAchat : Date
statut : enum(prêté, disponible, retiré) 1..*
1
1..*
1 Prêt datePrêt : Date
getEm prunteur() : Utilisateur getExemplaire() : Exem plaire
1
*
1
* Utilisateur
{UNIQUE :idUtilisateur}
idUtilisateur : String motPasse : String setMotPasse(m : String) nbPrêtsEnCours() : Integer
*
1 *
1
{ordonné}
{Il ne peut y avoir plus d'un PrêtEnCours pour un même Exemplaire}
{disjointe, complète}
{disjointe, complète}
{chevauchante, complète}
27/02/22 © Robert Godin. Tous droits réser vés.
4
16.1.1 Classe et interface ODL
Class Livre
( extent livres
key ISBN)
{ attribute string ISBN;
attribute string titre;
attribute integer annéeParution;
relationship set<Exemplaire> lesExemplaires inverse Exemplaire::leLivre
relationship list<Auteur> lesAuteurs inverse Auteur::lesLivres
integer nbExemplairesDisponibles();
};
Interface Personne
{ attribute string nom;
attribute string prénom;
void setNomPrénom(in string n; in string p);
};
16.1.1.1 INTERFACE ODL
Pas d ’extent (non instantiable)
Attribut/association
– équivalent lecteur/modifieur
– non hérité par interface
27/02/22 © Robert Godin. Tous droits réser vés.
6
16.1.2 Héritage d'interface (:) et de classe (extends)
Class Utilisateur : Personne ( extent utilisateurs
key idUtilisateur) { attribute string nom;
attribute string prénom;
attribute string idUtilisateur;
attribute string motPasse;
relationship set<Prêt> lesPrêts inverse Prêt::lUtilisateur void setMotPasse(in String m);
integer nbPrêtsEnCours();
};
Class Employé extends Utilisateur ( extent employés
key codeMatricule)
{ attribute string codeMatricule;
attribute enum CatEmp{bibliothécaire, commis}catégorieEmployé;
};
16.1.3 Littéral ODL
Literal_type
Atomic_literal Collection_literal Structured_literal
long long long short
unsigned long unsigned short
float double
boolean char
string
T set
T bag
T list
T array
K, T dictionary
date
time
timestamp
interval
listeAttributs struct
27/02/22 © Robert Godin. Tous droits réser vés.
8
Littéral structuré
Class Membre
( extent membre key noMembre)
{ struct typeDonnéesAdresse{
integer noCivique;
integer numéroAppartement;
string nomRue;
string nomVille;
string nomProvince;
string nomPays;
string codePostal;
};attribute integer noMembre;
attribute string nom;
attribute string prénom;
attribute adresse typeDonnéesAdresse;
};
Membre {UNIQUE : noMembre}
noMembre : Integer nom : String
prénom : String
adresse : typeDonnéesAdresse
typeDonnéesAdresse numéroCivique : Integer
numéroAppartement : Integer nomRue : String
nomVille : String nomProvince : String nomPays : String codePostal : String
<<datatype>>
16.1.4 Collections ODL
Class Livre
( extent livres
key ISBN)
{ …
attribut set<Exemplaire> lesExemplaires
… };
Class Exemplaire
( extent exemplaires key idExemplaire) {
… attribut Livre leLivre
27/02/22 © Robert Godin. Tous droits réser vés.
10
16.1.5 Association en ODL (relationship)
Class Livre
( extent livres
key ISBN)
{ …
relationship set<Exemplaire> lesExemplaires inverse Exemplaire::leLivre
… };
Class Exemplaire
( extent exemplaires key idExemplaire)
{ …
relationship Livre leLivre
inverse Livre::lesExemplaires
…
};
16.1.6 Spécification de la signature des opérations
Class Utilisateur : Personne ( extent utilisateurs
key idUtilisateur) { attribute string nom;
attribute string prénom;
attribute string idUtilisateur;
attribute string motPasse;
relationship set<Prêt> lesPrêts
inverse Prêt::lUtilisateur void setMotPasse( in String m);
integer nbPrêtsEnCours();
27/02/22 © Robert Godin. Tous droits réser vés.
12
16.2 Objets
transients/persistants
Cohabitation des objets
transiants/persistants pour une même classe
Persistance par atteignabilité
16.2.1 Constructeurs d'objets
Interface ObjectFactory { Object new();
};
Interface Object
{ enum Lock_Type{read, write, upgrade};
void lock(in Lock_Type mode) raises(LockNotGranted);
boolean try_lock(in Lock_Type mode);
boolean same_as(in Object anObject);
Object copy();
void delete();
};
27/02/22 © Robert Godin. Tous droits réser vés.
14
16.2.2 Contrôle de concurrence
Pessimiste par défaut
– verrouillage en deux phases
– mode read (partagé) en lecture
– mode write (exclusif) en écriture
– mode upgrade
demande explicite par lock() ou try-lock()
16.2.3 Noms de racines persistantes
bind() pour créer un nom de racine persistante
–
extent est une racine persistante
persistance par atteignabilité (reachability)
–
objets qui sont référencés par une racine deviennent persistants
–
au commit
lookup() pour chercher la racine
Interface Database{ void open(in String anOdmsName)
raises(DatabaseNotFound,DatabaseOpen);
void close() raises(DatabaseClosed, TransactionInProgress);
void bind(in Object anObject, in String aName) raises(DatabaseClosed, ObjectNameNotUnique, TransactionNotInProgress);
Object unbind(in String aName)
raises(DatabaseClosed, ObjectNameNotFound, TransactionNotInProgress);
Object lookup(in String aName)
raises(DatabaseClosed, ObjectNameNotFound,
27/02/22 © Robert Godin. Tous droits réser vés.
16
Autres approches de contrôle de la persistance
Contrôle programmatique explicite
– objet.makePersistent()
Par héritage
– sous-classes d ’une classe spéciale
16.2.4 Gestion des OID persistants
Table OID -> adresse transiante
– coût important de traduction
Mutation de pointeurs (pointer swizzling)
– bit qui distingue entre OID et adresse transiante
– quand muter ?
Automatique : au chargement
À la demande : au premier parcours
Mécanisme de mémoire virtuelle (hardware)
–
Object Store
27/02/22 © Robert Godin. Tous droits réser vés.
18
16.3 Le langage de requête OQL
Similarités avec SQL
– table -> racine persistente
Grammaire complète :
– http://www.odmg.org
16.3.1 SELECT de base
Le titre des livres parus après 1999
SELECT l.titre FROM livres AS l
WHERE l.annéeParution > 1999 Class Livre
( extent livres key ISBN)
{ attribute string ISBN;
attribute string titre;
attribute integer annéeParution;
relationship set<Exemplaire> lesExemplaires inverse Exemplaire::leLivre;
relationship list<Auteur> lesAuteurs inverse Auteur::lesLivres;
relationship Editeur lEditeur
inverse Editeur::lesLivres;
relationship Catégorie laCatégorie inverse Catégorie::lesLivres;
integer nbExemplairesDisponibles();
};
27/02/22 © Robert Godin. Tous droits réser vés.
20
16.3.2 Clause DISTINCT
Le titre et l'année des livres parus après 1999 sans doublons
SELECT DISTINCT l.titre, l.annéeParution FROM livres l
WHERE l.annéeParution > 1999 type du résultat :
litteral set<struct<titre:String,annéeParution integer>>
16.3.3 Constructeur STRUCT
Le titre et l'annéeParution des livres parus après 1999
Équivalent à
SELECT STRUCT(titre:l.titre, annéeParution:l.annéeParution) FROM livres AS l
WHERE l.annéeParution > 1999 type du résultat :
litteral bag<struct<titre:String,annéeParution:integer>>
SELECT l.titre,l.annéeParution FROM livres AS l
WHERE l.annéeParution > 1999
type du résultat :
27/02/22 © Robert Godin. Tous droits réser vés.
22
16.3.4 Sélection d'objets de la BD
Collection de références aux objets de la classe Livre parus après 1999
Peut ensuite manipuler les objets persistants
SELECT l
FROM livres l
WHERE l.annéeParution > 1999 type du résultat :
litteral bag<Livres>
16.3.5 Requête sans SELECT
Collection des livres
livres
type du résultat :
set<Livres>
27/02/22 © Robert Godin. Tous droits réser vés.
24
16.3.6 Expressions de chemins
Le titre de l ’objet unLivre (type Livre)
Exemple avec une opération
unLivre.titre
type du résultat : String
unLivre.nbExemplaires() type du résultat :
litteral integer
Expressions de chemins (suite)
Naviguer une association
En cascade
unLivre.lesExemplaires type du résultat :
set<Exemplaire>
unLivre.laCatégorie.leParent type du résultat :
Catégorie
27/02/22 © Robert Godin. Tous droits réser vés.
26
Navigation à travers une collection
Les idExemplaires d'un livre
Les idExemplaire des livres de l'année 2000
SELECT e.idExemplaire
FROM unLivre.lesExemplaires AS e type du résultat :
litteral bag<String>
SELECT e.idExemplaire
FROM livres AS l, l.lesExemplaires AS e WHERE l.annéeParution = 2000
type du résultat :
litteral bag<String>
Navigation à travers une collection (suite)
Le ISBN des livres actuellement empruntés par le membre dont le idUtilisateur = ‘unId’
SELECT p.lExemplaire.leLivre.ISBN
FROM membres AS m, m.lesPrêts AS p WHERE m.idUtilisateur = "unID" AND
P IN prêtsEnCours type du résultat :
litteral bag<String>
27/02/22 © Robert Godin. Tous droits réser vés.
28
16.3.7 SELECT enchâssé dans le FROM
les idExemplaire des livres de l'an 2000
SELECT e.idExemplaire
FROM (SELECT l.lesExemplaires FROM livres AS l
WHERE l.annéeParution = 2000) AS l2k, l2k.lesExemplaires AS e
type du résultat :
litteral bag<String>
16.3.8 SELECT enchâssé dans la
spécification du résultat d'un SELECT
Les ISBN des livres de l'an 2000
accompagnés de leurs exemplaires empruntés
SELECT
STRUCT(ISBN: l.ISBN, emprunts:(SELECT e
FROM l.lesExemplaires AS e WHERE e.statut = "prêté")) FROM livres AS l
WHERE l.annéeParution = 2000 type du résultat :
litteral bag<STRUCT<ISBN:String,emprunts:set<Exemplaire>>
27/02/22 © Robert Godin. Tous droits réser vés.
30
16.3.9 Aplatissement d'une collection de collections (FLATTEN)
FLATTEN(set ( set(1, 3), set (2, 5, 3), set (5, 8)) ) = set(1, 2, 3, 5, 8)
Extraire les exemplaires des livres parus en l'an 2000
FLATTEN (SELECT l.lesExemplaires FROM livres AS l
WHERE l.annéeParution = 2000) type du résultat :
litteral bag<Exemplaire>
16.3.10 Extraction de l'élément d'un singleton (ELEMENT)
Retourner l’objet de la classe
Livre qui correspond au ISBN =
‘111-11111-11’
element(
SELECT l FROM livres AS l
WHERE l.ISBN = "111-11111-11"
)
27/02/22 © Robert Godin. Tous droits réser vés.
32
16.3.11 Constructeurs d'objets
Le constructeur suivant construit un objet de la classe Exemplaire
Class Exemplaire
( extent exemplaires key idExemplaire)
{ attribute string idExemplaire;
attribute date dateAchat;
attribute enum statut {prêté,disponible,retiré};
relationship Livre leLivre
inverse Livre::lesExemplaires relationship set<Prêt> lesPrêts
inverse Prêt::lExemplaire };
Exemplaire(
idExemplaire : "A1E2F",
dateAchat : date "2000-04-25", statut : "disponible",
leLivre : element(
SELECT l FROM livres AS l
WHERE l.ISBN = "111-11111-11"),
LesPrêts : set())
16.3.12 Comparaison par identité ou par valeur
Le = compare les OID des objets
27/02/22 © Robert Godin. Tous droits réser vés.
34
16.3.13 Quantificateurs FOR ALL et EXISTS
Les livres dont tous les exemplaires sont empruntés
Les livres dont au moins un exemplaire est emprunté
SELECT l
FROM livres AS l
WHERE FOR ALL e IN l.lesExemplaires : e.statut = "prêté"
type du résultat : litteral set<Livre>
SELECT l
FROM livres AS l
WHERE EXISTS e IN l.lesExemplaires : e.statut = "prêté"
type du résultat :
litteral set<Livre>
16.3.14 Quantificateurs SOME, ANY et ALL
e1 op {SOME|ANY} e2
EXISTS ele IN e2 : e1 op ele
e1 op ALL e2
FOR ALL ele IN e2 : e1 op ele
27/02/22 © Robert Godin. Tous droits réser vés.
36
16.3.15 Fonctions de groupe
Le nombre moyen d’exemplaires disponibles par livre
AVG (SELECT l.nbExemplairesDisponibles()
FROM livres AS l)
16.3.16 Partition avec GROUP BY
Le nombre d’exemplaires disponibles par années de parution pour les années où le nombre dépasse 100
SELECT année,
nombreDisponibles :
SUM(SELECT l.nbExemplairesDisponible() FROM partition) FROM livres AS l
GROUP BY année : l.annéeParution
HAVING SUM(SELECT l.nbExemplairesDisponible() FROM partition) > 100 type du résultat :
litteral bag<struct<année : integer, nombreDisponibles : integer>>
27/02/22 © Robert Godin. Tous droits réser vés.
38
16.3.18 Tri avec ORDER BY
Les livres triés par ordre
descendant (DESC) de l’année de parution et par ordre ascendant (ASC) du titre
SELECT l
FROM livres AS l
ORDER BY l.annéeParution DESC, l.titre ASC type du résultat :
litteral set<Livre>
16.4.2.1 SCÉNARIO GLOBAL DE MANIPULATION DE DONNÉES EN JAVA
/* Ouvrir la BD
Implementation lImplementation = …; //extraction de l'objet spécifique au SGBDO Database maBD = lImplementation.newDatabase();
maBD.open(unNom, unModeDacces);
/* Débuter une transaction
Transaction uneTransaction = lImplementation.newTransaction();
uneTransaction.begin();
/*Lookup objet ou bind pour avoir accès à une ou des racines persistantes (au besoin). Opérations de manipulation de données Java (new, opérations d’update, les objets non accessibles sont automatiquement supprimés et garbage collectés… ; les liens créés entre objets par l’intermédiaire d’attributs sont gérés de manière persistante par le SGBD objet)
uneTransaction.commit();
/* Une autre transaction uneTransaction.begin();
…
uneTransaction.commit();
27/02/22 © Robert Godin. Tous droits réser vés.
40
16.4.2.2 DÉFINITION DE CLASSES CAPABLES DE PERSISTANCE
Dcollection, Dset, Dbag, Dlist, Darray et Dmap
// Exemple de classe Editeur public class Editeur
{
/* Les attributs de la classe private String nomEditeur ; private String ville ;
// La collection des livres de l'éditeur (pour l'association avec Livre) private Dset lesLivres;
// Exemple de classe Livre
// Seule l'association avec l'éditeur est prise en compte pour fin d'illustration public class Livre
{
/* Les attributs de la classe inlcuant les attributs pour réaliser /* les associations
private String ISBN ; private String titre ;
private integer annéeParution ; // Pour l'association avec Editeur
private Editeur lEditeur;
16.4.2.3 CRÉATION D'UNE RACINE PERSISTANTE
public class exempleInsertionsNouveauxObjetsOMLJava { public static void main (String args []){
/* Ouvrir la BD
Implementation lImplementation = …;
maBD = lImplementation.newDatabase();
maBD.open(unNom, unModeDacces);
/* Débuter une transaction
Transaction uneTransaction = lImplementation.newTransaction();
uneTransaction.begin();
/* Création d’une racine persistante editeurs qui joue le rôle de l’extent des éditeurs
Dset editeursSet = new Dset();
maBD.bind(editeursSet,’editeurs’) ;
/* En ajoutant unEditeur à la collection editeursSet qui est une racine persistante, unEditeur devient persistant par atteignabilité
Editeur unEditeur = new Editeur(‘Loze-Dion’,’Longueuil’);
editeursSet.add(unEditeur);
Editeur unAutreEditeur = new Editeur(‘Addison-Wesley’,’Reading MA’);
editeursSet.add(unAutreEditeur);
/* Les livres deviennent aussi transitivement persistants par atteignabilité lorsqu'ils somt ajoutés à la collection des livres d'un éditeur
Livre unLivre = new Livre(‘1-111-1111’, ‘SGBD’, 2000, unEditeur);
unEditeur.addLivre(unLivre);
Livre unAutreLivre = new Livre(‘2-222-2222’, ‘le titre’, 1999, unEditeur);
unEditeur.addLivre(unLivre);
27/02/22 © Robert Godin. Tous droits réser vés.
42
16.4.2.4 NAVIGATION À PARTIR D'UNE RACINE PERSISTANTE
public class exempleQuerySurDcollection{
public static void main (String args []){
/* Ouvrir la BD
Implementation lImplementation = …;
maBD = lImplementation.newDatabase();
maBD.open(unNom, unModeDacces);
/* Débuter une transaction
Transaction uneTransaction = lImplementation.newTransaction();
uneTransaction.begin();
/* Recherche de la racine persistante editeurs Dset editeursSet = (Dset)maBD.Lookup(’editeurs’);
/* Itérer sur editeurs
Iterator itérateurEditeurs = editeurSet.iterator();
while(iterateurEditeur.hasNext()){
Editeur unEditeur = (Editeur)iterateurEditeur.next();
/* traitement d'unEditeur }
uneTransaction.commit();
maBD.close();
} }
16.4.2.5 REQUÊTE SIMPLE SUR UNE DCOLLECTION
public class exempleItérationSurLesEditeurs{
public static void main (String args []){
/* Ouvrir la BD
Implementation lImplementation = …;
maBD = lImplementation.newDatabase();
maBD.open(unNom, unModeDacces);
/* Débuter une transaction
Transaction uneTransaction = lImplementation.newTransaction();
uneTransaction.begin();
/* Recherche de la racine persistante editeurs Dset editeursSet = (Dset)maBD.Lookup(’editeurs’);
Dcollection editeursDeParis = editeurSet.query(" ville = 'Paris'OR ville = 'Longueuil' ");
/* Manipulation de la collection editeursDeParis … uneTransaction.commit();
maBD.close();
}
27/02/22 © Robert Godin. Tous droits réser vés.
44
16.4.2.6 REQUÊTE OQL
public class exempleOQL{
public static void main (String args []){
/* Ouvrir la BD
Implementation lImplementation = …;
maBD = lImplementation.newDatabase();
maBD.open(unNom, unModeDacces);
/* Débuter une transaction
Transaction uneTransaction = lImplementation.newTransaction();
uneTransaction.begin();
/* Extraire la collection des éditeurs de Paris
OQLQuery uneRequeteOQL = lImplementation.newOQLQuery();
uneRequeteOQL.create("SELECT e FROM e IN editeurs WHERE e.ville = $1 OR e.ville = $2");
uneRequeteOQL.bind("Paris"); uneRequeteOQL.bind("Longueuil");
Dcollection editeursDeParis = OQLQuery.execute();
/* Manipulation de la collection editeursDeParis … uneTransaction.commit();
maBD.close();
} }