plan de cette partie sgbdoo - département...
Post on 10-Sep-2018
223 Views
Preview:
TRANSCRIPT
1
SGBDOO
Université de Nice Sophia-AntipolisVersion 2.0.1 – 22/10/11
Richard Grin
Plan de cette partie
Les Systèmes de Gestion de Bases de données Orientés Objet (SGBDOO)Le SGBDOO db4o
Richard Grin SGBDOO page 2
Pourquoi un SGBDOO ?
Richard Grin SGBDOO page 3
SGBDR
Un SGBDR ne comprend pas la notion d’objet ou d’association entre objetsIl comprend les notions de table, ligne, clé étrangère,…Il n’est pas possible de dire à un SGBDR « range tel objet »Il ne comprend que « range tels attributs dans telle table »Difficile de gérer les objets complexes ou liés au multimédia (images, vidéo,…)
Richard Grin SGBDOO page 4
Sauvegarder avec un SGBDR
Sauvegarde d’un objet dans un SGBDR :1. Demander à l’objet son identité et les valeurs
de toutes ses propriétés2. Lancer une commande SQL pour
sauvegarder ces propriétés dans la BD3. Pour chaque association de l’objet avec un
autre objet, regarder si les objets associés sont déjà dans la BD ; s’ils n’y sont pas, les sauvegarder comme pour l’objet (étape 1.) en donnant la bonne valeur à la clé étrangère
Richard Grin SGBDOO page 5
Récupérer avec un SGBDR
Récupérer un objet rangé dans un SGBDR :1. Lire toutes les propriétés de l’objet dans la
BD (requête SQL)2. Créer l’objet en mémoire centrale et
l’initialiser avec les valeurs lues3. Pour chaque propriété clé étrangère, lire les
données associées dans la BD, regarder si l’objet correspondant existe déjà et sinon le créer comme pour l’objet à l’étape 1.
Richard Grin SGBDOO page 6
2
Sans doute pas une manière très naturelle de faire !Ne pourrait-on travailler avec un SGBD qui comprendrait la notion d’objet et d’association entre objets ?
Richard Grin SGBDOO page 7
(dessin extrait d’un document de Objectivity)
Généralités sur les SGBDOO
Richard Grin SGBDOO page 8
Introduction
Un SGBDOO est un SGBD qui s’appuie sur le modèle objetLe schéma de la base est un schéma objet (objets, héritage, polymorphisme,…)En anglais, Object Oriented Data Base Management System (OODBMS)
21/11/99 Richard Grin SQL - page 9
Historique 1/2
Premiers projets au début des années 1980, suivis de 2 produits, dont Versant qui est toujours venduPlusieurs SGBDOO à la fin des années 19801991 : ODMG (Object Data Management Group), formé de vendeurs de SGBDOO, pour sortir le standard ODMG 1.0 en 1993ODMG participe à la normalisation du langage de requête OQLDissous en 2001, juste après ODMG 3.0
Richard Grin SGBDOO page 10
Historique 2/2
1995 : Le manifeste pour les SGBDOO2000 : le pic pour les SGBDOO (déclin depuis)Regain ces derniers temps avec des projets open source comme db4o, plus particulièrement pour les applications embarquées
Richard Grin SGBDOO page 11
Quelques SGBDOO
Versant Object Database pour C++ et Java ; Fast Objects .NETObjectStoreObjectivity/DBO2 (par universitaires français, n’existe plus)db4o (acheté par Versant fin 2008)
Richard Grin SGBDOO page 12
3
ODMG
Object Data Management GroupGroupe de vendeurs de SGBDOO et d’expertsSpécifications pour améliorer la portabilité des applications qui utilisent des SGBDOOModèle objet pour les objets persistants, qui s’appuie sur le modèle objet de l’OMG (Object Management Group), créateur de CORBA
Richard Grin SGBDOO page 13
Langages du standard ODMG
Langage de définition ODLLangage d’interrogation et de modification non procédural OQL, du type de SQLLiaisons avec les langages C++, Smalltalk et Java (JDO pour Java) pour utiliser ODL et OQLAucun produit n’implémente complètement ces langages
Richard Grin SGBDOO page 14
ODL
Interface et classesclass voiture (extents voitures key id) : vehicule {attribute short id;attribute float longueur...void demarrer();void arreter();
}
Richard Grin SGBDOO page 15
Requête ODL
select tuple (h.nom, h.nombre_de_lits)from h in Hopitalwhere h.adresse.ville.nom = "Paris" and "scannerl" in h.equipement
Richard Grin SGBDOO page 16
« OODBMS Manifesto »
Décrit les propriétés qu’un SGBDOO doit avoirEcrit par des universitaires en 1995
Richard Grin SGBDOO page 17
Propriétés obligatoires 1/3
Support des objets complexes, des ensembles, listes et tuples2 objets distincts peuvent avoir exactement les mêmes valeurs ; identité des objetsEncapsulation, mais moins stricte que pour les langages objetSupport des types, classes et héritageLiaison retardée, surcharge et redéfinition pour les opérations (méthodes)
Richard Grin SGBDOO page 18
4
Propriétés obligatoires 2/3
Nouveaux types définis par l’utilisateurPersistance d’un objet indépendante de son typePrise en charge des grandes BD (index, cluster, caches, optimisation des requêtes,…)Gestion des accès concurrents et des utilisateurs multiples, sérialisation des opérationsPossibilité de reprise après panne
Richard Grin SGBDOO page 19
Propriétés obligatoires 3/3
Facilités pour rechercher des données ; haut niveau, efficacité, indépendance vis-à-vis des applications
Richard Grin SGBDOO page 20
Propriétés optionnelles
Héritage multipleVérification des types à la compilationDistribution des donnéesModèles de transaction complexe (transactions longues, emboîtées)Gestion des versions des types de données
Richard Grin SGBDOO page 21
Modèles de persistance
Les principales possibilités sont :n persistance automatique par héritagen persistance automatique par référencen persistance explicite
Richard Grin SGBDOO page 22
Persistance par héritage
Une classe racine est fournie par le systèmeLes instances des classes qui héritent de cette classe sont automatiquement persistantesIl est possible de spécifier des instances de ces classes qui ne sont pas persistantesPas pratique pour les langages qui ne supportent pas l’héritage multiple
Richard Grin SGBDOO page 23
Persistance par référence
On peut indiquer explicitement que des objets sont persistantsTous les objets référencés par un objet persistant sont automatiquement persistants
Richard Grin SGBDOO page 24
5
Identité
Les SGBDOO utilisent l’identité des objets pour assurer l’unicité des objets et pour implémenter les associationsUn objet doit avoir une identité indépendamment de ses valeurs (au contraire d’une ligne d’un SGBDR)Le OID (Object IDentifier), généré, géré par le SGBD et sauvegardé avec les objets, sert à identifier les objets dans le SGBDOO
Richard Grin SGBDOO page 25
Difficulté possible
Le SGBDR aide le développeur à éviter les doublons en vérifiant l’unicité de la clé primaireAvec un SGBDOO, c’est l’application qui a la charge d’empêcher les doublonsMais les SGBDOO offrent presque tous la possibilité de définir une contrainte d’unicité sur un attribut (à partir de la version 7 de db4o)
Richard Grin SGBDOO page 26
2 types d’identité
2 types d’identité :n physique, qui dépend de l’emplacement où
l’objet est conservén logique, identificateur alloué par le système
et indépendant de l’emplacement de l’objet
Richard Grin SGBDOO page 27
Comparaison des types d’identité
Physique :n accès très rapiden difficile de changer un objet de placen donc problème si la taille de l’objet grandit
et qu’il faut le déplacern fragmentation de la mémoire
Logique :n plus souple, par exemple pour passer un
objet d’une base à une autre
Richard Grin SGBDOO page 28
Références
Les références vers d’autres objets utilisent les identifiants d’objets
Richard Grin SGBDOO page 29
Gestion des versions
De nombreux SGBDOO permettent de travailler avec des objets qui ont été créés avec différentes versions de leur classe, si les différences ne sont pas trop importantesLes objets des anciennes versions sont traduits « à la volée » dans nouvelles versionsL’administrateur peut aussi lancer des procédures pour faire passer les objets des anciennes versions à la version la plus récente
Richard Grin SGBDOO page 30
6
Types d’architecture
Serveur d’objetsServeur de pagesServeur de fichiers
Richard Grin SGBDOO page 31
Motivations (1)
Les SGBDR reposent sur le modèle d’architecture client – serveur, avec des clients très légersIls datent des années 80 où la puissance de calcul était concentrée dans les mainframesLes SGBDOO apparaissent au début des années 90A cette date une grande partie de la puissance de calcul n’est plus dans les serveurs centraux ; elle est plutôt dans les stations de travail
Richard Grin SGBDOO page 32
Motivations (2)
Les SGBDOO ont transféré une partie des traitements dans les machines clientes pour profiter de leur puissance et alléger la tâche supportée par les machines serveurs
Richard Grin SGBDOO page 33
Serveur d’objetsCelle qui semble la plus naturelleLe serveur connaît la notion d’objet (Object-Based ou Object-Server)Il gère des objets :n il renvoie des objets en réponse aux
requêtes des clientsn il peut lancer des méthodes (procédures)
sur les objets pour répondre aux requêtesLa machine cliente contient un cache pour les objets qu’elle manipule
Richard Grin SGBDOO page 34
Serveur d’objets – schéma 1
Richard Grin SGBDOO page 35
Extrait d’un article de Robert Greene
Serveur d’objets – schéma 2
Richard Grin SGBDOO page 36
Extrait d’un article de De Witt, Futtersack, Maier, Velez
7
Serveur de pagesLe serveur ne connaît pas le concept d’objet ; il ne peut lancer une méthode sur un objetIl conserve les données dans des pages (Page-Based ou Page-Server)Le client sait dans quelles pages se trouvent les objets et il demande ces pages au serveurLe client récupère et construit les objets à partir des pages que le serveur lui a renvoyéesLe client a un cache pour les pages qu’il manipule
Richard Grin SGBDOO page 37
Serveur de pages – schéma 1
Richard Grin SGBDOO page 38
Serveur de pages – schéma 2
Richard Grin SGBDOO page 39
Serveur de fichiers
Une variante du serveur de pages qui utilise un système du type NFS (File-Server)Le client récupère les données par des appels NFS (Network File System), comme si elles étaient sur le système de fichiers localAppelé aussi Container-Based (les segments de disques NFS sont appelés des containers)
Richard Grin SGBDOO page 40
Serveur de fichiers – schéma 1
Richard Grin SGBDOO page 41
Serveur de fichiers – schéma 2
Richard Grin SGBDOO page 42
8
Choix d’une architecture
Pas de solution meilleure dans tous les casLes principaux critères qui interviennent :n puissance et charge des clients et des serveurs ;
les architectures « pages » mettent plus de charge sur les clients ; risque de surcharge du serveur avec l’architecture « objets »
n charge du réseau ; moins de données en transit avec l’architecture « objets »
n le type de concurrence ; granularité plus fine avec l’architecture « objets » ; possible de bloquer un seul objet avec architecture « objets »
Richard Grin SGBDOO page 43
db4o
Richard Grin SGBDOO page 44
Objectifs de cette section
Donner les informations pour faciliter l’écriture du TP sur db4o
Richard Grin SGBDOO page 45
Spécificités de db4o
LégerPas de maintenance / administrationSimple d’emploiAPI simple pour Java et .NETRequêtes nativesPas un SGBDOO ODMG, pas de requêtes OQL par exempleConvient bien à une application embarquée (BD pas partagée entre plusieurs applications)
Richard Grin SGBDOO page 46
Exemple basiqueObjectContainer bd =
Db4oEmbedded.openFile("bd.data"); Personne personne =
new Personne("Dupond", "Pierre", 35); // Ajoute dans la base de données bd.store(personne);bd.commit(); // Récupère ce qui correspond à un exempleObjectSet<Personne> personnes =
bd.queryByExample(new Personne(null, null, 40)); for (Personne p : personnes) {
System.out.println(p); } } bd.close(); Richard Grin SGBDOO page 47
à mettre dans un bloc finally
Paquetages
Tous les paquetages sont des sous-paquetages de com.db4oLe paquetage com.db4o contient les interfaces et classes de base : ObjectContainer, ObjectSet, ObjectServer, Db4oEmbedded (la seule classe)
Richard Grin SGBDOO page 48
9
Connexion à une BD db4o
2 façons de se connecter :n en local, à une BD qui se trouve sur la même
machine ; une seule connexion en local est permise à un moment donné
n en client-serveur, par une connexion TCP/IP, sur une machine distante ; il faut donner un nom d’utilisateur et un mot de passe
Richard Grin SGBDOO page 49
Connexion locale
La classe Db4oEmbedded contient des méthodes static pour démarrer un moteur db4oObjectContainer openFile(nom)ouvre un ObjectContainer qui utilisera le fichier nom comme BD, en mode local
Richard Grin SGBDOO page 50
Connexion distante - serveur
ObjectServer server = Db4oClientServer.openServer(fichier, port)
à lancer sur la machine qui contient la BDLance un serveur qui utilisera le fichier nom comme BD et qui attendra les demandes de connexion des clients sur le port indiquéUne configuration peut être passée en 1er
paramètre (Db4oClientServer.newServerConfiguration())
Richard Grin SGBDOO page 51
Connexion distante - serveur
La méthode grantAccess(nom, motDePasse) de la classe ObjectServeraccorde l’autorisation de se connecter au client de nom et de mot de passe indiqués :server.grantAccess("toto", "md007p");
Richard Grin SGBDOO page 52
Connexion distante - client
ObjectContainer db = Db4oClientServer.openClient(machine, port,
utilisateur, motDePasse);à lancer sur la machine sur laquelle tourne le client qui souhaite se connecter à distanceRenvoie un ObjectContainer pour utiliser la BD installée sur la machine distante (sur laquelle tourne un serveur qui écoute le port indiqué)
Richard Grin SGBDOO page 53
Connexion distante - client
Une configuration peut être passée en 1er
paramètre (Db4oClientServer.newClientConfiguration())
Richard Grin SGBDOO page 54
10
ObjectContainer
Interface qui représente la connexion à une BD (locale ou en client-serveur)Un objectContainer garde un cache des objets qu’il manipuleLes informations contenues dans ce cache seront enregistrées dans la base de données lors d’un commit de la transaction
Richard Grin SGBDOO page 55
Méthodes de ObjectContainer (1)
void store(Object) insère ou modifie un objet dans le cache du containervoid delete(Object) supprime un objet dans le cache du container<T> ObjectSet<T> queryByExample(Object) récupère des objets qui correspondent au modèle passé en paramètre
Richard Grin SGBDOO page 56
Persistance par référence
Tous les objets référencés par un nouvel objet persistant sont automatiquement rendus persistant (s’ils ne le sont pas déjà) par la méthode store (quelle que soit la profondeur)Attention, il n’en est pas de même pour les objets passés en paramètre de la méthode store : les objets référencés et modifiés n’ont pas, par défaut, leurs modifications enregistrées dans la base au commit (voir la section sur la configuration de db4o)
Richard Grin SGBDOO page 57
Méthodes de ObjectContainer (2)
Query query() crée une nouvelle requête SODA (voir plus loin le langage SODA)<T> ObjectSet<T> query (surchargée) interroge la BD1 paramètre pour query, à choisir dans :n Class<T> : ramène tous les objets de la
classen Predicate<T> : critère de sélection ; voir
plus loin ; il est possible d’ajouter un 2ème
paramètre pour trier les objets renvoyésRichard Grin SGBDOO page 58
Méthodes de ObjectContainer (3)
close() ferme la connexioncommit()rollback()activate(Object, int profondeur)« active » un objet jusqu’à une certaine profondeur (voir section sur les requêtes)deactivate(Object, int profondeur)met les valeurs d’un objet à null ou à la valeur par défaut du type primitif, jusqu’à une certaine profondeur (attention !)
Richard Grin SGBDOO page 59
Méthodes de ObjectContainer (4)
ext() récupère une interface « avancée » ExtObjectContainer qui permet d’appeler d’autres méthodes sur ObjectContainerEn fait tous les ObjectContainer de db4o sont des ExtObjectContainer et on peut donc les caster en ce type (cf. Graphics et Graphics2D de Swing) et cette méthode évite seulement un cast
Richard Grin SGBDOO page 60
11
Insertion d’un nouvel objet dans la BDstore(objet) ajoute un nouvel objet dans le cache de l’objectContainerTous les objets « nouveaux » référencés par l’objet sont ajoutés à la base au moment du commit, et ainsi de suite tant que des objets nouveaux sont trouvésAttention, le parcours récursif s’arrête dès qu’un objet déjà présent dans le cache est rencontré ; ces objets ne sont pas mis à jour dans la BD (voir « profondeur de modification » dans la suite)
Richard Grin SGBDOO page 61
Validation de la transaction
L’ajout d’un nouvel objet dans le cache de l’objectContainer, comme la mise à jour ou la suppression n’est répercutée dans la base de données que lors de la validation (par la méthode commit()) de la transaction
Richard Grin SGBDOO page 62
Modification d’un objet dans la BDstore(objet) enregistre dans le cache les modifications effectuées sur un objet qui est déjà dans le cacheLes liens vers les objets référencés sont mis à jourLes « nouveaux » objets référencés (ceux qui ne sont pas déjà dans le cache) sont ajoutés au cache (récursivement)Les objets référencés déjà dans le cache ne sont par mis à jour dans le cache (voir « profondeur de modification » dans la suite)
Richard Grin SGBDOO page 63
Modification d’un objet
Attention, l’objet doit avoir été auparavant récupéré dans la BD (pas de clé primaire pour savoir si un objet est déjà dans la base)Tout objet créé par Java avec new est considéré comme un nouvel objet par db4o
Richard Grin SGBDOO page 64
Supprimer un objet dans la BD
Si l’objet n’est pas déjà géré par l’objectContainer, il faut tout d’abord le retrouver depuis la base, par exemple par :Classe objet =
bd.queryByExample(…);Ensuite il suffit d’appeler la méthode deletesur l’objet :bd.delete(objet);
Richard Grin SGBDOO page 65
Méthode queryByExample<T> ObjectSet<T> queryByExample (Object modele) throws Db4oIOException,
DatabaseClosedExceptionqueryByExample(null)renvoie tous les objets de la BDqueryByExample(objetModele)renvoie tous les objets de la BD qui correspondent à l’objet passé en paramètre (recherche par l’exemple)
Richard Grin SGBDOO page 66
12
ObjectSet<Item>
Classe fille de List<Item> ; il est recommandé de le ranger dans une variable de type List<Item>Attention, l’objectContainer sous-jacent doit rester ouvert pendant l’utilisation de la liste car les objets de la liste ne sont vraiment récupérés que lorsqu’on y accède !
Richard Grin SGBDOO page 67
Méthode queryMéthode surchargée<T> ObjectSet<T> query(Class<T> classe) récupère tous les objets de la BD du type de la classe passée en paramètre<T> ObjectSet<T> query(Predicate<T> prédicat)permet une requête native (voir section « Requêtes natives » ; renvoie les objets qui correspondent au prédicatUn deuxième paramètre de type Comparator<T> permet d’indiquer un ordre dans les objets renvoyés
Richard Grin SGBDOO page 68
Les exceptions
La politique de db4o est d’« avaler » les exceptions quand c’est possibleToutes les exceptions particulières à db4o sont non contrôlées (sous-types de RuntimeException)Le principal type d’exception est Db4oException qui enveloppe les exceptions lancées en interne (elles sont chaînées)
Richard Grin SGBDOO page 69
Exceptions à l’ouverture de la BD
DatabaseClosedException lancé lors d’une opération de db4o lorsque l’ObjectContainer est fermé alors qu’il devrait être ouvertDatabaseFileLockedException lancé lors de l’ouverture du fichier d’une BD (openFile) lorsque le fichier est bloqué par un autre processusDb4oIOException lancé lorsque db4o a rencontré une erreur système pour ses entrées-sorties
Richard Grin SGBDOO page 70
Gestion des exceptions
Un commit peut lancer plusieurs exceptionsLe plus souvent un commit est dans un bloc try
Si une exception est levée, il faut envisager d’invalider la transaction avec rollback()Il est aussi possible de réparer le problème dans le catch et de valider ensuite la transaction plus loin dans le catch
Richard Grin SGBDOO page 71
Exemple
try {// travail avec db4o...container.commit();
} catch (Exception ex){ .... }finally {container.close();
}
Richard Grin SGBDOO page 72
13
Exemple avec rollback
try {// travail avec db4o...container.commit();
} catch (Exception ex){container.rollback(); ...
}
finally { container.close(); }
Richard Grin SGBDOO page 73
Rollback
Attention, après un rollback les objets Java qui ont été modifiés pendant la transaction ne reflètent plus les valeurs de la BDIl faudra donc recharger les bonnes valeurs depuis la base de données si on veut les réutiliser (par une requête ou refresh ; on peut aussi désactiver ces objets pour effacer les mauvaises valeurs)
Richard Grin SGBDOO page 74
Méthodes de ExtObjectContainervoid refresh(Object objet,
int profondeur)ramène les valeurs qui sont actuellement dans la BD, jusqu’à une certaine profondeurvoid store(Object, profondeur)ajoute ou modifie un objet dans le cache de l’objectContainer en indiquant la profondeur de modificationboolean isClosed()boolean isStored(Object)
Richard Grin SGBDOO page 75
Méthodes de ExtObjectContainer<T> T peekPersisted(T objet, intprofondeur, boolean committed)retourne une copie d’un objet de la BD, avec les valeurs qu’il a actuellement dans la BD.commited indique si la copie tient compte des valeurs modifiées par les appels à storede la transaction en cours (pas encore validée par un commit)Peut servir à récupérer la valeur actuelle dans la base, avant un commit (3ème
paramètre à true) pour implémenter une stratégie optimiste de la concurrence
Richard Grin SGBDOO page 76
ExempleEmploye e = bd.queryByExample(…);salInitial = e.getSalaire();... // Nouveau salaire pour ee.setSalaire(nouvelleValeur);bd.store(e);...Employe eDansDb =
bd.ext().peekPersisted(e, 3, true);if (salInitial != eDansBd.getSalaire())
db.rollback();else
db.commit();Richard Grin SGBDOO page 77
Méthodes de ExtObjectContainerIdentité interne
long getId(objet) retourne l’identité « interne » (physique) d’un objet géré par l’ObjectContainer ; garantie d’unicité dans un seul ObjectContainer (mais change si la base est défragmentée)<T> T getById(long) accès le plus rapide à un objet dont on connaît l’id ; n’active pas l’objet (garde le niveau d’accès qu’il a déjà dans le cache local géré par l’objectContainer)
Richard Grin SGBDOO page 78
14
Méthodes de ExtObjectContainerIdentité logique
ObjectInfo getObjectInfo(objet)pour avoir la référence à un objet géré par l’ObjectContainerLa méthode Db4oUUID getUUID() de l’interface ObjectInfo retourne l’UUID de l’objet (garantie d’unicité dans toutes les bases de données db4o) <T> T getByUUID(Db4oUUID)
La génération d’UUID doit être configurée (méthode generateUUID de l’interface EmbeddedConfiguration)
Richard Grin SGBDOO page 79
Recherche par l’exemple(Query By Example, QBE)
Richard Grin SGBDOO page 80
Recherche par l’exemple
L’objet passé en paramètre de queryByExample indique les objets recherchésSes variables d’instances qui n’ont pas la valeur null (ou la valeur par défaut si la variable est d’un type primitif Java) forment le critère de rechercheSi on passe la valeur null à queryByExample , tous les objets de la base sont retournés
Richard Grin SGBDOO page 81
Exemple
ObjectSet<Facture> factures = bd.queryByExample(new Facture("08/54", null, null))
Richard Grin SGBDOO page 82
Avantages
Simple
Richard Grin SGBDOO page 83
Inconvénients
Pas possible de faire une recherche des objets qui ont la valeur par défaut des types primitifsDes conditions ne sont pas exprimables (pas d’autres comparaison que l’égalité par exemple)Un constructeur qui accepte les valeurs nulldoit existerImpossible de faire une recherche polymorphe sous une classe abstraite ou une interface (car pas possible de construire l’objet exemple)
Richard Grin SGBDOO page 84
15
Activation d’un objetUn objet est activé s’il est créé en mémoire par le container et si ses attributs sont remplis avec les valeurs de la base de donnéesTous les objets directement renvoyés par un queryByExample (ou par un query ; voir section suivante) sont activésActiver tous les objets référencés par un objet activé n’est pas toujours souhaitableIl est possible de configurer la profondeur d’activation lors d’une requête pour retrouver des objets de la base
Richard Grin SGBDOO page 85
Profondeur d’activation
Par défaut, la profondeur d’activation est 5Une profondeur de 1 signifie que seul l’objet racine est activé ; les objets qu’il référence ne sont pas créés en mémoire centraleIl est possible d’activer explicitement un objet, en donnant la profondeur ; par exemple, si un employé emp a été activé mais pas son département, le code suivant activera le département avec une profondeur de 1 :db.activate(emp.getDepartement(), 1);
Richard Grin SGBDOO page 86
Changer la profondeur d’activation
On peut la changer globalement ou pour tous les objets d’une classe (voir la section « Configuration de db4o »)
Richard Grin SGBDOO page 87
Activation transparente (1)
Depuis la version 7 db4o peut activer automatiquement les objets lorsque c’est utileCela signifie que les objets sont créés en mémoire à partir des données de la base si le code de l’application les utilise, sans que le développeur ait à se soucier de fixer la profondeur d’activation
Richard Grin SGBDOO page 88
Activation transparente (2)
Pour cela les classes des objets persistants doivent implémenter l’interface Activatable, ce qui peut être fait automatiquement par un outil fourni par db4oIl faut aussi configurer la base pour qu’elle supporte cette fonctionnalité :Configuration configuration = Db4oEmbedded.newConfiguration();
configuration.common().add(new TransparentActivationSupport());
Richard Grin SGBDOO page 89
Persistance transparente (1)On a vu que lorsqu’un instance de classe est modifiée et ensuite passée en paramètre de store, seules les modifications effectuée sur l’instance elle-même sont enregistrées dans la basePar défaut, les modifications effectuées sur les instances référencées par cette instance, et déjà gérées par db4o ne sont pas enregistrées ; on peut cependant changer la profondeur de modification comme on le verra dans la section « Configuration de db4o »
Richard Grin SGBDOO page 90
16
Persistance transparente (2)
La version 7 a ajouté la possibilité de mettre à jour automatiquement ces instances référencées par l’instance passée en paramètre de storeLes classes des instances concernées doivent implémenter l’interface ActivableIl faut aussi configurer la base pour qu’elle supporte cette fonctionnalité :configuration.common().add(new TransparentPersistenceSupport());
Richard Grin SGBDOO page 91
Interface Activatable
Lorsqu’un objet implémente cette interface, par défaut il n’est pas activé : ses champs ne sont pas initialisésLorsqu’une méthode est appelée sur cet objet, il doit donc être d’abord activéC’est pour cela que toutes les méthodes qui sont liées à la persistance de l’objet qui implémente cette interface doivent être modifiées pour commencer par activer l’objet
Richard Grin SGBDOO page 92
Méthodes de l’interface Activatable
void bind(Activator activator) : appelée par db4o lorsque l’instance est récupérée depuis la base, pour associer un « activator » à l’instancevoid activate(ActivationPurpose but) : doit être appelée au début des méthodes de la classe en passant comme but la valeur READ de ActivationPurpose (pour les méthodes liées à l’écriture dans la base) ou Write (pour les méthodes liées à la lecture)
Richard Grin SGBDOO page 93
Implémentations des méthodes de Activatable
Il y a une implémentation qui convient la plupart du tempsLe plus simple est d’utiliser un outil fourni par db4o, le enhancer, sous la forme d’une tâche ant contenue dans le fichier jar dont le nom se termine par « -tools »Consultez la documentation de db4o pour plus de précision
Richard Grin SGBDOO page 94
Faut-il utiliser Activatable ?Cette interface facilite la tâche du développeur qui n’a plus à positionner la profondeur d’activation ou la profondeur de modification pour chaque cas particulierMais est-ce que les performances ne sont pas affaiblies par cet automatisme ?Et est-ce que cette facilité justifie la modification de toutes les classes du modèle objet ?Voir aussi les problèmes exposés à l’adresse : http://developer.db4o.com/Resources/view.aspx/Reference/Usage_Pitfalls
Richard Grin SGBDOO page 95
Requêtes natives
Richard Grin SGBDOO page 96
17
Définition
La requête est définie dans le langage de programmation, Java par exempleAvantages : n pas de nouveau langage à apprendren grande souplessen erreurs détectées à la compilation
Désavantage :n peut ne pas être optimisé
Richard Grin SGBDOO page 97
Exemple
Predicate<Personne> predicat =new Predicate<Personne>() {public boolean match(Personne p) {
return p.getAge() > 60;}
};List<Personne> personnes = bd.query(predicat);
Richard Grin SGBDOO page 98
Tri du résultat de la recherche
Il est possible de passer un Comparator(paquetage java.util ; voir cours sur les collections) en paramètre de la méthode query, avec le PredicateL’ensemble des objets retournés sera trié en utilisant ce Comparator
Richard Grin SGBDOO page 99
Exemple
Comparator<Personne> cmp = new Comparator<Personne>() {public int compare(
Personne p1, Personne p2) {return p1.getNom()
.compareTo(p2.getNom());}
};List<Personne> personnes = bd.query(predicat, cmp);
Richard Grin SGBDOO page 100
Optimisation d’une requête native
La Façon naïve d’exécuter une requête native :1. récupérer tous les objets de la base 2. les passer un par un à la méthode match3. ne garder que ceux pour lesquels match
renvoie trueSi le nombre d’objets est important, les performances seront catastrophiques
Richard Grin SGBDOO page 101
Optimisation d’une requête native
Pour obtenir de meilleures performances les requêtes natives doivent être transformées en requêtes SODA pour profiter des index et des optimisations de db4o, et ne pas avoir à créer trop d’objets
Richard Grin SGBDOO page 102
18
Ecouteur pour requêtes nativesPermet de savoir si la requête native a été optimisée par db4oPar exemple :((ObjectContainerBase)bd).getNativeQueryHandler().addListener(
new Db4oQueryExecutionListener() {public void notifyQueryExecuted(
NQOptimizationInfo info) { System.out.println(info.message());
} });
Richard Grin SGBDOO page 103
Requêtes SODA(Simple Object Data Access)
Richard Grin SGBDOO page 104
Utilité du langage SODA
Les requêtes natives sont traduites dans le langage SODAIl peut être utile de connaître ce langage pour les cas où une requête native ne peut être automatiquement optimisées ou, pour optimiser au maximum des requêtesCe cours n’en donne qu’un rapide aperçu
Richard Grin SGBDOO page 105
Graphe pour SODA
L’idée de SODA est de représenter une requête comme un arbre dont les nœuds représentent des classes ou des champs et les arêtes représentent des associations pour atteindre les nœudsDes contraintes associées aux nœuds indiquent si les nœuds doivent être sélectionnés
Richard Grin SGBDOO page 106
Exemple
Richard Grin SGBDOO page 107
Pilotes dont le nom est MS :
Query query = db.query();query.constrain(Pilot.class);query.descend("name").constrain("MS");ObjectSet<Pilot> result = query.execute();
(Image et exemple du tutoriel en ligne sur db4o)
Exemple plus complexe
Query query = db.query();query.constrain(Pilot.class);Constraint constr =query.descend("name").constrain("MS");
query.descend("points").constrain(new Integer(20)).greater().or(constr);
Richard Grin SGBDOO page 108
19
Configuration de db4o
Richard Grin SGBDOO page 109
Configuration de db4oIl est possible de changer certains comportements de db4o avec des méthodes de la classe EmbeddedConfigurationIl faut commencer par récupérer une instance de Configuration (ne pas utiliser la même configuration pour plusieurs ouvertures) :EmbeddedConfiguration config =
Db4oEmbedded.newConfiguration();
Richard Grin SGBDOO page 110
Configuration de db4oAprès avoir modifié la configuration, on la passe à l’ouverture de la BD parEmbeddedDb4o.openFile(config, "fichier.data");
Richard Grin SGBDOO page 111
Profondeur d’activation
Elle indique quels objets attachés à un objet retrouvé par une requête, seront chargés en mémoireUne profondeur de 1 indique que seul l’objet retrouvé sera chargé en mémoire ; les objets associés seront remplacés par null dans l’objet retrouvé
Richard Grin SGBDOO page 112
Imposer une profondeur d’activationLa valeur par défaut est 5 lors d’une interrogation de la baseOn peut la changer globalement par config.activationDepth(profondeur)
ou pour tous les objets d’une classe parconfig.common().objectClass(UneCl.class).minimumActivationDepth(profondeur);config.common().objectClass(UneCl.class).maximumActivationDepth(profondeur);
Rappel (voir section « Recherche par l’exemple ») : on peut aussi activer les membres d’un objet à une certaine profondeur
Richard Grin SGBDOO page 113
Activation des objets référencés
config.common().objectClass(UneCl.class).cascadeOnActivate(true);
config.common().objectClass(UneCl.class).objectField("champ").cascadeOnActivate(true);
Richard Grin SGBDOO page 114
20
Profondeur de modification
Pour de meilleures performances, storen’enregistre dans la BD que les modificationsfaites sur l’objet passé en paramètre (profondeur 1)Les modifications effectuées sur les objets référencés par l’objet ne seront pas prises en compte
Richard Grin SGBDOO page 115
Configuration de laprofondeur de modification
Il est possible de modifier ce comportement :nmise à jour des objets référencés : config.common().objectClass(UneClasse.class).cascadeOnUpdate(true)
n profondeur de 2 :config.common().objectClass(UneClasse.class).updateDepth(2)
Rappel : le plus souple est souvent d’utiliser la variante de store qui prend en paramètre la profondeur de modification
Richard Grin SGBDOO page 116
Index
Pour les grands ensembles de données, il est possible d’accélérer des requêtes en indiquant que des index devront être construits sur certains champs :config.common().objectClass("UneClasse").objectField("UnChamp").indexed(true)
Richard Grin SGBDOO page 117
Concurrence
Richard Grin SGBDOO page 118
Niveau d’isolation
Il n’est pas possible de choisir un autre niveau que le niveau read committed
Richard Grin SGBDOO page 119
Gestion des collisions
Gestion optimiste, par exemple en utilisant peekPersisted pour vérifier au dernier moment si on a eu raison d’être optimiste (le code vérifie certaines données n’ont pas été modifiées par une autre transaction depuis le début du traitement)Gestion pessimiste, par l’application car il n’est pas possible de bloquer des données dans la BD
Richard Grin SGBDOO page 120
21
Gestion pessimiste
Il faut utiliser des sémaphores liés à db4o pour créer des sections critiques dans le codeUn sémaphore est repéré par un nom (de type String)Les sections de code critiques doivent être encadrées par les appels des méthodes de ExtObjectSemaphoreboolean setSemaphore(nom, timeout)et void releaseSemaphore(nom)
Richard Grin SGBDOO page 121
Sémaphores
Le 2ème paramètre de la méthode setSemaphore indique combien de millisecondes attendre qu’une autre transaction relâche le semaphoreLa méthode renvoie true si le code possédait déjà le sémaphore ou s’il a pu l’acquérir dans le délai indiqué ; elle renvoie false sinonUn sémaphore est relâché par un appel à releaseSemaphore ou lorsque l’objectContainer est fermé
Richard Grin SGBDOO page 122
Protection d’un objet
Il est possible d’utiliser plusieurs sémaphoresPour protéger un objet, une astuce est d’utiliser un sémaphore dont le nom contient l’identificateur de l’objet (obtenu par objectContainer.getId())
Richard Grin SGBDOO page 123
Exempleif (extObjectContainer.
setSemaphore(sem, 1000)) {// début section critique...// fin section critiqueextObjectContainer.releaseSemaphore(sem);
} else {// Traitement de la collision.// rollback ?
}
Richard Grin SGBDOO page 124
Gestion des versions
Richard Grin SGBDOO page 125
Refactoring automatique
db4o sait prendre en charge les modifications suivantes :n ajouter une interface à une classen supprimer un champ dans une classen ajouter un champn changer le type d’un champn renommer un champn renommer une classe
Richard Grin SGBDOO page 126
22
Supprimer/ajouter un champ
Il n’y a rien à faireLes données déjà enregistrés dans la base (avec l’ancienne définition) seront récupérées sous la forme d’objets de la nouvelle définition ; l’ancien champ sera ignoréIdem pour l’ajout ; les anciennes données seront récupérées comme des objets de la nouvelle classe ; le nouveau champ aura la valeur null ou 0
Richard Grin SGBDOO page 127
Renommer un champ ou une classe
Il faut lancer une commande (une seule fois) pour que db4o soit au courant de la modificationconfiguration.common().objectClass("p.class").rename("nouvPaquetage.nouvClasse")configuration.common().objectClass("p.class").objectField("ancienChamp").rename("nouvChamp")
Richard Grin SGBDOO page 128
Changer le type d’un champ
db4o ajoute un nouveau champL’ancien champ est conservé et la base peut alors fonctionner avec les 2 versions de la classe (jusqu’à la prochaine défragmentation de la base)Il faut écrire un programme qui recopie les anciennes données (avec conversion de type) dans le nouveau champ db4o
Richard Grin SGBDOO page 129
Exemple pour changer le type d’un champ
L’exemple (tiré du manuel de référence de db4o) montre comment récupérer les noms de pilotes qui sont dans un champ nomCe champ nom était avant de type String et il devient du type Identite
Richard Grin SGBDOO page 130
Exemple pour changer le type d’un champ
public class Identite {private String nom; private String id; public Identity(String nom, String id) {this.nom = nom;this.id = id;
}public void setNom(String nom) {this.nom = nom;
}public void setId(String id) {this.id = id;
} Richard Grin SGBDOO page 131
Exemple pour changer le type d’un champ
StoredClass cl = container.ext().storedClass("p.Pilote");
StoredField ac = cl.storedField("nom", String.class); Query q = container.query();q.constrain(Pilote.class); ObjectSet result = q.execute(); for (int i = 0; i< result.size(); i++){
Pilote pilot = (Pilote)result.get(i);pilote.setNom(new Identite(ac.get(pilote).toString(),""));
container.store(pilote);}
Richard Grin SGBDOO page 132
23
Problèmes avec db4o
Richard Grin SGBDOO page 133
Manque de fonctionnalités
Le code de l’application doit prendre en charge des fonctionnalités qui sont remplies par les SGBDR :n pas de contraintes de clé primaire et de
référence – l’application doit faire attention à ne pas dupliquer les objets
n pas de blocage des objets de la BD –l’application doit créer des sections critiques
Richard Grin SGBDOO page 134
Optimisation des requêtes natives
Impossible dès que la requête est trop complexeIdem le moteur SQL des premiers temps des SGBDR (améliorations à venir, comme pour les moteurs des SGBDR ?)
Richard Grin SGBDOO page 135
Classes particulières
Certaines classes du JDK utilisent des champs transient pour fonctionnerPar exemple Calendar, BigInteger ou BigDecimal
Les champs transient reçoivent leur valeur lors de l’exécution du constructeurCes classe posent des problèmes à db4o qui n’utilise pas les constructeurs des classes pour construire en mémoire centrale les objets récupérés depuis la base de données
Richard Grin SGBDOO page 136
Configuration spéciale pour la persistance (1)
Une configuration spéciale est indispensable pour la sauvegarde des classes qui utilisent des champs transientLe problème est compliqué par le fait que l’implantation de ces classes a été modifiée dans les différentes versions du JDKEt de plus db4o a lui-même changé sa façon de résoudre le problème suivant les versions
Richard Grin SGBDOO page 137
Configuration spéciale pour la persistance (2)
2 solutions possibles (à tester sur chaque classe particulière) :n avant la lecture dans la base de données, indiquer
à db4o qu’il faut passer par un constructeur pour créer les objets de ces classesconfiguration.common().objectClass(Calendar.class).callConstructor(true);
n avant l’écriture dans la base de données, indiquer à db4o qu’il faut enregistrer dans la base les champs transientsconfiguration.common().objectClass(BigDecimal.class).storeTransientFields(true);
Richard Grin SGBDOO page 138
24
Configuration spéciale pour la persistance (3)
Dans ses versions récentes, db4o résout le problème d’une autre façon, avec un handlerqui traite certains types d’une façon particulièrePour prendre en compte BigDecimal et Biginteger, il faut écrire le code suivant :configuration.common().add(new BigMathSupport());
Pour chaque JDK et version de db4o la façon de résoudre le problème est différente !
Richard Grin SGBDOO page 139
Problème avec le cache
Quelquefois une requête ne rend pas ce qui est dans la BDEn effet, l’ObjectContainer utilise un cache des objets qu’il a déjà utilisés et les renvoie s’ils sont concernés par une requêteDans l’exemple suivant, le nouvel âge de Sophie Dupond n’a pas été enregistré dans la base malgré ce que le résultat de la requête pourrait laisser croire
Richard Grin SGBDOO page 140
Exemple de problème 1/2
// Récupère Monsieur DupondList<Personne> liste = bd.query(new Predicate<Personne>() { public boolean match(Personne p) {
return p.getNom().equals("Dupond") && p.getSexe().equals("M");
} });
Personne p = liste.get(0);Personne sophie = p.getEpouse();
Richard Grin SGBDOO page 141
Exemple de problème 2/2
// Sophie avait 25 ans; elle passe à 26 ans sophie.setAge(sophie.getAge() + 1); // Enregistre modifications sur Mr Dupondbd.store(p); bd.commit(); // Est-ce que âge de Sophie est OK ?// Affiche 26 alors que c’est 25 dans BDsophie = (Personne)db.queryByExample(new Personne("Sophie", "Dupond")).next();
System.out.println(sophie.getAge());
Richard Grin SGBDOO page 142
Éviter ce problème
Il faut utiliser refresh :sophie = (Personne)db.queryByExample ( new Personne("Sophie","Dupond")).next();
bd.refresh(sophie);// Affiche 25 et pas 26System.out.println(sophie.getAge());
Richard Grin SGBDOO page 143
top related