Persistance des objets « Perdre la mémoire c'est perdre son identité » J.J Rousseau Jean-Jacques LE COZ Abstraction Presque toutes les applications ont besoin de données persistantes dans le temps. La persistance est un des concepts majeurs du génie logiciel. Sans persistance, après l'arrêt des machines, les systèmes sont souvent inexploitables. Introduction Une des tâches les plus critiques pour les applications Sauver et restaurer les informations La persistance est la mémorisation des données depuis la mémoire vers des supports de stockage afin qu'elles soient restaurées quand l'application est de nouveau exécutée Sources de persistance Sources de persistance Les fichiers plats Les fichiers organisés Organisation séquentielle Organisation indexée, relative Les bases de données Base de données orientée objet Base de données relationnelle Base de données relationnelle et objet Base de données XML La source majeure de la persistance Bases de données relationnelles Largement adoptées par l'industrie Standardisées Flexibles Robustes Données partagées par des applications hétérogènes Maturité Modèle relationnel Développé par Edgar Codd (1970) Données représentées par des tables Relations définies par des clefs primaires et étrangères Accès aux données par un langage de haut niveau non procédural : SQL Sépare la représentation logique et la représentation physique des données Les SGBDR (rdbms) Technologie basée sur des concepts mathématiques Nombreux éditeurs Un langage commun IBM, Oracle, Sybase, Informix, Ingres, MySQL, PostgreSQL, SAPDB, ... Structured Query Language ( SQL ) Nombreuses interfaces de programmation Les SGBDR (suite) Fleuron de la technologie dans les années 70 et 80. Beaucoup de recherche et développement Stockage organisation gestion de données structurées Concurrence et intégrité Partage Persistance et orienté objet Orienté objet et persistance Il y a plusieurs façons de rendre persistants les objets Le choix d'une méthode de persistance est une part importante de la conception d'une application Sérialisation Bases de données La persitance des objets Un objet encapsule un état La persitance doit permettre de mémoriser cet état La persitance doit permettre, plus tard, de recréer un objet avec cet état Plus largement, la persistance doit permettre de mémoriser et de re-créer un graphe d'objets Graphe d'objets sauvegarder une facture son adresse leclient une facture une facture persistance par navigation Persistance des objets avec les SGBDR Relationnel et orienté objet Le but de la conception orientée objet est de modéliser un processus Le but de la conception des bases de données relationnelles est la normalisation Mapping Objet-Relationnel TABLES DANS LE SGBDR OBJETS EN MEMOIRE Paradigmes objet et relationnel Non concordance des paradigmes Le paradigme de l'orienté objet Le paradigme relationnel Le type des acteurs sont les classes Le type des acteurs sont les tables Inadéquation Impedance mismatch Problème d'identité Le paradigme de l'orienté objet L'identité est attachée à l'objet (OID) Gérée par l'environnement d'exécution Le paradigme relationnel L'identité est une caractéristique du tuple Colonne de type clef primaire Contrainte de clef primaire gérée par le système (unicitée, pas de valeur nulle) Souvent source d'une optimisation physique Mécanisme d'indexation Problème de relation Le paradigme de l'orienté objet Les relations peuvent être mono ou bidirectionnelles Les relations passent par l'identité des objets Le paradigme relationnel Les relations sont mono-directionnelles Les relations passent par les clefs étrangères Une clef étrangère référence une clef primaire Contrainte d'intégrité référentielle Contrainte de clef étrangère gérée par le système Exemple Exemple (suite) Implémentation dans le langage Java : public class Client { private String nom; private String adresse; private Facture[ ] factures; } private class Facture { private int numero; private double montant; private Client client; } Exemple (suite) Implémentation dans le langage SQL : create table client ( ) nom VARCHAR(20) PRIMARY KEY, adresse VARCHAR(60) NOT NULL create table facture ( ) numero INTEGER PRIMARY KEY, montant float NOT NULL, nomclient VARCHAR(20) FOREIGN KEY REFERENCES client Inadéquation plus pertinente Lorsque le modèle objet est plus complexe Graphe d'objets persistants Problème de granularité Exemple de l'orienté objet : Solution relationnelle adresse comme table avec des colonnes spécialisées solution peu courante Autre solution relationnelle solution plus courante adresse comme simple colonne ou comme plusieurs colonnes Problème de granularité Le paradigme de l'orienté objet Granularité très souple Le modèle est par nature distribué Le paradigme relationnel Granularité limitée en SQL2 Notamment à cause des performances Extensions SQL3 Les UDT (User Data Table) Non standards Non portables Problème du sous-typage Le paradigme de l'orienté objet Un des concepts majeurs Vecteur du polymorphisme Le paradigme relationnel Non supporté en SQL2 Supporté en partie en SQL3 Pas de polymorphisme Non standard Non portable Solutions de mapping liées au sous-typage Solution horizontale Chaque classe concrète devient une table Solution la plus simple Solution verticale Chaque classe de la hiérarchie mappe vers sa propre table Solution la plus flexible Solution union (filtrée, typée) Toutes les classes mappent vers une seule table Solution qui offre de bonnes performances Exemple de spécialisation Solutions relationnelles SOLUTION HORIZONTALE SOLUTION VERTICALE SOLUTION UNION Problèmes d'isolation Les bases de données relationnelles fournissent des mécanismes pour isoler leur modèle des applications Haut niveau Vues (views) Bas niveau Les clefs primaires de substitution (surrogate keys) Clefs artificielles souvent auto-incrémentées Aucune concordance avec l'orienté objet L'isolation par les vues applications En lecture seulement, parfois permet la mise à jour mais de façon limitée (non portable) table vue interface table table implémentation Isolation par les clefs surrogate technique <<table>> client colonne clef surrogate colonnes ''métier'' sémantique colonne clef primaire auto-incrémentée colonnes représentant les informations du domaine métier Certaines d'entre elles peuvent (clés naturelles) servir d'argument aux clauses where Isolation par les clefs surrogate insert into table (colonnes métier) values (valeurs); select * from table where colonneMétierUnique = valeurMétier; select projection from table1, table2 where table1.clefPKsurrogate = table2.clefFKsurrogate ... ; colonnes techniques que pour la navigation : prédicats de jointure Problèmes d'isolation Les langages orientés objet fournissent, eux aussi, des mécanismes pour isoler l'implémentation Isolation de l'état Isolation du comportement Encapsulation Interfaces Classes abstraites Aucune concordance avec le relationnel Exemple Le Zoo ne connait que l'interface Pensionnaire Mécanismes de persistance Mécanismes de persistance Orthogonalité vis-à-vis de la persistance Par aspect (aspect programming) Par introspection (reflection) Par enrichissement (enhancement) Par navigation (reachability) Non orthogonalité vis-à-vis de la persistance Par implémentation Par héritage Solutions orthogonales Langage Java Aspect Aspect programming Java Persistence API (JPA), EJB3 Introspection Package reflect et byte code Intergiciels de mapping OR : Hibernate Bases de données objet : DB4O Enrichissement Mécanisme d'enhancement Java Data Object (JDO) Solutions non orthogonales Langage Java Serialization EJB2 Implémentation de l'interface java.io.Serializable Java Architecture for XML Binding (JAXB) Implémentation de l'interface EntityBean Bases de données orientées objet Impémentation par interface et/ou par héritage Poet, ObjectStore, Ozone, ... Solutions intrusives Implémentation de requêtes SQL SQL embarqué Intergiciels de bas niveau ODBC, JDBC, SQLJ Problèmes SQL est non orienté objet SQL, langage de bas niveau dans un langage de haut niveau orienté objet Lourdeurs de programmation avec les graphes d'objets complexes Solutions avec patrons Le patron de conception DAO Pattern Data Access Objects Avec implémentation de requêtes SQL Découple l'accès aux données de la partie métier de l'application Problèmes Solutions complexes Nécessite beaucoup de code Manque de souplesse et de portabilité Pattern DAO Classe Modèle classe persistante Classe ModèleDAO Classe DAO adaptateur indépendance vis-à-vis du modèle SGBDR Solution avec des intergiciels Outils de mapping objet/relationnel Langage Java Standard Java Solutions originales JDO Java Data Object (JSR12 Sun Microsystem) JPA Java Persistence API (JSR220 Sun Microsystem) Nombreux éditeurs Castor Cayenne iBatis Solution par composants Java J2EE EJB EntityBean CMP versions 1, 2, 3 Outils de mapping Fichiers de configuration modèle objet persistant outil de mapping Schéma relationnel caches* * différents niveaux: caches d'objets et/ou de données Mapping et Wrapping (1) Outils de mapping Couche logicielle intermédiaire Entre les objets et les tables Objets Couche de mapping Tables Application Mapping et Wrapping (2) Outils de wrapping Couche logicielle enrobante Exemples : iBatis, Spring JDBC Application Objets Tables Classe persistante avec JPA @Entity @Table(name="ETUDIANT") public class Etudiant { private int id; private String nom; private String prenom; private String adresse; @Id @GeneratedValue public int getId() { return id; } ... } Persistance avec les SGBDOO Modèle de persistance pour les objets Offre la persistance pour les objets Attributs, opérations et associations Spécifié par Atkinson (1989) Standardisé par l'ODMG Object Data Management Group Les SGBDOO définissent les classes d'objets persistants de la même manière que les langages OO Modèle de données objet OBJETS DANS LE SGBDOO OBJETS EN MEMOIRE Base de données objet Mémorise les OID dans l'objet pour indiquer à quels autres objets il est en relation L'OID n'est pas visible Ni par les utilisateurs Ni par les programmeurs Un objet reste le même objet même si son état change complètement Concepts Le fait que l'identité d'un objet ne se confonde pas avec son état signifie que les concepts d'égalité et d'identité sont différents Identité : même OID Égalité : même valeur d'état Différents niveaux d'égalité Égalité superficielle Égalité profonde Représentation des relations Il est possible d'avoir des relations inverses Elles correspondent aux relations bidirectionnelles du modèle objet Les relations inverses renforcent l'intégrité Par exemple Une relation inverse garantie qu'un item commandé est associé à une seule commande Représentation des relations (suite) Seules les relations prédéfinies pour mémoriser les OID des objets en relation peuvent être utilisées pour des requêtes ou naviguer dans la base de données Les SGBDOO n'offrent pas la même souplesse d'interrogation que les SGBDR Les performances des SGBDOO sont meilleures que celles des SGBDR pour la navigation sur les relations Orthogonalité Principes énoncés par Atkinson et Morrison (1995) Indépendance de la persistance Type de donnée orthogonal Les lignes de code sont identiques qu'elles manipulent des objets persistants ou non persistants Les objets sont persistants quel que soit leur type Identification de la persistance Le mécanisme d'identification des objets persistants n'est pas lié aux types Avantages des SGBDOO Objets et relations complexes Hiérarchies de classes Pas d'impedance mismatch Pas de clé primaire Un seul langage Pas de langage de requête Haute performance pour certaines tâches Exemple avec db4O public static void main(String[] args) { ObjectContainer db = Db4o.openFile("BASE.yap"); try { Produit p1 = new Produit("1000", "DUCATI 1098", 17550.55f); db.set(p1); } finally { db.close(); } } Serialization Java et la persistance Un mécanisme simple de persistance est implémenté dans le langage Java Grâce à l'interface java.io.Serializable Et à la gestion des entrées/sorties de flux InputStream, OutputStream Flux d'octets vers un fichier sur disque ou le réseau Possibilité de rendre une donnée membre non persistante Par le mot réservé transient Exemple de Serialization public class Personne implements java.io.Serializable { private String nom; private String prenom; private transient String motdepasse = ''défaut''; public Personne(String nom, String prenom) { this.setNom(nom); this.setPrenom(prenom); } public String getNom() { return nom; } public void setNom(String nom) { this.nom = nom; } public String getPrenom() { return prenom; } public void setPrenom(String prenom) { this.prenom = prenom; } public String getMotdepasse() { return motdepasse; } public void setMotedepasse(String pwd) { motdepasse = pwd; } } Exemple (suite) import java.io.*; public class SauverPersonne { public static void main(String argv[]) { Personne personne = new Personne("Martin","Jean"); personne.setMotdepasse(''azerty''); try { FileOutputStream fichier = new FileOutputStream("personne.data"); ObjectOutputStream oos = new ObjectOutputStream(fichier); oos.writeObject(personne); oos.flush(); oos.close(); } catch (java.io.IOException e) { e.printStackTrace(); } } } Exemple (suite) import java.io.*; public class RestaurerPersonne { public static void main(String argv[]) { try { FileInputStream fichier = new FileInputStream("personne.data"); ObjectInputStream ois = new ObjectInputStream(fichier); Personne personne = (Personne) ois.readObject(); System.out.println("nom : "+personne.getNom()); System.out.println("prenom : "+personne.getPrenom()); System.out.println("prenom : "+personne.getMotdepasse()); } catch (java.io.IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } Bibliographie [Ambler 2001] Ambler Scott, The Design of a Robust Persistence Layer. www.ambysoft.com/persistenceLayer.html [Ambler 2002] Ambler Scott, Mapping Objects to Relational Databases. AmbySoft Inc. www.ambysoft.com/mappingObjects.html [Fussel 1997] Fussel Mark, Foundations of Object Relational Mapping. ChiMu Corporation. www.chimu.com/publications/objectRelational/