Index: topia/doc/PersistenceImplantationJDBC-2.rst diff -u /dev/null topia/doc/PersistenceImplantationJDBC-2.rst:1.1 --- /dev/null Fri Aug 19 16:02:33 2005 +++ topia/doc/PersistenceImplantationJDBC-2.rst Fri Aug 19 16:02:28 2005 @@ -0,0 +1,144 @@ +====================================== +Implantation d'un storage sur JDBC - 2 +====================================== + +:Authors: Benjamin POUSSIN & Arnaud THIMEL +: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.