Implantation d'un storage sur JDBC - 2
Document ajouté sur le CVS pour la nouvelle manière d'implanter la persistence. Voici le contenu : ====================================== Implantation d'un storage sur JDBC - 2 ====================================== :Authors: Benjamin POUSSIN <poussin@codelutin.com> & Arnaud THIMEL <thimel@codelutin.com> :Version: $Revision: 1.1 $ :Date: $Date: 2005/08/19 16:02:28 $ Le problème avec la première implantation ----------------------------------------- Le première version de la persistence JDBC a été réalisée. Elle a mis en avant quelques défauts : - Difficulté pour certaines bases (Postgre / Derby) à convertir les valeurs de la colonne "value" de BLOB à un format numérique (DOUBLE PRECISION principalement). Ces bases nécessitent un CAST explicite (où du moins la création supplémentaire d'un CAST implicite) souvent difficilement réalisable. - La compléxité des requêtes envoyées à la base pour faire les find. Certaines bases s'emmelent les pinceaux avec les requêtes (MySQL en tête !). Exemple de requête générée pour récupérer les Companies visibles par la transaction '1123170253913' dont le nom est 'Code Lutin' : |SELECT DISTINCT id FROM data |WHERE (field='nom' AND value='Code Lutin') |AND (id,longdate) IN ( | SELECT id, min(longdate) FROM management | WHERE (id,longdate) IN ( | SELECT id, max(longdate) FROM management | WHERE class='org.codelutin.test2.entities.Company' | AND (longdate in (-1123170253913) OR (longdate>0 AND longdate<=1123170253913)) | AND id NOT IN ( | SELECT id FROM management | WHERE isDeleted=true | AND (longdate in (-1123170253913) OR (longdate>0 AND longdate<=1123170253913)) | ) | GROUP BY id | UNION | SELECT id, longdate FROM management | WHERE class='org.codelutin.test2.entities.Company' | AND isDeleted=false | AND longdate in (-1123170253913) | ) | GROUP BY id |) La solution ----------- On se propose donc de changer la manière dont les informations sont stockées et de se rapprocher d'une implantation plus conventionnelle : On génère pour chaque entité un schéma de table qui lui est propre. Etant donné que les nom d'entité (et encore plus des classes d'associations générées) peut être très long, on crééra un nom de table pour chaque table. On aura donc autant de tables que d'entités, plus une table management, dont le rôle sera de faire l'association entre le nom des entités et le nom de la table associée pour une version de schéma donnée. Dans le première version, la table management recenssait toutes les entités à un instant précis avec leut état à cet instant. (classe, new, deleted, schemaVersion). On souhaite toutefois conserver ces informations. Elle seront donc toutes rajoutées dans les tables générées à l'exception de la classe et du schemaVersion (car dans management). Pour qu'il n'y ait pas d'ambiguïté avec les champs propres à l'entité, on préfixera ces champs du caratère '_'. Le nom des tables sera le nom de l'entité (sans le package) suivi du schemaVersion. Pour les classes d'associations générées (non comprises dans le modèle au départ), le nom étant trop grand, on ne prendra que la fin des noms des entités (avec le nom des attributs) suivies du schemaVersion. (cf. exemple plus bas) Le passage à une nouvelle version pour une entité sera effectué de la manière suivante : 1. On charge en mémoire toute la table actuelle ; 2. On supprime la table actuelle ; 3. On créé la nouvelle table ; 4. On convertit tous les objets remontés ; 5. On sauve tous les objets convertis dans la nouvelle table. Pour une relation entre Company et Employee (dont la classe d'association ne fait pas initialement partie du modèle), on obtient ainsi quatre tables : Company123456 : - _id : String (topiaId) - _longdate : long - nom : String - adresse : String - _isNew : boolean - _isDeleted : boolean Employee789012 : - _id : String (topiaId) - _longdate : long - nom : String - age : int - sexe : char - _isNew : boolean - _isDeleted : boolean Employee_company__Company_employee827923283 : - _id : String (topiaId) - _longdate : long - company : String (topiaId) - employee : String (topiaId) - _isNew : boolean - _isDeleted : boolean management - class : String (fullyQualifiedName) - table : String - schemaVersion : long Le contenu de la table management sera : +-------------------------------------+---------------------------------------------+----------------+ | class | table | schemaVersion | +=====================================+=============================================+================+ | org.codelutin.test2.Company | Company123456 | 123456 | +-------------------------------------+---------------------------------------------+----------------+ | org.codelutin.test2.Employee | Employee789012 | 789012 | +-------------------------------------+---------------------------------------------+----------------+ | org.codelutin.[...]Company_employee | Employee_company__Company_employee827923283 | 827923283 | +-------------------------------------+---------------------------------------------+----------------+ Conclusion ---------- Une telle persistence ne devrait à priori pas pauser de problème avec la grande majorité des bases de données. Elle simplifiera la lisibilité brute de la base, permettra la génération de reqêtes plus simples, et une maniulation des données plus aisée. Cependant, en se rapprochant d'un schéma de stockage de données plus classique, on s'expose aux mêmes problèmes que les solutions précedemment écartées telles que JDO.
participants (1)
-
Arnaud Thimel