r2261 - in trunk/topia-persistence/src/site: . rst rst/devel rst/user
Author: bleny Date: 2011-04-16 18:41:18 +0200 (Sat, 16 Apr 2011) New Revision: 2261 Url: http://nuiton.org/repositories/revision/topia/2261 Log: replace messy user doc by incomplete tutorial Added: trunk/topia-persistence/src/site/rst/devel/ trunk/topia-persistence/src/site/rst/devel/Devel.rst trunk/topia-persistence/src/site/rst/devel/HibernateMapping.rst trunk/topia-persistence/src/site/rst/devel/Isolation.rst trunk/topia-persistence/src/site/rst/devel/SchemaMigration.rst trunk/topia-persistence/src/site/rst/devel/Todo.rst trunk/topia-persistence/src/site/rst/devel/event.rst trunk/topia-persistence/src/site/rst/devel/project.rst trunk/topia-persistence/src/site/rst/devel/security.rst trunk/topia-persistence/src/site/rst/index.rst trunk/topia-persistence/src/site/rst/user/ trunk/topia-persistence/src/site/rst/user/FAQ.rst trunk/topia-persistence/src/site/rst/user/ModelGeneration.rst trunk/topia-persistence/src/site/rst/user/TopiaQuery.rst trunk/topia-persistence/src/site/rst/user/continue_devel.rst trunk/topia-persistence/src/site/rst/user/extend_model.rst trunk/topia-persistence/src/site/rst/user/howto.rst trunk/topia-persistence/src/site/rst/user/start.rst trunk/topia-persistence/src/site/rst/user/start_using_api.rst trunk/topia-persistence/src/site/rst/user/tagvalues.rst Removed: trunk/topia-persistence/src/site/rst/Devel.rst trunk/topia-persistence/src/site/rst/FAQ.rst trunk/topia-persistence/src/site/rst/HibernateMapping.rst trunk/topia-persistence/src/site/rst/Isolation.rst trunk/topia-persistence/src/site/rst/ModelGeneration.rst trunk/topia-persistence/src/site/rst/SchemaMigration.rst trunk/topia-persistence/src/site/rst/Todo.rst trunk/topia-persistence/src/site/rst/TopiaQuery.rst trunk/topia-persistence/src/site/rst/event.rst trunk/topia-persistence/src/site/rst/howto.rst trunk/topia-persistence/src/site/rst/index.rst trunk/topia-persistence/src/site/rst/project.rst trunk/topia-persistence/src/site/rst/security.rst trunk/topia-persistence/src/site/rst/tagvalues.rst Modified: trunk/topia-persistence/src/site/site_fr.xml Deleted: trunk/topia-persistence/src/site/rst/Devel.rst =================================================================== --- trunk/topia-persistence/src/site/rst/Devel.rst 2011-04-16 16:25:22 UTC (rev 2260) +++ trunk/topia-persistence/src/site/rst/Devel.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -1,170 +0,0 @@ -.. - -.. * #%L -.. * ToPIA :: Persistence -.. * -.. * $Id$ -.. * $HeadURL$ -.. * %% -.. * Copyright (C) 2004 - 2010 CodeLutin -.. * %% -.. * This program is free software: you can redistribute it and/or modify -.. * it under the terms of the GNU Lesser General Public License as -.. * published by the Free Software Foundation, either version 3 of the -.. * License, or (at your option) any later version. -.. * -.. * This program is distributed in the hope that it will be useful, -.. * but WITHOUT ANY WARRANTY; without even the implied warranty of -.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.. * GNU General Lesser Public License for more details. -.. * -.. * You should have received a copy of the GNU General Lesser Public -.. * License along with this program. If not, see -.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. -.. * #L% -.. - -TopiaContextFactory -=================== - -Le topia context est créé en faisant la demande sur le *TopiaContextFactory*. -On peut passer en paramètre au *TopiaContextFactory* un object *Property* qui -permet de configurer le context. Si aucun fichier est passé en paramètre, un fichier de -propriété **TopiaContextImpl.properties** est recherché dans le classpath. - -Fichier de configuration -======================== - -Le fichier de configuration est un fichier lisible par un objet *Property*. -Il contient différentes informations : -- liste des entités à gérer -- option de connexion à la base de données -- les services à activer - -Liste des entités à gérer -------------------------- - -Il est possible de définir les entités soit directement en indiquant un -répertoire contenant les mappings hibernate:: - - topia.persistence.directories=<path> - -soit en indiquant une liste de classe séparé par des virgule:: - - topia.persistence.classes=<list de classe> - -Le mieux est d'utiliser la liste de classe qui est non spécifique à une -persistence ou à une plateforme. - -Option de connexion à la base de données ----------------------------------------- - -Hibernate -~~~~~~~~~ - -Les options pour hibernate peuvent être directement dans le fichier de configuration principal ou dans un fichier de configuration secondaire. Dans ce cas il faut indiquer dans le fichier de configuration principal le chemin de ce fichier:: - - topia.persistence.properties.file=<filesystem or classpath path> - -Les options hibernates sont les options hibernate classique : - -- hibernate.connection.username -- hibernate.connection.password -- hibernate.dialect -- hibernate.connection.driver_class -- hibernate.connection.url - -Les services à activer ----------------------- - -Il est possible d'indiquer les services à activer grâce aux options:: - - topia.service.<service name>=<class> - topia.service.security=org.nuiton.topia.security.TopiaSecurityServiceImpl - topia.service.index=org.nuiton.topia.index.LuceneIndexer - topia.service.history=org.nuiton.topia.history.TopiaHistoryServiceImpl - -<service name> doit correspondre au nom de service que <class> retourne, sinon il est désactivé. - -Les services disponibles actuellement sont: - -- Service d'indexation full text -- Service d'historisation des modifications des entités -- Service de sécurité -- Service d'upgrade automatique des données hibernates - -TopiaContext -============ - -Le *TopiaContext* permet de récupérer les services, d'ouvrir des transactions -en récupérant des nouveaux *TopiaContext* fils, de s'enregistrer en tant que -listener pour recevoir les notifications de modification sur les entités. - -Sur les *TopiaContext* fils, on peut récupérer des DAO qui permettent de -créer, modifier, rechercher les entités. - -Entité -====== - -Normalement **Topia** est fait pour pouvoir générer n'importe quel type de POJO -et les rendre persistants. Mais il est plus simple d'utiliser la génération -de code fournit avec **Topia** pour générer les entités à partir d'un -diagramme UML. Dans ce cas toutes les entités héritent de *TopiaEntity* qui -contient des méthodes pour s'enregistrer sur les modifications des attributs -ou pouvoir lever un droit de veto sur une modification. Sont aussi -disponible les méthodes: - -- getTopiaId -- getTopiaVersion -- getTopiaCreationDate -- getTopiaContext -- getComposite: Retourne tous les objets qui seront effacé si cet objet est effacé -- getAggregate: Retourne les objets en lien avec celui-ci - -Lorsque l'on utilise la génération on peut implanter une classe qui hérite -du *Abstract* généré et qui se finisse par Impl. Par exemple si dans notre -modèle nous avons la classe *Toto* il sera généré une interface *Toto* et -une classe abstraite *TotoAbstract*, il faudra alors implanter *TotoImpl*:: - - extends TotoAbstract extends TopiaEntityAbstract implements Toto - extends TopiaEntityAbstract implements *TopiaEntity - -Cette classe impl permet d'ajouter des méthodes métiers à l'entité ou des -méthode d'accès différent sur les attributs. - -DAO -=== - -Il n'y a plus qu'un seul type de persistence possible pour les DAO, à savoir Hibernate (depuis la 2.2.0). Il est possible d'étendre un DAO -pour lui ajouter différentes méthodes plus complexes ou plus spécifiques que celles proposées par défaut : - -- findAll -- findAllByProperties(Map<String, Object> properties) -- findAllByProperties(String param, Object property, ...) -- findByProperty(String property) -- tous les find pour chaque property existante de l'entité -- ... - -Pour spécifier d'autres méthodes, il suffit d'utiliser directement le modèle UML qui sert à la génération des entités. -Un stéréotype <<dao>> doit être précisé sur une méthode d'entité pour indiquer qu'elle doit se situer dans un DAO. -Le fichier *DAOImpl* associé ne sera plus généré et devra être créé par le développeur en héritant du *DAOAbstract*. -(voir FAQ pour un exemple sur l'extension d'un DAO). - -Note sur les signatures de méthodes - Par commodité, les méthodes retournant une liste d'entités commencent par findAllBy tandis que celles retournant une seule entité - commencent par findBy. - -TopiaService -============ - -Pour implanter un TopiaService il faut absolument créer une interface qui -hériter de l'interface *TopiaService* et mettre dans cette interface un -attribut static qui définit le nom du service:: - - public static final String SERVICE_NAME = "monservice"; - -Un service peut avoir besoin de nouvelles entités pour fonctionner. Pour cela -il faut retourner la liste des entités grâce à la méthode -**getPersistenceClasses**. - -Après instanciation du service par le **TopiaContext** celui-ci est -initialisé grâce à la méthode **init(TopiaContextImplementor)**. Il peut -alors se mettre listener sur le context ou les DAO par exemple. Deleted: trunk/topia-persistence/src/site/rst/FAQ.rst =================================================================== --- trunk/topia-persistence/src/site/rst/FAQ.rst 2011-04-16 16:25:22 UTC (rev 2260) +++ trunk/topia-persistence/src/site/rst/FAQ.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -1,124 +0,0 @@ -.. - -.. * #%L -.. * ToPIA :: Persistence -.. * -.. * $Id$ -.. * $HeadURL$ -.. * %% -.. * Copyright (C) 2004 - 2010 CodeLutin -.. * %% -.. * This program is free software: you can redistribute it and/or modify -.. * it under the terms of the GNU Lesser General Public License as -.. * published by the Free Software Foundation, either version 3 of the -.. * License, or (at your option) any later version. -.. * -.. * This program is distributed in the hope that it will be useful, -.. * but WITHOUT ANY WARRANTY; without even the implied warranty of -.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.. * GNU General Lesser Public License for more details. -.. * -.. * You should have received a copy of the GNU General Lesser Public -.. * License along with this program. If not, see -.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. -.. * #L% -.. - -=== -FAQ -=== - -Problème lors du chargement d'une entity -======================================== - -Le chargement utilise les méthodes Set des propriétés, il faut donc faire -attention si on les surcharge. - -Il faut faire attention lors de l'ajout, sur l'entity, de méthodes qui ont la -même signature que des méthods Set de propriétés avec juste des arguments -différents, car elles peuvent être utilisées à la place de la vrai méthode -pour quelque valeur (par exemple null). - -Faire fonctionner les Web Services Topia via RMI -================================================ -L'utilisation des Web Services sur RMI impose la génération de classes sauvées -sur disque. -Elle sont construites à la volée et sauvées dans le dossier "./topiagen". - -Ce dossier doit donc se trouver dans le classpath. - -Comment commit (ou rollback) une transaction directement à partir d'un DAO ? -============================================================================ - -Contrairement à ce que l'on pourrait croire aux premiers abords, les méthodes commitTransaction() -et rollbackTransaction() disponibles dans les DAO ne sont pas prévus à cet effet. Il faut toujours -utiliser le contexte pour commit (ou rollback) une transaction. Donc pour le faire à partir d'un DAO : -dao.getContext().commitTransaction() // on récupère le context (transaction sur le DAO) et on commit. -Le principe reste identique pour le rollback. -Pour revenir sur les méthodes commitTransaction() et rollbackTransaction() disponibles sur le DAO, elles -servent de "callback" au moment du commit (ou rollback) de la transaction. Le context se chargera d'appeler -tous les commitTransaction() des DAO, ceci afin de permettre un traitement spécifique au DAO au moment du commit. -Ce traitement peut donc être effectué directement à partir du dao via cette méthode sans passer par le context. - -Comment étendre un DAO avec d'autres méthodes spécifiques ? -=========================================================== - -Il est possible d'étendre un DAO avec des méthodes définies à partir du modèle -(méthode différente entre version 2.2 et 2.4). - -Il suffit de créer une interface contenant les méthodes à ajouter au dao. -Cette interface doit avoir le stéréotype <<dao>>. De plus l'interface doit -dépendre (lien de dépendance nommé explicitement 'dao') de la classe de l'entité. -Le DAOImpl ne sera pas généré et devra être défini à la charge du développeur. - -Exemple (présent dans topiatest.zargo dans les sources de topia-persistence) : - -Ajout d'une méthode findAllByCompany sur une entité Contact. Chaque société à un ensemble d'employés (Employee) qui ont des -contacts (Tel, Adresse, ...). Ces contacts ne sont pas unique à chaque employé. Il peut être intéressant de connaître directement -tous les contacts d'une société directement avec le DAO:: - - public class ContactDAOImpl<E extends Contact> extends ContactDAOAbstract<E> { - - @Override - public Set<Contact> findAllByCompany(Company company) throws TopiaException { - ... - } - - } - -Une erreur de compilation apparaîtra si ce fichier n'existe pas (car non généré). La signature de la méthode -est présente dans le DAOAbstract (ici ContactDAOAbstract), d'où le @Override. - -Note - L'ajout du throws TopiaException est automatique et n'a pas besoin d'être spécifié au niveau du modèle. - -Comment gérer une clé métier sur une entité (naturalId) ? -========================================================= - -Chaque entité possède une cré primaire topiaId, mais dans certains cas il est -important d'avoir une notion d'unicité sur une ou plusieurs propriétés d'une -entité, ce qu'on appele une clé métier. Le comportement souhaité serait de -préserver l'unicité sur ces propriétés ainsi que la création d'un index pour -optimiser l'accès aux données. - -Il est donc nécessaire de préciser cette notion au niveau du modèle, cela -par le biais du tagValue (également propriété hibernate) **naturalId** :: - - fr.ird.observe.entities.referentiel.ParametrageTaillePoidsFaune.class.tagvalue.naturalIdMutable=false - fr.ird.observe.entities.referentiel.ParametrageTaillePoidsFaune.attribute.sexe.tagvalue.naturalId=true - fr.ird.observe.entities.referentiel.ParametrageTaillePoidsFaune.attribute.ocean.tagvalue.naturalId=true - fr.ird.observe.entities.referentiel.ParametrageTaillePoidsFaune.attribute.ocean.tagvalue.notNull=false - fr.ird.observe.entities.referentiel.ParametrageTaillePoidsFaune.attribute.espece.tagvalue.naturalId=true - -Ici, les propriétés "sexe", "ocean" et "espece" forment la clé métier de -l'entité "ParametrageTaillePoidsFaune". Par défaut les propriétés -d'une clé métier sont non null, mais il est possible de préciser dans certains -cas qu'une propriété peut l'être (comme ici avec "ocean"). - -Le naturalId provoque trois résultats : - -- création d'un index unique en base. -- vérification dans hibernate de l'intégrité de l'entité à la création : - il est donc nécessaire de créer l'entité avec des valeurs pour les propriétés - de la clé métier (méthode create sur le dao). -- impossibilité de modifier les valeurs de ces propriétés sur une entité - existante ; à moins de le préciser dans la configuration via le tagValue - "naturalIdMutable" placé à "true" (déconseillé). Deleted: trunk/topia-persistence/src/site/rst/HibernateMapping.rst =================================================================== --- trunk/topia-persistence/src/site/rst/HibernateMapping.rst 2011-04-16 16:25:22 UTC (rev 2260) +++ trunk/topia-persistence/src/site/rst/HibernateMapping.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -1,120 +0,0 @@ -.. - -.. * #%L -.. * ToPIA :: Persistence -.. * -.. * $Id$ -.. * $HeadURL$ -.. * %% -.. * Copyright (C) 2004 - 2010 CodeLutin -.. * %% -.. * This program is free software: you can redistribute it and/or modify -.. * it under the terms of the GNU Lesser General Public License as -.. * published by the Free Software Foundation, either version 3 of the -.. * License, or (at your option) any later version. -.. * -.. * This program is distributed in the hope that it will be useful, -.. * but WITHOUT ANY WARRANTY; without even the implied warranty of -.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.. * GNU General Lesser Public License for more details. -.. * -.. * You should have received a copy of the GNU General Lesser Public -.. * License along with this program. If not, see -.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. -.. * #L% -.. - -================= -Mapping hibernate -================= - -Ce document décrit les choix de mapping faits en fonction -du diagramme de classe UML. - -JDBC -==== - -Généralité ----------- - -- Tous les objets utilisent le versionnement dans un champs version:: - - <version name="topiaVersion" type="long" node="@topiaVersion"/> - -- On utilise les méthodes d'accès pour accêder aux propriétés - -Héritage --------- - -- Seules les classes concrêtes ont un mapping (au travers de l'interface + impl) -- Chaque classe à un fichier de mapping séparé. - -On utilisera union-subclass - -Identifiant ------------ - -Lors de la description de la classe, on peut indiquer de ne pas générer de clé -technique. Dans ce cas, la clé métier est utilisée (tagvalue: technicalKey=false). -Par défaut une clé technique est utilisée et est de la forme uuid.hex:: - - <id name="topiaId" column="topiaId" type="string"> - <generator class="uuid.hex"/> - </id> - -La description de la clé métier est faite par un tagvalue sur la classe -(tagvalue: key=prop1,prop2,prop3). Si une clé technique est utilisée, une -contrainte d'unicité est tout de même faite sur la clé métier. - -La clé métier sert aussi pour le toString, equals, hashCode. - -Si l'id d'une entité est composé de plusieurs champs, ces champs doivent-être -rassemblés dans une classe indépendante de l'entité. Par contre le mapping -assemble l'entity et son id dans la même table:: - - <composite-id name="#field" class="#class"> - <key-property name="#field1" column="#col1"/> - <key-property name="#field2" column="#col2"/> - <key-property name="#field3" column="#col3"/> - </composite> - -Si l'id est un objet simple il peut être directement mis dans l'entité. - -Relation 1-0 ------------- - - - -Relation 1-1 ------------- - -Relation 0-N ------------- - -Relation 1-N ------------- - -Relation N-N ------------- - -Classe d'association --------------------- - -Composition ------------ - -Le composant peut changer de propriétaire (set méthode) mais le -propriétaire perd en même temps le lien vers son composé. - -Aggregation ------------ - -Si une classe est aggrégée avec une autre, alors elle suit la vie de l'entité -à laquelle elle est aggrégée (cascade delete, update) - -Elle ne peut pas être affectée a une autre entité. Pas de set sur cette classe -vers l'autre classe. - -XML -=== - -Toutes les propriétés sont des éléments sauf la clé technique qui est un -attribut. Deleted: trunk/topia-persistence/src/site/rst/Isolation.rst =================================================================== --- trunk/topia-persistence/src/site/rst/Isolation.rst 2011-04-16 16:25:22 UTC (rev 2260) +++ trunk/topia-persistence/src/site/rst/Isolation.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -1,92 +0,0 @@ -.. - -.. * #%L -.. * ToPIA :: Persistence -.. * -.. * $Id$ -.. * $HeadURL$ -.. * %% -.. * Copyright (C) 2004 - 2010 CodeLutin -.. * %% -.. * This program is free software: you can redistribute it and/or modify -.. * it under the terms of the GNU Lesser General Public License as -.. * published by the Free Software Foundation, either version 3 of the -.. * License, or (at your option) any later version. -.. * -.. * This program is distributed in the hope that it will be useful, -.. * but WITHOUT ANY WARRANTY; without even the implied warranty of -.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.. * GNU General Lesser Public License for more details. -.. * -.. * You should have received a copy of the GNU General Lesser Public -.. * License along with this program. If not, see -.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. -.. * #L% -.. - -=========================== -Isolation des TopiaContexts -=========================== - - -Remarque: les requètes ne sont pas bonnes, mais sont là pour donner l'idée -générale. - -Pour mettre en place l'isolation entre les différents TopiaContexts créés par -beginTransaction, il faut ajouter un nouvelle propriété sur les -TopiaEntity: TopiaContextId. Cette propriété prend la valeur de l'id du -TopiaContext qui a créé ou chargé l'objet. On voit donc que plusieurs objets -ayant le même id peuvent exister, le TopiaContextId doit donc faire partie -de la clé de l'objet. Il faut aussi ajouter un champs TopiaDeleted pour -savoir si un objet a été effacé ou non. - -Dans le mapping hibernate pour chaque class d'entité, on a un filtre: -where TopiaContextId == :id || (TopiaContextId > 0 && TopiaContextId <= :id) - -Ce filtre n'est pas suffisant car on a toutes les versions commités de -l'objet jusqu'a :id, il faut un autre filtre apres les recherches pour -n'avoir que les dernieres versions des entites et supprimer dans ce groupe -les entitées marquées et effacées. -where TopiaContextId = max(TopiaContextId) && isDeleted=false group by topiaId - -Lors d'un beginTransaction le nouveau TopiaContext active ce filtre pour son -propre id. - -De cette manière un TopiaContext ne voit que les objets qu'il a créé et/ou -modifié, ou les objets plus ancien que lui. - -Cet Id est: - System.nanoTime() et donc toujours négatif. - -Lors d'un commit d'un TopiaContext, on passe tous les TopiaContextId de -toutes les entités qui sont égales a l'id du TopiaContext en sa version -positive: update <table> set TopiaContextId = -:id where TopiaContextId = :id -De plus le TopiaContext renouvelle son id et modifie tous les filtres pour -qu'il aie la vision d'objets créés par d'autre TopiaContext avant son commit. - -Lors d'un rollback il suffit de faire le renouvellement de l'id et la mise à -jour des filtres. - -Sous-transaction -================ - -La gestion des TopiaContextId pourrait offrir les sous-transactions, si -dans le filtre on ajoutait comme condition, au lieu de TopiaContextId == :id, -TopiaContextId in (:idList) ou idList serait la liste des ids du -TopiaContext courant ainsi que des TopiaContext parents. - -Historisation -============= - -La gestion des TopiaContextId permet d'offrir l'historisation de tous les -objets. Car tous les objets commités sont conservés avec un TopiaContextId -différent pour chaque version. - -Implantation -============ - -- Mettre en place les champs supplémentaires: TopiaContextId, TopiaDeleted -- Modifier la clé primaire pour ajouter TopiaContextId -- Ajouter les filtres dans les mappings -- Ajouter un id sur les TopiaContext -- Modifier le comportement de DAO.delete pour qu'il marque juste l'objet - comme effacé sans l'effacer TopiaDeleted=true -- Pour toutes les recherches ajouter un filtre pour ne retourner que les - derniere version non deleted Deleted: trunk/topia-persistence/src/site/rst/ModelGeneration.rst =================================================================== --- trunk/topia-persistence/src/site/rst/ModelGeneration.rst 2011-04-16 16:25:22 UTC (rev 2260) +++ trunk/topia-persistence/src/site/rst/ModelGeneration.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -1,111 +0,0 @@ -.. - -.. * #%L -.. * ToPIA :: Persistence -.. * -.. * $Id$ -.. * $HeadURL$ -.. * %% -.. * Copyright (C) 2004 - 2010 CodeLutin -.. * %% -.. * This program is free software: you can redistribute it and/or modify -.. * it under the terms of the GNU Lesser General Public License as -.. * published by the Free Software Foundation, either version 3 of the -.. * License, or (at your option) any later version. -.. * -.. * This program is distributed in the hope that it will be useful, -.. * but WITHOUT ANY WARRANTY; without even the implied warranty of -.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.. * GNU General Lesser Public License for more details. -.. * -.. * You should have received a copy of the GNU General Lesser Public -.. * License along with this program. If not, see -.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. -.. * #L% -.. - -Génération des modèles ----------------------- - - -Le module "topia-persistence" de topia est capable de -générer la persistence à partir d'un modèle UML. - -Nous allons détailler ici comme inclure la génération dans le -cycle de compilation maven. - - -Architecture maven ------------------- - -+---------------------------------+-----------------------------------------+ -| src/main/xmi/mymodel.zargo | exemple de modele UML avec argoUML | -+---------------------------------+-----------------------------------------+ -| src/main/xmi/mymodel.properties | fichier de propriétés attaché au modele | -+---------------------------------|-----------------------------------------+ - - -Configuration du pom.xml ------------------------- - -Pour générer les sources dans la phase "generate-sources" de maven, et utiliser -les sources générées, et faut configurer le pom. - -Plugin eugene -============= - -:: - -<plugin> - <groupId>org.nuiton.eugene</groupId> - <artifactId>maven-eugene-plugin</artifactId> - <!-- la version peut être plus récente --> - <version>1.0.0</version> - <executions> - <execution> - <id>Generator</id> - <phase>generate-sources</phase> - <configuration> - <srcDirUml>src/main/xmi</srcDirUml> - <srcXmiDest>target/generated-sources/xmi/</srcXmiDest> - <fullPackagePath>org.company.package</fullPackagePath> - <extractedPackages>org.company.package</extractedPackages> - <srcGenDest>target/generated-sources/objectmodel/</srcGenDest> - <includes>**/*.objectmodel</includes> - <templates>org.nuiton.topia.generator.TopiaMetaGenerator</templates> - <destDirGen>target/generated-sources/java</destDirGen> - <defaultPackage>org.company.package</defaultPackage> - </configuration> - <goals> - <goal>zargo2xmi</goal> - <goal>xmi2objectmodel</goal> - <goal>generate</goal> - </goals> - </execution> - </executions> - <dependencies> - <dependency> - <groupId>org.nuiton.topia</groupId> - <artifactId>topia-persistence</artifactId> - <!-- la version peut être plus récente --> - <version>2.2.0</version> - <scope>runtime</scope> - </dependency> - </dependencies> -</plugin> - -Pour plus d'information à propos d'eugene, merci de consulter le site : -http://maven-site.nuiton.org/eugene/ - -Dépendances du projet -===================== - -Il faut enfin ajouter "topia-persistence" en dépendance du projet : - -:: - -<dependency> - <groupId>org.nuiton.topia</groupId> - <artifactId>topia-persistence</artifactId> - <!-- la version peut être plus récente --> - <version>2.2.0</version> - <scope>compile</scope> -</dependency> Deleted: trunk/topia-persistence/src/site/rst/SchemaMigration.rst =================================================================== --- trunk/topia-persistence/src/site/rst/SchemaMigration.rst 2011-04-16 16:25:22 UTC (rev 2260) +++ trunk/topia-persistence/src/site/rst/SchemaMigration.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -1,137 +0,0 @@ -.. - -.. * #%L -.. * ToPIA :: Persistence -.. * -.. * $Id$ -.. * $HeadURL$ -.. * %% -.. * Copyright (C) 2004 - 2010 CodeLutin -.. * %% -.. * This program is free software: you can redistribute it and/or modify -.. * it under the terms of the GNU Lesser General Public License as -.. * published by the Free Software Foundation, either version 3 of the -.. * License, or (at your option) any later version. -.. * -.. * This program is distributed in the hope that it will be useful, -.. * but WITHOUT ANY WARRANTY; without even the implied warranty of -.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.. * GNU General Lesser Public License for more details. -.. * -.. * You should have received a copy of the GNU General Lesser Public -.. * License along with this program. If not, see -.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. -.. * #L% -.. - -===================================== -Comment migrer d'un schéma à un autre -===================================== - - -Une application modifie et ajoute des objets. La persistence doit donc être -adaptée à ces changements. Le problème est la migration des données -existantes dans le nouveau schéma. - -Voici quelques idées d'implantations. - -Hibernate et dynamic-map -======================== - -Hibernate permet de mapper les objets de la base de données dans des -dynamic-map. Nous n'avons donc pas besoin de pojo pour les représenter, il -nous suffit d'avoir le mapping hibernate. - -L'idée est donc, lors de la modification de schéma, de regrouper tous les -anciens mapping dans un seul fichier de mapping qui contiendra le numero de -version du schema. - -On utilisera ces mappings pour charger l'ancienne configuration et ainsi les -réenregistrer dans le nouveau schéma. - -Une classe java de migration devra être écrite pour transformer les données -d'un schéma vers un autre schéma. - -Avantage --------- - -Le changement de schéma est fait en java - -Désavantage ------------ - -Il faut dans la base une table qui indique dans quelle version de schéma -actuelle est la base (Topia->schemaVersion). -Une autre solution est de faire une base -par version, le numero de version étant dans le nom de la base (inconveniant : -le nom de la base change a chaque version). -Une autre solution possible est de faire un -changement de schéma dans une transaction, donc on peut lire les anciennes -données dans une transaction et on écrit les nouvelles dans une autre -transaction sur la même table mais qui aurait des schéma différents. - -Il faut, dans les noms des tables, le numéro de version du schéma pour que les -les anciennes tables ne servent pas comme nom pour les nouvelles. - -Il faut soit faire l'aggrégation des mapping dans un seul fichier, soit -n'utiliser qu'un seul fichier pour les mappings, soit avoir un fichier par -classe et par version, mais il est moins simple de retrouver tous les -fichiers de mapping et surtout moins simple - -En fait il n'y a pas vraiment de desavantage. La solution parrait simple et -efficace. - -Exemple de classe de conversion -------------------------------- - -:: - - class Convert { - convert() { - // recherche de la version actuelle de la base topia->schemaVersion - // recherche de la version utilisé par l'application config->schemaVersion - // si les versions divergent, appel de toutes les méthodes convert - // pour arriver à la version de schema actuelle dans config - } - - convert_2_0_1_to_2_0_2(){ - // chargement schema 2_0_1 en utilisant les dynamic-map - // chargement schema 2_0_2 en utilisant les dynamic-map - ... - // code de migration d'un schema a un autre - // si pas de modification pour une classe, il faut au moins faire une - // copie pour remplir les nouvelles tables - ... - // modification de version dans topia->schemaVersion - // commit nouvelle données - // on peut supprimer les anciennes tables - } - - convert_2_0_2_to_2_1_0(){ - // idem - } - } - -Hibernate et XML -================ - -Il est aussi possible de lire une base en XML. On utiliserait donc la même -technique que pour les dynamic-map, mais on utiliserait du XSL pour -convertir le XML vers le schéma souhaité. De cette facon il n'y a pas besoin -de table intermédiaire ni de numéro de version de schéma dans les tables. - -- Export XML en utilisant le vieux mapping -- converion en enchainant les transformations XSL -- Import du nouveau fichier XML - -Inconvéniant ------------- - -si le volume est important il peut-etre long de tout transformer en XML. - -Kettle -====== - -Une autre idee est de ne pas utiliser hibernate mais kettle pour la -migration des données. Nous aurions de la même façon dans le nom des tables -un numero de version de schéma. Un fichier kettle decrirait la migration -d'une version à une autre. Et les différents fichiers serait chaînés pour -arriver au schéma souhaité. Deleted: trunk/topia-persistence/src/site/rst/Todo.rst =================================================================== --- trunk/topia-persistence/src/site/rst/Todo.rst 2011-04-16 16:25:22 UTC (rev 2260) +++ trunk/topia-persistence/src/site/rst/Todo.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -1,255 +0,0 @@ -.. - -.. * #%L -.. * ToPIA :: Persistence -.. * -.. * $Id$ -.. * $HeadURL$ -.. * %% -.. * Copyright (C) 2004 - 2010 CodeLutin -.. * %% -.. * This program is free software: you can redistribute it and/or modify -.. * it under the terms of the GNU Lesser General Public License as -.. * published by the Free Software Foundation, either version 3 of the -.. * License, or (at your option) any later version. -.. * -.. * This program is distributed in the hope that it will be useful, -.. * but WITHOUT ANY WARRANTY; without even the implied warranty of -.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.. * GNU General Lesser Public License for more details. -.. * -.. * You should have received a copy of the GNU General Lesser Public -.. * License along with this program. If not, see -.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. -.. * #L% -.. - -==== -TODO -==== - -Recherches à faire ------------------- - -- des persistences hibernates sur LDAP ou FlatFile -- des outils de migration/evolution de schema - -Generic DAO ------------ -http://www.hibernate.org/328.html:: - - public abstract class GenericHibernateDAO<T> { - ... - Class<T> persistentClass = (Class<T>) ((ParameterizedType) getClass() - .getGenericSuperclass()).getActualTypeArguments()[0]; - - -Regarder si TopiaContext ne pourrait pas être remplacé par un PicoContainer -http://www.hibernate.org/180.html -http://www.hibernate.org/182.html - -doc sur l'optimisation des requetes HQL -http://www.jroller.com/page/wakaleo/?anchor=hibernate_optimisation - -Generation ----------- - -- (2) import/export XML dans ToPIA, à mettre dans le mapping hibernate (en partie fait, mais très stable...) - - -Gestion des versions des POJO ------------------------------ - -mettre en place serialVersionUID sur les entités - -Gestion des droits et de la sécurité ------------------------------------- - -Le créateur de l'objet n'est pas dans l'objet lui même mais dans une table a -part. - -Owner: topiaId de l'entity, id du propriétaire - -Les droits des objets sont dans une table a part -(voir http://www.hibernate.org/140.html). - -Il serait bon que les droits s'appliquent sur un group ou un user. Et qu'un user -puisse appartenir a un group, et qu'un group puisse aussi appartenir a un group - -Il faut aussi modifier le Policy ou autre pour pouvoir lire les permissions -dans hibernate lorsqu'on nous les demandes. Mettre des méthodes statique dans -une classe contenant une session hibernate statique pour permettre l'ajout -de permission a l'execution, sans qu'on est besoin de relire toutes les -permissions a chaque fois, la session servant de cache (mais les sessions -ne sont pas multithread d'ou le synchronise) - -synchronized public void addPermission(TopiaPermission); -synchronized public List<TopiaPermission> getAllPermission(); - -Entity directement dans Topia ------------------------------ - -- User: login, password, email -- Group: name, (User|Group)* -- Permission: action(create, load, update, delete, admin permission), classname, - principal, topiaId de l'entity ou null si le droit sur toutes les entites de ce type - - -Les services ------------- - -..image: ServiceCall.png - -Les services on besoin d'avoir le context de l'appelant pour pouvoir faire -des choix: -- choix de la base de données -- droit de l'utilisateur -- ... - -Pour cela le premier argument de chaque methode generee doit etre un token -retourner par le service d'authentification. - -Le service d'authentification (LA/SSO?) permet de recuperer les informations -du TopiaClientContext qui contient des informations utiles: -- applicationId (identifiant de l'application appelant (im.codelutin.com, im.libre-entreprise.com, ...)) -- clientId (identifiant du client appelant (gaim, exodus, gabber, ...)) -- userLogin -- userPassword - -On a un TopiaServiceManager qui permet de recuperer un proxy sur le service -souhaité. Le proxy n'a pas en premier argument ce TopiaClientContext, il est -ajouté automatiquement lors de l'appel. De cette maniere cote client cela -est completement transparent. - - -# Cote client -ChoremServiceHelper csh = ChoremServiceHelper.getInstance("codelutin.chorem.com", "mentawai", "poussin", "xxxxxxxx"); -CRMService crm = csm.getCRMService(); // retourne un proxy sur le service -List<Person> persons = crm.getAllPerson(); // retourne la liste de toutes les personnes visible par poussin - -# Cote serveur dans getAllPerson(String token) -TopiaClientContext tcc = TopiaAuthenticationService.getTopiaClientContext(token); -Properties prop = ChoremUtil.getContextProperties(tcc); -ChoremContext context = ChoremContext.getContext(prop); -List<Person> result = ChoremDAOHelper.getCRMDAO(context).getAllPerson(); -return result; - -Le moyen de recuperer le TopiaAuthentificationService doit etre specifier -dans les fichiers de configuration de l'application. Il doit y avoir -plusieurs implantation pour ce service: -- class avec methode static pour les applications standalone -- EJB -- service web -- ... - -L'application doit pouvoir plugger sa propre methode d'authentification -(acces a un LDAP, a une BD, a un Liberty Alliance, ...), chaque implantation -doit utiliser cette methode d'authentification (delegation). - -De meme pour l'implantation des services, les services doivent être des -classes Java normal (sans le token en parametre) mais contenant une methode -setTopiaContext() qui permet de mettre a jour - - -Autre ------ - -- tag-value transaction sur les operations des services avec les valeurs - traditionnelles de la spec EJB (required, requiresNew, mandatory, - supports, notSupported, never ). ex auto=required -- dernier user ayant modifié une entité -- tag-value auto avec un pattern sur les attributs. ex auto=now -- tag-value mask avec un pattern sur les attributs. ex : mask=price - puis dans les fichiers de traductions : price=#+,## -- tag-value enumName avec un pattern sur les attributs. ex : - enum=projectStatus - La valeur des énumérations est conservé dans un fichier de configuration - qui peut-etre surchargé par des valeurs dans une table en base de - données : projectStatus=a faire, fait, fini -- tag-value i18n avec un pattern sur les attributs. ex : i18n=true (en partie fait :) ) -- Generation des UI par defaut (JAXX et JSP) -- prendre en compte le contenu de l'onglet doc des entités et attributs - jusqu'au -- pour les tooltips (doc tooltips/doc user/doc dev) - -A reflechir (voir si c vraiment utile) --------------------------------------- -- pouvoir monitorer un attribut (user, date, oldValue, new Value) - Ces attributs ont une valeur tagguée versioned à vrai ou faux. - -> getHistory[Attribut]():list<History> - -Amélioration templates ----------------------- - -- préférer définir des variables plutôt que d'injecter du code dans les templates : - -Example : - -avant - -:: - - /*{table="<%=GeneratorUtil.getDBName(attr.getDeclaringElement()) + "_" + getName(attr)%>"*/ - - -après - -:: - - String dbName = GeneratorUtil.getDBName(attr.getDeclaringElement()) + "_" + getName(attr); - -ou - -:: - - String attrName = getName(attr); - String dbName = GeneratorUtil.getDBName(attr.getDeclaringElement()); - - /*{table="<%=dbName+"_"+attrName%>"}*/ - -- mettre une javadoc pour dire ce que la méthode va faire - -- incorporer des tests unitaires de génération :) - -- créer des constantes pour les stereotypes tagValues et les utiliser... - -- aller à la chasse aux constantes (exemple propertiesPattern dans DAOAbstractGenerator) - -- faire la chasse au code inutilisé - -- ajouter hasTagValue sur ObjectModelElement dans lutingenerator - -- réfléchir comment générer les imports pour ne plus utilisers les FQN - -- vérifier les javadocs générées (ajouter les exceptions,...) - -- reussir a résoudre les casts dans les DAOAbstraxct sur la méthode getEntityClass - -- réusiner les codes de génération d'attributs : - -:: - - String lazy = " lazy=\""; - if (notEmpty(attr.getTagValue(GeneratorUtil.TAG_LAZY))){ - lazy += attr.getTagValue(GeneratorUtil.TAG_LAZY); - } else { - lazy += "true"; - } - lazy += "\""; - -mais il ya d'autres cas à prévoir... : - -:: - - String fetch = ""; - if (notEmpty(attr.getTagValue(GeneratorUtil.TAG_FETCH))){ - fetch = " fetch=\"" + attr.getTagValue(GeneratorUtil.TAG_FETCH) + "\""; - } - -- Dans lutingenerator, renommer Util en GeneratorUtil et dans ToPIA, - GeneratorUtil en TopiaGeneratorUtil - -- supprimer les les boucles sur Iterator quand c'est possible et utiliser pluot des for-each - -- étudier la nécessité des GeneratorUtil.toLowerCaseFirstLetter(assocAttrName) présents dans EntityAbstractGenerator à propos des classes d'assoc - -- TODO Check wether this method could be used to generate getter and setters - -- Uniformiser et faire hériter les générateurs des interfaces et classe d'impl pour que le générateur de la classe d'impl soit capable de générer aussi l'interface Deleted: trunk/topia-persistence/src/site/rst/TopiaQuery.rst =================================================================== --- trunk/topia-persistence/src/site/rst/TopiaQuery.rst 2011-04-16 16:25:22 UTC (rev 2260) +++ trunk/topia-persistence/src/site/rst/TopiaQuery.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -1,543 +0,0 @@ -.. - -.. * #%L -.. * ToPIA :: Persistence -.. * -.. * $Id$ -.. * $HeadURL$ -.. * %% -.. * Copyright (C) 2004 - 2010 CodeLutin -.. * %% -.. * This program is free software: you can redistribute it and/or modify -.. * it under the terms of the GNU Lesser General Public License as -.. * published by the Free Software Foundation, either version 3 of the -.. * License, or (at your option) any later version. -.. * -.. * This program is distributed in the hope that it will be useful, -.. * but WITHOUT ANY WARRANTY; without even the implied warranty of -.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.. * GNU General Lesser Public License for more details. -.. * -.. * You should have received a copy of the GNU General Lesser Public -.. * License along with this program. If not, see -.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. -.. * #L% -.. - -TopiaQuery -========== - -:Author: Florian Desbois -:Contact: topia-devel@list.nuiton.org ou topia-users@list.nuiton.org -:Revision: $Revision$ -:Date: $Date$ - -L'objet TopiaQuery permet de créer plus simplement des requêtes HQL pour éviter -les concaténations complexes lors de l'utilisation de la méthode **find** -du TopiaContext. - -Chacune des parties de la requête sont indépendantes et seront concaténés au -moment de l'exécution. Il est donc possible d'ajouter des éléments à la -requête à n'importe quel moment de sa construction (from, select, where, order, -group, ...). - -La TopiaQuery peut donc être construite à un endroit et exécutée à un autre. -Une même requête peut également être réutilisée pour être passée en sous-requête -ou exécutée plusieurs fois à la suite avec certains légers changement de -paramètres. - -.. contents:: - -Modèle exemple --------------- - -Ci-dessous un modèle simple utilisé pour les exemples de cette documentation. - -.. image:: modelForTopiaQuery.png - -Instantiation -------------- - -La TopiaQuery nécessite obligatoirement une entité référence pour être exécutée. -Cette entité correspondra à l'élément principal du FROM de la requête et si -nécessaire sera ajouté automatiquement au SELECT. - -Il y a plusieurs façons d'instancier la TopiaQuery : - -Directement depuis un DAO :: - - TopiaContext transaction = rootContext.beginTransaction(); - BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); - TopiaQuery query = dao.createQuery(); - -ou depuis un topiaContext :: - - TopiaContext transaction = rootContext.beginTransaction(); - TopiaQuery query = transaction.createQuery(Boat.class, "B"); - -L'intérêt de passer par un DAO est de pouvoir par la suite executer la requête -avec ce même DAO. Il est également possible d'utiliser des alias pour l'élément -principal de la requête pour pouvoir plus facilement gérer les cas de jointure. -Il suffit de préciser l'alias au moment de l'instanciation :: - - TopiaContext transaction = rootContext.beginTransaction(); - BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); - TopiaQuery query = dao.createQuery("E"); - -Ajout d'éléments au WHERE -------------------------- - -Les méthodes de base nécessaires concernent l'ajout d'élements dans le WHERE de la -requête. Plusieurs méthodes sont disponibles suivant les besoins pour ajouter -simplement un élément au where :: - - TopiaQuery query = boatDAO.createQuery(); - - // Recherche sur l'immatriculation du navire : immatriculation = 142154 - query.addEquals("immatriculation", 142154); - - // Recherche toutes les dates de construction < 2006 - query.addWhere("buildYear", Op.LT, 2006); - - // Recherche des navires ayant un nom - query.addNotNull("name"); - - // depuis 2.3.4 - // Recherche des navires n'ayant pas de nom - query.addNull("name"); - - // Recherche des navires ayant une date de construction 2003, 2004 ou 2006 - query.addEquals("buildYear", 2003, 2004, 2006); - - // depuis 2.3.4 - // Recherche entre deux dates - TopiaQuery queryContact = contactDAO.createQuery(); - Calendar dateBegin = new GregorianCalendar(2010,2,3); - Calendar dateEnd = new GregorianCalendar(2010,5,6); - queryContact.addBetween("creationDate", dateBegin.getTime(), dateEnd.getTime()); - - // depuis 2.3.4 - // Utilisation d'une sous-requête (les paramètres de la sous-requête seront - // ajoutés automatiquement à la requête principale en gérant les doublons - // (sur la valeur et la clé)). - // Le ? correspond à l'endroit ou sera injecté la requête, attention aux - // parenthèses. - queryContact.addSubQuery("boat IN elements(?)", query); - -Il est fortement conseillé d'utiliser les constantes des entités pour les noms -de leurs propriétés :: - - query.addEquals(Boat.IMMATRICULATION, 142154); - query.addNotNull(Boat.NAME); - ... - -La TopiaQuery peut être chaînée, les méthodes permettant l'ajout d'éléments -renvoient toutes la même TopiaQuery avec l'élément ajouté :: - - TopiaContext transaction = rootContext.beginTransaction(); - BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); - dao.createQuery().addEquals(Boat.IMMATRICULATION, 142154).addNotNull(Boat.NAME); - -Opérateurs ----------- - -Une enum interne à la TopiaQuery permet de manipuler les opérateurs nécessaires -aux ajouts dans le WHERE : - -- TopiaQuery.Op.EQ : Opérateur = -- TopiaQuery.Op.GT : Opérateur > -- TopiaQuery.Op.GE : Opérateur >= -- TopiaQuery.Op.LIKE : Opérateur LIKE -- TopiaQuery.Op.LT : Opérateur < -- TopiaQuery.Op.LE : Opérateur <= -- TopiaQuery.Op.NOT_NULL : Opérateur IS NOT NULL -- TopiaQuery.Op.NULL : Opérateur IS NULL -- TopiaQuery.Op.NEQ : Opérateur != - -Autres parties de la requête ----------------------------- - -Ajout d'élément au FROM -~~~~~~~~~~~~~~~~~~~~~~~ - -Il est souvent nécessaire d'ajouter une autre entité au FROM de la requête, -pour ce faire, il existe deux méthodes : - -- addFrom(Class entityClass) : ajoute une entité au FROM - (Ex : addFrom(Contact.class);) - -- addFrom(Class entityClass, String alias) : ajoute une entité au FROM avec un - alias (Ex : addFrom(Contact.class, "C");) - -C'est généralement la dernière méthode qui sera la plus utilisé, l'utilisation -des alias facilitant grandement les liaisons entre les entités. - -Depuis la 2.3.4, deux méthodes ont été rajoutés pour le cas des jointures : - -- addJoin(Class entityClass, String alias, boolean fetch) : utilise un inner - join pour lier une entité à celle de la requête. Concrètement l'opérateur - JOIN Hql sera utilisé : 'FROM Contact C JOIN C.boat' :: - - TopiaContext transaction = rootContext.beginTransaction(); - ContactDAO dao = ModelDAOHelper.getBoatDAO(transaction); - TopiaQuery query = dao.createQuery("C").addJoin("C.boat", null, false); - -- addLeftJoin(Class entityClass, String alias, boolean fetch) : même chose que - le addJoin sauf que l'opérateur LEFT JOIN Hql sera utilisé. - - -Voir le `Chargement des donnees` pour l'utilisation du fetch. - -Ajout d'élément au SELECT -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Deux méthodes sont disponibles pour le cas du SELECT, une méthode addSelect -qui se chargera d'ajouter une propriété au SELECT, et une méthode setSelect -qui définira directement quel est le SELECT souhaité. Pour le cas du addSelect, -la méthode gère automatiquement l'entité principale utilisé pour instancier -la requête, il n'est donc pas nécessaire de l'ajouter manuellement. - -TODO : find an example - -Le setSelect quant à lui est utilisé pour les aggregations par exemple ou -pour récupérer des parties précises du résultat :: - - TopiaContext transaction = rootContext.beginTransaction(); - BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); - // On souhaite connaître le nombre de résultats uniquement - TopiaQuery query = dao.createQuery(). - addNotNull(Boat.NAME). - setSelect("COUNT(*)"); - -autre exemple :: - - // On souhaite récupérer uniquement les noms des navires - TopiaQuery query = dao.createQuery(). - addNotNull(Boat.NAME). - setSelect(Boat.NAME); - -Note - Pour l'ajout d'une contrainte sur l'unicité des résultats, vous pouvez - utiliser la méthode addDistinct() qui permet l'ajout du mot clé DISTINCT sur - le SELECT de la requête. - -Ajout d'élément au GROUP BY -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Dans certains cas, il peut être nécessaire d'utiliser un GROUP BY -pour les aggregations :: - - TopiaContext transaction = rootContext.beginTransaction(); - ContactDAO dao = ModelDAOHelper.getContactDAO(transaction); - // On souhaite connaître le nombre de contacts par navire - TopiaQuery query = dao.createQuery(). - setSelect("COUNT(*)"). - addGroup(Contact.BOAT); - -Ajout d'élément au ORDER BY -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Il est possible également d'ajouter un ordre aux résultats :: - - TopiaContext transaction = rootContext.beginTransaction(); - BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); - // Tous les noms des navires triés - TopiaQuery query = dao.createQuery(). - addNotNull(Boat.NAME). - setSelect(Boat.NAME). - addOrder(Boat.NAME); - -Une autre méthode est disponible pour l'ordre descendant : addOrderDesc. -Cependant rien ne vous interdit la syntaxe suivante :: - - addOrder(Boat.NAME, Boat.BUILD_YEAR + " desc"); - -Requête complexe ----------------- - -L'intérêt majeur de la TopiaQuery est de pouvoir la manipuler à travers des -méthodes tout en lui ajoutant des éléments suivant certaines conditions. -Il peut être également utile d'utiliser une TopiaQuery comme sous-requête d'une -autre. De plus certains mots clés comme EXISTS ou encore l'utilisation de -méthode HQL ne possèdent pas leurs propres méthodes. Vous pouvez cependant -utiliser la méthode de base **addWhere(String str)** qui permet l'ajout au WHERE -directement (avec ajout automatique des parenthèses). Dans ce cas, il est -souvent nécessaire d'ajouter des paramètres HQL à la requête (:monParam) qui -devront être ajouté à la TopiaQuery en utilisant la méthode -**addParam(String name, Object value)**. Ex :: - - TopiaContext transaction = rootContext.beginTransaction(); - ContactDAO dao = ModelDAOHelper.getContactDAO(transaction); - Date beginDate = ... - Date endDate = ... - TopiaQuery query1 = dao.createQuery("C"). - addWhere("C." + Contact.VALIDATION + " IS NOT NULL OR " + - "C." + Contact.CREATION_DATE + " BETWEEN :begin AND :end"). - addParam("begin", beginDate).addParam("end", endDate); - -La méthode **fullQuery()** permettra de récupérer la requête sous forme -de chaîne pour pouvoir la manipuler comme sous-requête. Il est possible -également de récupérer les paramètres via la méthode **getParams()** pour -les rajouter à la requête global :: - - // suite du code précédent - // On souhaite la date de création la plus récente sur la requête précédente - query1.setSelect("MAX(C." + Contact.CREATION_DATE + ")"); - - // Préparation de la deuxième requête - TopiaQuery query2 = dao.createQuery("C2"); - - // sélection spécifique pour un navire - if (immatriculation != null) { - query2.addEquals("C2." + Contact.BOAT + "." + Boat.IMMATRICULATION, - immatriculation); - - // Ajout d'une condition sur le navire dans la première requête - query1.addWhere("C." + Contact.BOAT + " = C2." + Contact.BOAT); - } - - // Utilisation de la première requête comme sous-requête - query2.add("C2." + Contact.CREATION_DATE + " = (" + query1.fullQuery() + ")"); - // Ajout des paramètres nécessaires de la première requête dans la deuxième - query2.addParams(query1.getParams()); - -Depuis la 2.3.4, la méthode **addSubQuery(String statement, TopiaQuery subquery)** -permet de faciliter l'injection d'une sous-requête notamment pour la gestion -des paramètres automatiquement (avec prise en charge des doublons) :: - - // Même chose que précédemment en utilisant la méthode addSubQuery - query2.addSubQuery("C2." + Contact.CREATION_DATE + " = (?)", query1); - -La requête sous forme HQL :: - - SELECT C2 FROM Contact C2 - WHERE C2.boat.immatriculation = :immatriculation - AND C2.creationDate = (SELECT MAX(C.creationDate) FROM Contact C - WHERE (C.validation IS NOT NULL OR - C.creationDate BETWEEN :begin AND :end) - AND C.boat = C2.boat); - -Attention - Il ne faut pas utiliser la méthode addEquals(String str, Object value) pour - une comparaison entre deux propriétés comme précédemment : - *query1.addWhere("C." + Contact.BOAT + " = C2." + Contact.BOAT)*. - L'appel *query1.addEquals("C." + Contact.BOAT, "C2." + Contact.BOAT)* ne - fonctionnera pas comme souhaité. - -Résultats ---------- - -Plusieurs méthodes sont disponibles pour récupérer les résultats de la requête. -Pour chaque méthode, il est nécessaire de l'appeler avec le contexte -topia. La méthode de base est la méthode execute() qui renvoie -une liste non typé à l'instar de la méthode find(...) du TopiaContext. Il -est cependant possible de récupérer directement un objet, un entier (pour -un aggregat par exemple) ou une chaîne de caractères suivant le select de la -requête. Pour le count très utile dans de nombreux cas, il est mis à disposition -la méthode **executeCount()** qui se chargera de remplacer temporairement le -select par un COUNT(*). L'avantage c'est que votre requête ne perd pas son -SELECT d'origine pour pouvoir être par exemple executé de façon différente par -la suite. - -Note - Si la requête contient un DISTINCT (via la méthode addDistinct()), le - executeCount() gèrera automatiquement la contrainte sur la requête : - "SELECT COUNT(DISTINCT B) FROM Boat B ..." - -Limitation des résultats -~~~~~~~~~~~~~~~~~~~~~~~~ - -Il est possible de limiter le nombre de résultats lors de l'exécution pour -optimiser la requête dans le cas d'une pagination par exemple. Pour ce faire -il faut utiliser les méthodes **setLimit(int start, int end)** et/ou -**setMaxResults(int max)** :: - - // 18 premiers résultats - query.setLimit(0, 17); - // équivalent à - query.setMaxResults(18); - // résultats du 50ème au 60ème - query.setLimit(49, 59); - -// depuis 2.3.4 - -Pour éviter d'embarquer ces paramètres à chaque fois qu'ils sont nécessaires -lors d'un filtrage paginée, un bean, *EntityFilter* est disponible. -Il contient les attributs suivants : - -- startIndex : index de début des résultats. - -- endIndex : index de fin des résultats. - -- orderBy : propriétés à ordonner (l'ajout des mots clés 'asc' et 'desc' est - possible). - -- referenceId : identifiant d'une référence utile à la requête. - -- referenceProperty : nom de la propriété correspondant à la valeur du referenceId. - -Exemple : Nous souhaitons les contacts 30 à 60 triés par 'creationDate' décroissant et -'personName' croissant pour un navire donné par son topiaId :: - - EntityFilter filter = new EntityFilter(); - filter.setStartIndex(30); - filter.setEndIndex(60); - filter.setOrderBy("creationDate desc, personName"); - filter.setReferenceId(boat.getTopiaId()); - // ou filter.setReference(boat); - filter.setReferenceProperty("boat"); - - TopiaQuery query = contactDAO.createQuery().addFilter(filter); - -L'intérêt de l'EntityFilter est de pouvoir l'instancier et le manipuler directement -depuis votre interface (Swing, Web, ...) et de l'utiliser sur une requête métier. -La méthode **addFilter(EntityFilter filter)** permettra d'injecter les paramètres -s'ils possèdent une valeur. - -Note - L'ordre définit par défaut est celui de création par ordre décroissant : - *topiaCreateDate desc*. - -Utilisation des DAO -~~~~~~~~~~~~~~~~~~~ - -Les DAO fournissent également quelques méthodes permettant de récupérer plus -facilement les résultats avec le type souhaité : - -- **countByQuery(TopiaQuery query)** : compte le nombre de résultats de la - requête. -- **existByQuery(TopiaQuery query)** : renvoie vrai si la requête à retourner - au moins 1 résultat. -- **findByQuery(TopiaQuery query)** : renvoie une entité (un seul résultat) -- **findAllByQuery(TopiaQuery query)** : renvoie une liste d'entités -- **findAllMappedByQuery(TopiaQuery query)** : renvoie une map d'entités avec - pour clé le topiaId de l'entité. -- **findAllMappedByQuery(TopiaQuery query, Class keyClass, String keyProperty)** : - renvoie une map d'entités avec pour clé la propriété passée en argument. - -Exemple :: - - TopiaContext transaction = rootContext.beginTransaction(); - BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); - TopiaQuery query = dao.createQuery(); - ... - // pour vérifier l'existance de résultat - boolean hasResult = dao.existByQuery(query); - - // pour savoir le nombre de résultats - int count = dao.countByQuery(query); - - // pour récupérer les résultats - Map<String, Boat> boatMap = dao.findAllMappedByQuery(query); - // ou - List<Boat> boatList = dao.findAllByQuery(query); - // ou juste le premier résultat - Boat boat = dao.findByQuery(query); - // ou avec pour clé l'immatriculation du navire (unique) - Map<Integer, Boat> boatMapImma = dao.findAllMappedByQuery(query, - Integer.class, Boat.IMMATRICULATION); - - -Résultats complexes -~~~~~~~~~~~~~~~~~~~ - -Certains cas de requête peuvent avoir des résultats plus complexes, notamment -lorsqu'il s'agit de propriétés de différentes entités ou avec l'utilisation d' -aggrégats (AVG, SUM, COUNT). Dans ce cas il faut utiliser la méthode de base -**findByQuery(TopiaQuery query)** depuis une transaction -qui renverra une liste non typée. Lorsqu'il y a plus d'un élément dans le -select la liste renvoyée est une List<Object[]>, le tableau pour chaque ligne -correspondant aux valeurs des résultats. Exemple :: - - TopiaContext transaction = rootContext.beginTransaction(); - ContactDAO dao = ModelDAOHelper.getContactDAO(transaction); - String boatImma = Contact.BOAT + "." + Boat.IMMATRICULATION; - // On souhaite le nombre de contacts par navire - TopiaQuery query = dao.createQuery(). - setSelect(boatImma, "COUNT(*)").addGroup(boatImma); - - List<Object[]> results = transaction.findByQuery(query); - // Parcours des résultats - for (Object[] result : results) { - Integer immatriculation = (Integer)result[0]; - Long count = (Long)result[1]; - } - -Note - Les aggrégats renvoient principalement un type Long et non Integer. - -Chargement des donnees ----------------------- - -Généralement une fois la requête exécutée, la transaction utilisée est directement -fermée (topiaContext.closeContext()). Dans ce cas, il est souvent nécessaire de -charger certaines entités pour éviter les malencontreuses LazyException d'Hibernate. -Plusieurs possibilités s'offrent à vous : - -Chargement automatique -~~~~~~~~~~~~~~~~~~~~~~ - -Hibernate permet de déclarer explicitement que certaines relations doivent se -charger dès la récupération des entités. Il faut pour cela utiliser le tagValue -*lazy* dans le fichier de properties du modèle. Par exemple pour charger -le navire associé à chaque contact récupéré via une requête, il faut préciser :: - - myapp.entity.Contact.attribute.boat.tagvalue.lazy=false - -(*myapp.entity.Contact* étant le nom qualifié de la classe Contact) - -Ainsi chaque contact récupéré aura automatiquement son navire associé de chargé. - -**Attention** cependant, il ne faut pas abuser du tagvalue *lazy* car sinon Hibernate -risque de charger une bonne partie de votre base de données à chaque fois, ce qui -peut s'avérer extrêment coûteux. Cette utilisation doit être limitée au cas d'une -simple association comme c'est ici le cas, le Boat chargé étant **indispensable** -à l'utilisation du Contact. - -Chargement manuelle -~~~~~~~~~~~~~~~~~~~ - -La TopiaQuery fournit deux méthodes intéressantes pour le chargement manuelle : - - - addLoad(String...) : permet de charger les relations une fois la requête - exécutée. - - - addFetch(String...) : permet de charger les relations directement au moment - de la requête en utilisant une jointure et le mot clé 'FETCH' Hql. - -Le addLoad est pour le moment limité à des relations unitaires (autant que votre -modèle vous le permet, ex : entityA.entityB.entityC) ou à une seule relation -multiple directe ou indirecte (entityA.entitiesB). Si nous prenons le cas du -modèle d'exemple, il est possible de charger le navire associé aux contacts en -utilisant : queryContact.addLoad(Contact.BOAT); - -Dans le cas du addLoad, plusieurs requêtes seront exécutées suivant le nombre -de Contact résultats. Il est dans ce cas plus judicieux d'utiliser le addFetch -qui chargera directement les Boat au moment de la récupération des Contact : -queryContact.addFetch(Contact.BOAT); L'alias peut s'avérer indispensable pour -l'utilisation du addFetch, voir la javadoc pour l'utilisation des arguments. - -Note - Les méthodes de jointures permettent de faire un fetch directement : - addJoin(String property, String alias, boolean fetch); - Voir la partie de la documentation concernant le FROM de la requête. - -Attention - Hibernate ne supporte pas plus de 3 ou 4 jointures suivant leurs complexités ! - Il est donc important de limiter l'utilisation des fetch aux cas simples. - -Que choisir ? -~~~~~~~~~~~~~ - -- Relation unitaire (N-1) obligatoire : utiliser le tagValue *lazy* - -- Requête relativement simple (moins de deux jointures) : utiliser le addFetch - -- Requête complexe : utiliser le addLoad - -- Si addLoad non utilisable (trop de chargement de collections) : effectuer un - chargement manuelle en parcourant les résultats. Pour le chargement d'une - entité simple, il suffit d'utiliser le getter correspondant pour la charger, - tandis que pour une collection, l'appel à la méthode size associée permet de - charger l'intégralité des éléments. - - - Copied: trunk/topia-persistence/src/site/rst/devel/Devel.rst (from rev 2250, trunk/topia-persistence/src/site/rst/Devel.rst) =================================================================== --- trunk/topia-persistence/src/site/rst/devel/Devel.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/devel/Devel.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,170 @@ +.. - +.. * #%L +.. * ToPIA :: Persistence +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2004 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 of the +.. * License, or (at your option) any later version. +.. * +.. * This program is distributed in the hope that it will be useful, +.. * but WITHOUT ANY WARRANTY; without even the implied warranty of +.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.. * GNU General Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - +TopiaContextFactory +=================== + +Le topia context est créé en faisant la demande sur le *TopiaContextFactory*. +On peut passer en paramètre au *TopiaContextFactory* un object *Property* qui +permet de configurer le context. Si aucun fichier est passé en paramètre, un fichier de +propriété **TopiaContextImpl.properties** est recherché dans le classpath. + +Fichier de configuration +======================== + +Le fichier de configuration est un fichier lisible par un objet *Property*. +Il contient différentes informations : +- liste des entités à gérer +- option de connexion à la base de données +- les services à activer + +Liste des entités à gérer +------------------------- + +Il est possible de définir les entités soit directement en indiquant un +répertoire contenant les mappings hibernate:: + + topia.persistence.directories=<path> + +soit en indiquant une liste de classe séparé par des virgule:: + + topia.persistence.classes=<list de classe> + +Le mieux est d'utiliser la liste de classe qui est non spécifique à une +persistence ou à une plateforme. + +Option de connexion à la base de données +---------------------------------------- + +Hibernate +~~~~~~~~~ + +Les options pour hibernate peuvent être directement dans le fichier de configuration principal ou dans un fichier de configuration secondaire. Dans ce cas il faut indiquer dans le fichier de configuration principal le chemin de ce fichier:: + + topia.persistence.properties.file=<filesystem or classpath path> + +Les options hibernates sont les options hibernate classique : + +- hibernate.connection.username +- hibernate.connection.password +- hibernate.dialect +- hibernate.connection.driver_class +- hibernate.connection.url + +Les services à activer +---------------------- + +Il est possible d'indiquer les services à activer grâce aux options:: + + topia.service.<service name>=<class> + topia.service.security=org.nuiton.topia.security.TopiaSecurityServiceImpl + topia.service.index=org.nuiton.topia.index.LuceneIndexer + topia.service.history=org.nuiton.topia.history.TopiaHistoryServiceImpl + +<service name> doit correspondre au nom de service que <class> retourne, sinon il est désactivé. + +Les services disponibles actuellement sont: + +- Service d'indexation full text +- Service d'historisation des modifications des entités +- Service de sécurité +- Service d'upgrade automatique des données hibernates + +TopiaContext +============ + +Le *TopiaContext* permet de récupérer les services, d'ouvrir des transactions +en récupérant des nouveaux *TopiaContext* fils, de s'enregistrer en tant que +listener pour recevoir les notifications de modification sur les entités. + +Sur les *TopiaContext* fils, on peut récupérer des DAO qui permettent de +créer, modifier, rechercher les entités. + +Entité +====== + +Normalement **Topia** est fait pour pouvoir générer n'importe quel type de POJO +et les rendre persistants. Mais il est plus simple d'utiliser la génération +de code fournit avec **Topia** pour générer les entités à partir d'un +diagramme UML. Dans ce cas toutes les entités héritent de *TopiaEntity* qui +contient des méthodes pour s'enregistrer sur les modifications des attributs +ou pouvoir lever un droit de veto sur une modification. Sont aussi +disponible les méthodes: + +- getTopiaId +- getTopiaVersion +- getTopiaCreationDate +- getTopiaContext +- getComposite: Retourne tous les objets qui seront effacé si cet objet est effacé +- getAggregate: Retourne les objets en lien avec celui-ci + +Lorsque l'on utilise la génération on peut implanter une classe qui hérite +du *Abstract* généré et qui se finisse par Impl. Par exemple si dans notre +modèle nous avons la classe *Toto* il sera généré une interface *Toto* et +une classe abstraite *TotoAbstract*, il faudra alors implanter *TotoImpl*:: + + extends TotoAbstract extends TopiaEntityAbstract implements Toto + extends TopiaEntityAbstract implements *TopiaEntity + +Cette classe impl permet d'ajouter des méthodes métiers à l'entité ou des +méthode d'accès différent sur les attributs. + +DAO +=== + +Il n'y a plus qu'un seul type de persistence possible pour les DAO, à savoir Hibernate (depuis la 2.2.0). Il est possible d'étendre un DAO +pour lui ajouter différentes méthodes plus complexes ou plus spécifiques que celles proposées par défaut : + +- findAll +- findAllByProperties(Map<String, Object> properties) +- findAllByProperties(String param, Object property, ...) +- findByProperty(String property) +- tous les find pour chaque property existante de l'entité +- ... + +Pour spécifier d'autres méthodes, il suffit d'utiliser directement le modèle UML qui sert à la génération des entités. +Un stéréotype <<dao>> doit être précisé sur une méthode d'entité pour indiquer qu'elle doit se situer dans un DAO. +Le fichier *DAOImpl* associé ne sera plus généré et devra être créé par le développeur en héritant du *DAOAbstract*. +(voir FAQ pour un exemple sur l'extension d'un DAO). + +Note sur les signatures de méthodes + Par commodité, les méthodes retournant une liste d'entités commencent par findAllBy tandis que celles retournant une seule entité + commencent par findBy. + +TopiaService +============ + +Pour implanter un TopiaService il faut absolument créer une interface qui +hériter de l'interface *TopiaService* et mettre dans cette interface un +attribut static qui définit le nom du service:: + + public static final String SERVICE_NAME = "monservice"; + +Un service peut avoir besoin de nouvelles entités pour fonctionner. Pour cela +il faut retourner la liste des entités grâce à la méthode +**getPersistenceClasses**. + +Après instanciation du service par le **TopiaContext** celui-ci est +initialisé grâce à la méthode **init(TopiaContextImplementor)**. Il peut +alors se mettre listener sur le context ou les DAO par exemple. Property changes on: trunk/topia-persistence/src/site/rst/devel/Devel.rst ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/topia-persistence/src/site/rst/devel/HibernateMapping.rst (from rev 2250, trunk/topia-persistence/src/site/rst/HibernateMapping.rst) =================================================================== --- trunk/topia-persistence/src/site/rst/devel/HibernateMapping.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/devel/HibernateMapping.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,120 @@ +.. - +.. * #%L +.. * ToPIA :: Persistence +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2004 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 of the +.. * License, or (at your option) any later version. +.. * +.. * This program is distributed in the hope that it will be useful, +.. * but WITHOUT ANY WARRANTY; without even the implied warranty of +.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.. * GNU General Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - +================= +Mapping hibernate +================= + +Ce document décrit les choix de mapping faits en fonction +du diagramme de classe UML. + +JDBC +==== + +Généralité +---------- + +- Tous les objets utilisent le versionnement dans un champs version:: + + <version name="topiaVersion" type="long" node="@topiaVersion"/> + +- On utilise les méthodes d'accès pour accêder aux propriétés + +Héritage +-------- + +- Seules les classes concrêtes ont un mapping (au travers de l'interface + impl) +- Chaque classe à un fichier de mapping séparé. + +On utilisera union-subclass + +Identifiant +----------- + +Lors de la description de la classe, on peut indiquer de ne pas générer de clé +technique. Dans ce cas, la clé métier est utilisée (tagvalue: technicalKey=false). +Par défaut une clé technique est utilisée et est de la forme uuid.hex:: + + <id name="topiaId" column="topiaId" type="string"> + <generator class="uuid.hex"/> + </id> + +La description de la clé métier est faite par un tagvalue sur la classe +(tagvalue: key=prop1,prop2,prop3). Si une clé technique est utilisée, une +contrainte d'unicité est tout de même faite sur la clé métier. + +La clé métier sert aussi pour le toString, equals, hashCode. + +Si l'id d'une entité est composé de plusieurs champs, ces champs doivent-être +rassemblés dans une classe indépendante de l'entité. Par contre le mapping +assemble l'entity et son id dans la même table:: + + <composite-id name="#field" class="#class"> + <key-property name="#field1" column="#col1"/> + <key-property name="#field2" column="#col2"/> + <key-property name="#field3" column="#col3"/> + </composite> + +Si l'id est un objet simple il peut être directement mis dans l'entité. + +Relation 1-0 +------------ + + + +Relation 1-1 +------------ + +Relation 0-N +------------ + +Relation 1-N +------------ + +Relation N-N +------------ + +Classe d'association +-------------------- + +Composition +----------- + +Le composant peut changer de propriétaire (set méthode) mais le +propriétaire perd en même temps le lien vers son composé. + +Aggregation +----------- + +Si une classe est aggrégée avec une autre, alors elle suit la vie de l'entité +à laquelle elle est aggrégée (cascade delete, update) + +Elle ne peut pas être affectée a une autre entité. Pas de set sur cette classe +vers l'autre classe. + +XML +=== + +Toutes les propriétés sont des éléments sauf la clé technique qui est un +attribut. Property changes on: trunk/topia-persistence/src/site/rst/devel/HibernateMapping.rst ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/topia-persistence/src/site/rst/devel/Isolation.rst (from rev 2250, trunk/topia-persistence/src/site/rst/Isolation.rst) =================================================================== --- trunk/topia-persistence/src/site/rst/devel/Isolation.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/devel/Isolation.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,92 @@ +.. - +.. * #%L +.. * ToPIA :: Persistence +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2004 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 of the +.. * License, or (at your option) any later version. +.. * +.. * This program is distributed in the hope that it will be useful, +.. * but WITHOUT ANY WARRANTY; without even the implied warranty of +.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.. * GNU General Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - +=========================== +Isolation des TopiaContexts +=========================== + + +Remarque: les requètes ne sont pas bonnes, mais sont là pour donner l'idée +générale. + +Pour mettre en place l'isolation entre les différents TopiaContexts créés par +beginTransaction, il faut ajouter un nouvelle propriété sur les +TopiaEntity: TopiaContextId. Cette propriété prend la valeur de l'id du +TopiaContext qui a créé ou chargé l'objet. On voit donc que plusieurs objets +ayant le même id peuvent exister, le TopiaContextId doit donc faire partie +de la clé de l'objet. Il faut aussi ajouter un champs TopiaDeleted pour +savoir si un objet a été effacé ou non. + +Dans le mapping hibernate pour chaque class d'entité, on a un filtre: +where TopiaContextId == :id || (TopiaContextId > 0 && TopiaContextId <= :id) + +Ce filtre n'est pas suffisant car on a toutes les versions commités de +l'objet jusqu'a :id, il faut un autre filtre apres les recherches pour +n'avoir que les dernieres versions des entites et supprimer dans ce groupe +les entitées marquées et effacées. +where TopiaContextId = max(TopiaContextId) && isDeleted=false group by topiaId + +Lors d'un beginTransaction le nouveau TopiaContext active ce filtre pour son +propre id. + +De cette manière un TopiaContext ne voit que les objets qu'il a créé et/ou +modifié, ou les objets plus ancien que lui. + +Cet Id est: - System.nanoTime() et donc toujours négatif. + +Lors d'un commit d'un TopiaContext, on passe tous les TopiaContextId de +toutes les entités qui sont égales a l'id du TopiaContext en sa version +positive: update <table> set TopiaContextId = -:id where TopiaContextId = :id +De plus le TopiaContext renouvelle son id et modifie tous les filtres pour +qu'il aie la vision d'objets créés par d'autre TopiaContext avant son commit. + +Lors d'un rollback il suffit de faire le renouvellement de l'id et la mise à +jour des filtres. + +Sous-transaction +================ + +La gestion des TopiaContextId pourrait offrir les sous-transactions, si +dans le filtre on ajoutait comme condition, au lieu de TopiaContextId == :id, +TopiaContextId in (:idList) ou idList serait la liste des ids du +TopiaContext courant ainsi que des TopiaContext parents. + +Historisation +============= + +La gestion des TopiaContextId permet d'offrir l'historisation de tous les +objets. Car tous les objets commités sont conservés avec un TopiaContextId +différent pour chaque version. + +Implantation +============ + +- Mettre en place les champs supplémentaires: TopiaContextId, TopiaDeleted +- Modifier la clé primaire pour ajouter TopiaContextId +- Ajouter les filtres dans les mappings +- Ajouter un id sur les TopiaContext +- Modifier le comportement de DAO.delete pour qu'il marque juste l'objet + comme effacé sans l'effacer TopiaDeleted=true +- Pour toutes les recherches ajouter un filtre pour ne retourner que les + derniere version non deleted Property changes on: trunk/topia-persistence/src/site/rst/devel/Isolation.rst ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/topia-persistence/src/site/rst/devel/SchemaMigration.rst (from rev 2250, trunk/topia-persistence/src/site/rst/SchemaMigration.rst) =================================================================== --- trunk/topia-persistence/src/site/rst/devel/SchemaMigration.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/devel/SchemaMigration.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,137 @@ +.. - +.. * #%L +.. * ToPIA :: Persistence +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2004 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 of the +.. * License, or (at your option) any later version. +.. * +.. * This program is distributed in the hope that it will be useful, +.. * but WITHOUT ANY WARRANTY; without even the implied warranty of +.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.. * GNU General Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - +===================================== +Comment migrer d'un schéma à un autre +===================================== + + +Une application modifie et ajoute des objets. La persistence doit donc être +adaptée à ces changements. Le problème est la migration des données +existantes dans le nouveau schéma. + +Voici quelques idées d'implantations. + +Hibernate et dynamic-map +======================== + +Hibernate permet de mapper les objets de la base de données dans des +dynamic-map. Nous n'avons donc pas besoin de pojo pour les représenter, il +nous suffit d'avoir le mapping hibernate. + +L'idée est donc, lors de la modification de schéma, de regrouper tous les +anciens mapping dans un seul fichier de mapping qui contiendra le numero de +version du schema. + +On utilisera ces mappings pour charger l'ancienne configuration et ainsi les +réenregistrer dans le nouveau schéma. + +Une classe java de migration devra être écrite pour transformer les données +d'un schéma vers un autre schéma. + +Avantage +-------- + +Le changement de schéma est fait en java + +Désavantage +----------- + +Il faut dans la base une table qui indique dans quelle version de schéma +actuelle est la base (Topia->schemaVersion). +Une autre solution est de faire une base +par version, le numero de version étant dans le nom de la base (inconveniant : +le nom de la base change a chaque version). +Une autre solution possible est de faire un +changement de schéma dans une transaction, donc on peut lire les anciennes +données dans une transaction et on écrit les nouvelles dans une autre +transaction sur la même table mais qui aurait des schéma différents. + +Il faut, dans les noms des tables, le numéro de version du schéma pour que les +les anciennes tables ne servent pas comme nom pour les nouvelles. + +Il faut soit faire l'aggrégation des mapping dans un seul fichier, soit +n'utiliser qu'un seul fichier pour les mappings, soit avoir un fichier par +classe et par version, mais il est moins simple de retrouver tous les +fichiers de mapping et surtout moins simple + +En fait il n'y a pas vraiment de desavantage. La solution parrait simple et +efficace. + +Exemple de classe de conversion +------------------------------- + +:: + + class Convert { + convert() { + // recherche de la version actuelle de la base topia->schemaVersion + // recherche de la version utilisé par l'application config->schemaVersion + // si les versions divergent, appel de toutes les méthodes convert + // pour arriver à la version de schema actuelle dans config + } + + convert_2_0_1_to_2_0_2(){ + // chargement schema 2_0_1 en utilisant les dynamic-map + // chargement schema 2_0_2 en utilisant les dynamic-map + ... + // code de migration d'un schema a un autre + // si pas de modification pour une classe, il faut au moins faire une + // copie pour remplir les nouvelles tables + ... + // modification de version dans topia->schemaVersion + // commit nouvelle données + // on peut supprimer les anciennes tables + } + + convert_2_0_2_to_2_1_0(){ + // idem + } + } + +Hibernate et XML +================ + +Il est aussi possible de lire une base en XML. On utiliserait donc la même +technique que pour les dynamic-map, mais on utiliserait du XSL pour +convertir le XML vers le schéma souhaité. De cette facon il n'y a pas besoin +de table intermédiaire ni de numéro de version de schéma dans les tables. + +- Export XML en utilisant le vieux mapping +- converion en enchainant les transformations XSL +- Import du nouveau fichier XML + +Inconvéniant +------------ + +si le volume est important il peut-etre long de tout transformer en XML. + +Kettle +====== + +Une autre idee est de ne pas utiliser hibernate mais kettle pour la +migration des données. Nous aurions de la même façon dans le nom des tables +un numero de version de schéma. Un fichier kettle decrirait la migration +d'une version à une autre. Et les différents fichiers serait chaînés pour +arriver au schéma souhaité. Property changes on: trunk/topia-persistence/src/site/rst/devel/SchemaMigration.rst ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/topia-persistence/src/site/rst/devel/Todo.rst (from rev 2250, trunk/topia-persistence/src/site/rst/Todo.rst) =================================================================== --- trunk/topia-persistence/src/site/rst/devel/Todo.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/devel/Todo.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,255 @@ +.. - +.. * #%L +.. * ToPIA :: Persistence +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2004 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 of the +.. * License, or (at your option) any later version. +.. * +.. * This program is distributed in the hope that it will be useful, +.. * but WITHOUT ANY WARRANTY; without even the implied warranty of +.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.. * GNU General Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - +==== +TODO +==== + +Recherches à faire +------------------ + +- des persistences hibernates sur LDAP ou FlatFile +- des outils de migration/evolution de schema + +Generic DAO +----------- +http://www.hibernate.org/328.html:: + + public abstract class GenericHibernateDAO<T> { + ... + Class<T> persistentClass = (Class<T>) ((ParameterizedType) getClass() + .getGenericSuperclass()).getActualTypeArguments()[0]; + + +Regarder si TopiaContext ne pourrait pas être remplacé par un PicoContainer +http://www.hibernate.org/180.html +http://www.hibernate.org/182.html + +doc sur l'optimisation des requetes HQL +http://www.jroller.com/page/wakaleo/?anchor=hibernate_optimisation + +Generation +---------- + +- (2) import/export XML dans ToPIA, à mettre dans le mapping hibernate (en partie fait, mais très stable...) + + +Gestion des versions des POJO +----------------------------- + +mettre en place serialVersionUID sur les entités + +Gestion des droits et de la sécurité +------------------------------------ + +Le créateur de l'objet n'est pas dans l'objet lui même mais dans une table a +part. + +Owner: topiaId de l'entity, id du propriétaire + +Les droits des objets sont dans une table a part +(voir http://www.hibernate.org/140.html). + +Il serait bon que les droits s'appliquent sur un group ou un user. Et qu'un user +puisse appartenir a un group, et qu'un group puisse aussi appartenir a un group + +Il faut aussi modifier le Policy ou autre pour pouvoir lire les permissions +dans hibernate lorsqu'on nous les demandes. Mettre des méthodes statique dans +une classe contenant une session hibernate statique pour permettre l'ajout +de permission a l'execution, sans qu'on est besoin de relire toutes les +permissions a chaque fois, la session servant de cache (mais les sessions +ne sont pas multithread d'ou le synchronise) + +synchronized public void addPermission(TopiaPermission); +synchronized public List<TopiaPermission> getAllPermission(); + +Entity directement dans Topia +----------------------------- + +- User: login, password, email +- Group: name, (User|Group)* +- Permission: action(create, load, update, delete, admin permission), classname, + principal, topiaId de l'entity ou null si le droit sur toutes les entites de ce type + + +Les services +------------ + +..image: ServiceCall.png + +Les services on besoin d'avoir le context de l'appelant pour pouvoir faire +des choix: +- choix de la base de données +- droit de l'utilisateur +- ... + +Pour cela le premier argument de chaque methode generee doit etre un token +retourner par le service d'authentification. + +Le service d'authentification (LA/SSO?) permet de recuperer les informations +du TopiaClientContext qui contient des informations utiles: +- applicationId (identifiant de l'application appelant (im.codelutin.com, im.libre-entreprise.com, ...)) +- clientId (identifiant du client appelant (gaim, exodus, gabber, ...)) +- userLogin +- userPassword + +On a un TopiaServiceManager qui permet de recuperer un proxy sur le service +souhaité. Le proxy n'a pas en premier argument ce TopiaClientContext, il est +ajouté automatiquement lors de l'appel. De cette maniere cote client cela +est completement transparent. + + +# Cote client +ChoremServiceHelper csh = ChoremServiceHelper.getInstance("codelutin.chorem.com", "mentawai", "poussin", "xxxxxxxx"); +CRMService crm = csm.getCRMService(); // retourne un proxy sur le service +List<Person> persons = crm.getAllPerson(); // retourne la liste de toutes les personnes visible par poussin + +# Cote serveur dans getAllPerson(String token) +TopiaClientContext tcc = TopiaAuthenticationService.getTopiaClientContext(token); +Properties prop = ChoremUtil.getContextProperties(tcc); +ChoremContext context = ChoremContext.getContext(prop); +List<Person> result = ChoremDAOHelper.getCRMDAO(context).getAllPerson(); +return result; + +Le moyen de recuperer le TopiaAuthentificationService doit etre specifier +dans les fichiers de configuration de l'application. Il doit y avoir +plusieurs implantation pour ce service: +- class avec methode static pour les applications standalone +- EJB +- service web +- ... + +L'application doit pouvoir plugger sa propre methode d'authentification +(acces a un LDAP, a une BD, a un Liberty Alliance, ...), chaque implantation +doit utiliser cette methode d'authentification (delegation). + +De meme pour l'implantation des services, les services doivent être des +classes Java normal (sans le token en parametre) mais contenant une methode +setTopiaContext() qui permet de mettre a jour + + +Autre +----- + +- tag-value transaction sur les operations des services avec les valeurs + traditionnelles de la spec EJB (required, requiresNew, mandatory, + supports, notSupported, never ). ex auto=required +- dernier user ayant modifié une entité +- tag-value auto avec un pattern sur les attributs. ex auto=now +- tag-value mask avec un pattern sur les attributs. ex : mask=price + puis dans les fichiers de traductions : price=#+,## +- tag-value enumName avec un pattern sur les attributs. ex : + enum=projectStatus + La valeur des énumérations est conservé dans un fichier de configuration + qui peut-etre surchargé par des valeurs dans une table en base de + données : projectStatus=a faire, fait, fini +- tag-value i18n avec un pattern sur les attributs. ex : i18n=true (en partie fait :) ) +- Generation des UI par defaut (JAXX et JSP) +- prendre en compte le contenu de l'onglet doc des entités et attributs + jusqu'au -- pour les tooltips (doc tooltips/doc user/doc dev) + +A reflechir (voir si c vraiment utile) +-------------------------------------- +- pouvoir monitorer un attribut (user, date, oldValue, new Value) + Ces attributs ont une valeur tagguée versioned à vrai ou faux. + -> getHistory[Attribut]():list<History> + +Amélioration templates +---------------------- + +- préférer définir des variables plutôt que d'injecter du code dans les templates : + +Example : + +avant + +:: + + /*{table="<%=GeneratorUtil.getDBName(attr.getDeclaringElement()) + "_" + getName(attr)%>"*/ + + +après + +:: + + String dbName = GeneratorUtil.getDBName(attr.getDeclaringElement()) + "_" + getName(attr); + +ou + +:: + + String attrName = getName(attr); + String dbName = GeneratorUtil.getDBName(attr.getDeclaringElement()); + + /*{table="<%=dbName+"_"+attrName%>"}*/ + +- mettre une javadoc pour dire ce que la méthode va faire + +- incorporer des tests unitaires de génération :) + +- créer des constantes pour les stereotypes tagValues et les utiliser... + +- aller à la chasse aux constantes (exemple propertiesPattern dans DAOAbstractGenerator) + +- faire la chasse au code inutilisé + +- ajouter hasTagValue sur ObjectModelElement dans lutingenerator + +- réfléchir comment générer les imports pour ne plus utilisers les FQN + +- vérifier les javadocs générées (ajouter les exceptions,...) + +- reussir a résoudre les casts dans les DAOAbstraxct sur la méthode getEntityClass + +- réusiner les codes de génération d'attributs : + +:: + + String lazy = " lazy=\""; + if (notEmpty(attr.getTagValue(GeneratorUtil.TAG_LAZY))){ + lazy += attr.getTagValue(GeneratorUtil.TAG_LAZY); + } else { + lazy += "true"; + } + lazy += "\""; + +mais il ya d'autres cas à prévoir... : + +:: + + String fetch = ""; + if (notEmpty(attr.getTagValue(GeneratorUtil.TAG_FETCH))){ + fetch = " fetch=\"" + attr.getTagValue(GeneratorUtil.TAG_FETCH) + "\""; + } + +- Dans lutingenerator, renommer Util en GeneratorUtil et dans ToPIA, + GeneratorUtil en TopiaGeneratorUtil + +- supprimer les les boucles sur Iterator quand c'est possible et utiliser pluot des for-each + +- étudier la nécessité des GeneratorUtil.toLowerCaseFirstLetter(assocAttrName) présents dans EntityAbstractGenerator à propos des classes d'assoc + +- TODO Check wether this method could be used to generate getter and setters + +- Uniformiser et faire hériter les générateurs des interfaces et classe d'impl pour que le générateur de la classe d'impl soit capable de générer aussi l'interface Property changes on: trunk/topia-persistence/src/site/rst/devel/Todo.rst ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/topia-persistence/src/site/rst/devel/event.rst (from rev 2250, trunk/topia-persistence/src/site/rst/event.rst) =================================================================== --- trunk/topia-persistence/src/site/rst/devel/event.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/devel/event.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,91 @@ +.. - +.. * #%L +.. * ToPIA :: Persistence +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2004 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 of the +.. * License, or (at your option) any later version. +.. * +.. * This program is distributed in the hope that it will be useful, +.. * but WITHOUT ANY WARRANTY; without even the implied warranty of +.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.. * GNU General Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - +Gestion des évènements +====================== + +On peut se mettre listener sur deux sortes d'évènements : les TopiaEntityEvent et +les TopiaVetoableEntityEvent. La difference entre les deux se situe sur le moment de +l'appel. + + +TopiaVetoableEntityEvent +------------------------ + +Les TopiaVetoableEntityEvent sont appelés avant l'action, ce qui +permet de l'interdire en levant une exception (par exemple pour gérer la +sécurité). + +Les TopiaVetoableEntityEvent contiennent la classe à laquelle se rapporte l'event +et si possible l'identifiant de l'objet qui sera impacté. Cela n'est pas +toujours le cas; par exemple lors de la creation, l'identifiant n'existe pas forcément +et donc ne peut-etre donné. + +Propagation +~~~~~~~~~~~ + +Les TopiaVetoableEntityEvent sont aussi levés pour tous les contexts pères +du context qui a produit l'event et ceci juste apres avoir prévenu les +listeners du context courant. + +TopiaEntityEvent +---------------- + +Les TopiaEntityEvent sont appelés après l'action pour prévenir du changement. + +Les TopiaEntityEvent contiennent l'entity à laquelle se rapporte l'event + +Propagation +~~~~~~~~~~~ + +Les TopiaEntityEvent sont propagé au context pere lors du commit du context. + +Si un rollback est fait, alors ce sont les listeners du context eux-même qui +sont prévenus du changement. + +Implantation +============ + +Les DAO sont responsables de l'appel des méthodes fire sur le context qui les +a créés lors de l'appel sur ceux-ci des methodes create, update, delete, find +(pour le chargement). + +Le cas Hibernate +---------------- + +Dans le DAO hibernate le context est listener des différents évènements levés +par la session. Mais ces évènements ne sont levés que lors du commit. Dans Topia +on souhaite avoir directement un évènement lors d'un create, update ou delete +sur le DAO. Le DAO hibernate lève donc des évènements lorsque l'on appelle +ces méthodes. + +On a aussi des évènements lors du commit. Il est donc possible qu'on aie, +par exemple, le même évènement Update envoyé deux fois au listener si on fait +un update sur le DAO suivi du commit sur le context. + +On conserve tout de meme le mécanisme d'évènement levé au moment du commit par +hibernate car il est beaucoup plus puissant. Il permet aussi d'être prévenu de +modifications apportées aux constituants d'une entité et non pas seulement des +évènements portants sur l'entité elle-même comme c'est le cas dans le mecanisme +implanté dans les DAO. Property changes on: trunk/topia-persistence/src/site/rst/devel/event.rst ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/topia-persistence/src/site/rst/devel/project.rst (from rev 2250, trunk/topia-persistence/src/site/rst/project.rst) =================================================================== --- trunk/topia-persistence/src/site/rst/devel/project.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/devel/project.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,34 @@ +.. - +.. * #%L +.. * ToPIA :: Persistence +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2004 - 2011 CodeLutin, Chatellier Eric +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 of the +.. * License, or (at your option) any later version. +.. * +.. * This program is distributed in the hope that it will be useful, +.. * but WITHOUT ANY WARRANTY; without even the implied warranty of +.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.. * GNU General Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - +Liste de projets similaires ou se rapprochant +============================================= + +subPersistence +-------------- + +http://subpersistence.sourceforge.net/ + +Librairie d'abstraction de libraire de mapping O/R +Supporte Hibernate pour l'instant. Semble vouloir supporter aussi Castor. Property changes on: trunk/topia-persistence/src/site/rst/devel/project.rst ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/topia-persistence/src/site/rst/devel/security.rst (from rev 2250, trunk/topia-persistence/src/site/rst/security.rst) =================================================================== --- trunk/topia-persistence/src/site/rst/devel/security.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/devel/security.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,52 @@ +.. - +.. * #%L +.. * ToPIA :: Persistence +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2004 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 of the +.. * License, or (at your option) any later version. +.. * +.. * This program is distributed in the hope that it will be useful, +.. * but WITHOUT ANY WARRANTY; without even the implied warranty of +.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.. * GNU General Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - +======== +sécurité +======== + +Implantation de la sécurité +=========================== + +La sécurité est un simple objet java qui hérite de TopiaHelper + +Il se met alors listener sur tous les events vetoables et lève des exceptions +si la personne qui essaie de charger/créer/modifier/supprimer l'objet n'en a pas +le droit. + +Le service de sécurité vient avec son fichier de configuration. Dans ce fichier +il y a les paramètres utiles au service pour retrouver les informations sur les +droits. + +TopiaHelper est en fait une interface qui contient la méthode +init(TopiaContext, Properties) + + +package +------- + +:org.nuiton.topia.security: pour tout ce qui touche a la sécurité + (TopiaAuthenticationHelper, TopiaAuthorisationHelper, LoginModule, Filter, ...) +:org.nuiton.topia.security.entities: pour les entities utiles à la définition + de la sécurité (user, group, permission) Property changes on: trunk/topia-persistence/src/site/rst/devel/security.rst ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Deleted: trunk/topia-persistence/src/site/rst/event.rst =================================================================== --- trunk/topia-persistence/src/site/rst/event.rst 2011-04-16 16:25:22 UTC (rev 2260) +++ trunk/topia-persistence/src/site/rst/event.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -1,91 +0,0 @@ -.. - -.. * #%L -.. * ToPIA :: Persistence -.. * -.. * $Id$ -.. * $HeadURL$ -.. * %% -.. * Copyright (C) 2004 - 2010 CodeLutin -.. * %% -.. * This program is free software: you can redistribute it and/or modify -.. * it under the terms of the GNU Lesser General Public License as -.. * published by the Free Software Foundation, either version 3 of the -.. * License, or (at your option) any later version. -.. * -.. * This program is distributed in the hope that it will be useful, -.. * but WITHOUT ANY WARRANTY; without even the implied warranty of -.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.. * GNU General Lesser Public License for more details. -.. * -.. * You should have received a copy of the GNU General Lesser Public -.. * License along with this program. If not, see -.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. -.. * #L% -.. - -Gestion des évènements -====================== - -On peut se mettre listener sur deux sortes d'évènements : les TopiaEntityEvent et -les TopiaVetoableEntityEvent. La difference entre les deux se situe sur le moment de -l'appel. - - -TopiaVetoableEntityEvent ------------------------- - -Les TopiaVetoableEntityEvent sont appelés avant l'action, ce qui -permet de l'interdire en levant une exception (par exemple pour gérer la -sécurité). - -Les TopiaVetoableEntityEvent contiennent la classe à laquelle se rapporte l'event -et si possible l'identifiant de l'objet qui sera impacté. Cela n'est pas -toujours le cas; par exemple lors de la creation, l'identifiant n'existe pas forcément -et donc ne peut-etre donné. - -Propagation -~~~~~~~~~~~ - -Les TopiaVetoableEntityEvent sont aussi levés pour tous les contexts pères -du context qui a produit l'event et ceci juste apres avoir prévenu les -listeners du context courant. - -TopiaEntityEvent ----------------- - -Les TopiaEntityEvent sont appelés après l'action pour prévenir du changement. - -Les TopiaEntityEvent contiennent l'entity à laquelle se rapporte l'event - -Propagation -~~~~~~~~~~~ - -Les TopiaEntityEvent sont propagé au context pere lors du commit du context. - -Si un rollback est fait, alors ce sont les listeners du context eux-même qui -sont prévenus du changement. - -Implantation -============ - -Les DAO sont responsables de l'appel des méthodes fire sur le context qui les -a créés lors de l'appel sur ceux-ci des methodes create, update, delete, find -(pour le chargement). - -Le cas Hibernate ----------------- - -Dans le DAO hibernate le context est listener des différents évènements levés -par la session. Mais ces évènements ne sont levés que lors du commit. Dans Topia -on souhaite avoir directement un évènement lors d'un create, update ou delete -sur le DAO. Le DAO hibernate lève donc des évènements lorsque l'on appelle -ces méthodes. - -On a aussi des évènements lors du commit. Il est donc possible qu'on aie, -par exemple, le même évènement Update envoyé deux fois au listener si on fait -un update sur le DAO suivi du commit sur le context. - -On conserve tout de meme le mécanisme d'évènement levé au moment du commit par -hibernate car il est beaucoup plus puissant. Il permet aussi d'être prévenu de -modifications apportées aux constituants d'une entité et non pas seulement des -évènements portants sur l'entité elle-même comme c'est le cas dans le mecanisme -implanté dans les DAO. Deleted: trunk/topia-persistence/src/site/rst/howto.rst =================================================================== --- trunk/topia-persistence/src/site/rst/howto.rst 2011-04-16 16:25:22 UTC (rev 2260) +++ trunk/topia-persistence/src/site/rst/howto.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -1,281 +0,0 @@ -.. - -.. * #%L -.. * ToPIA :: Persistence -.. * -.. * $Id$ -.. * $HeadURL$ -.. * %% -.. * Copyright (C) 2004 - 2011 CodeLutin, Chatellier Eric -.. * %% -.. * This program is free software: you can redistribute it and/or modify -.. * it under the terms of the GNU Lesser General Public License as -.. * published by the Free Software Foundation, either version 3 of the -.. * License, or (at your option) any later version. -.. * -.. * This program is distributed in the hope that it will be useful, -.. * but WITHOUT ANY WARRANTY; without even the implied warranty of -.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.. * GNU General Lesser Public License for more details. -.. * -.. * You should have received a copy of the GNU General Lesser Public -.. * License along with this program. If not, see -.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. -.. * #L% -.. - -How to -====== - -Ce document a pour objectif de prendre en main le framework Topia. Le document -est constitué de 4 parties, la modélisation, la génération, la configuration et -l'utilisation. - -Modélisation ------------- - -La première étape constiste à réaliser le modèle UML soit avec Argouml -(http://argouml.tigris.org) soit avec Poséidon (http://www.gentleware.com). - -Le stérotype «entity» sur les classes permet de préciser que la classe est -persistée par Topia. D'autre stérotypes (extern, service, ...) sont disponibles -mais ne sont pas présentés. - -Le fichier de modélisation peut être complété par un fichier de configuration -nommé <nom fichier modélisation>.properties. Il contient des informations -techniques propres aux librairies utilisé par Topia. - -Exemple : - -:: - - # Précise comment est mappé un type - # model.tagvalue.<type java>=<type base de donnée> - model.tagvalue.java.lang.String=text - - # Précise le schema de la base de données par défaut - # model.tagvalue.dbSchema=<nom schéma> - model.tagvalue.dbSchema=test - - # Précise l'entête de l'ensemble des fichiers générés - # model.tagvalue.copyright=<valeur> - model.tagvalue.copyright=/* *##%\n Copyright (C) 2011 Code Lutin\n *##% */ - - # Force le chargement d'un attribut - # <nom paquetage>.<nom entité>.attribute.<nom attribut>.tagvalue.lazy=false - org.codelutin.Person.attribute.association.tagvalue.lazy=false - -Génération ----------- - -La génération des fichiers Topia se font par l'utilisation du plugin maven -Eugene_. Ce plugin est disponible sur le repository central. - -Configuration du plugin maven : - -:: - - <plugin> - <groupId>org.nuiton.eugene</groupId> - <artifactId>maven-eugene-plugin</artifactId> - <version>2.3.2</version> - <executions> - <execution> - <phase>process-sources</phase> - <!--Configuration of model generator--> - <configuration> - <inputs>zargo</inputs> - <fullPackagePath>org.nuiton.topiatest</fullPackagePath> - <defaultPackage>org.nuiton.topiatest</defaultPackage> - <extractedPackages>org.nuiton.topiatest</extractedPackages> - <templates> - org.nuiton.topia.generator.TopiaMetaTransformer - </templates> - </configuration> - <goals> - <goal>smart-generate</goal> - </goals> - </execution> - </executions> - <dependencies> - <dependency> - <groupId>org.nuiton.topia</groupId> - <artifactId>topia-persistence</artifactId> - <version>2.5.2</version> - <scope>compile</scope> - </dependency> - </dependencies> - </plugin> - -Le plugin utilise Eugene_ avec les templates de génération de Topia, le -fichier argouml ou poséidon doit se trouver dans le répertoire -``src/main/xmi``. Les fichiers sont générés dans le répertoire -``target/generated-sources/java``. Il faut préciser au plugin les paquetages -à traiter avec le ``defaultPackage`` et ``extractedPackages``. - -Ajout dans des dépendances de Topia pour la compilation des fichiers générés : - -:: - - <dependency> - <groupId>org.nuiton.topia</groupId> - <artifactId>topia-persistence</artifactId> - <version>2.5.2</version> - <scope>compile</scope> - </dependency> - -Pour une classe modélisée, nous retrouvons 6 fichiers : - * Une interface - * Une classe abstraite - * Une implantation - * Une configuration hibernate - * Un DAO abstrait - * Une implantation du DAO - -Une classe Helper est aussi générée, permettant l'accès à l'ensemble des DAO. - -Configuration -------------- - -Un fichier contenant les informations de connexion à la base de données et de -configuration de Topia doit être créé au niveau des ressources du projet. -Par convention, ce fichier est nommé ``TopiaContextImpl.properties``. - -Exemple : - -:: - - # Permet la création, la modification, ou pas automatique de la base de données - # [create | update | none] - hibernate.hbm2ddl.auto=update - - # Affichage des requêtes dans la console - # [true | false] - hibernate.show_sql=false - - # Permet de préciser les classes a persister - topia.persistence.classes=org.codelutin.Person, org.codelutin.Pet - - # Informations de connection : - - # Dialect à utiliser - hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect - - # Driver JDBC - hibernate.connection.driver_class=org.postgresql.Driver - - # URL de connection - hibernate.connection.url=jdbc:postgresql://localhost/mydb - - # Login de l'utilisateur qui se connecte - hibernate.connection.username=user - - # Mot de passe de l'utilisateur - hibernate.connection.password=xxxx - -Utilisation ------------ - -Implantation des méthodes -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Si des méthodes ont été définies dans le modèle de données, il faut créer -l'implantation correspondante. Le paquetage doit porter le même nom que celui de -la génération. - -Gestion des transactions -~~~~~~~~~~~~~~~~~~~~~~~~ - ->>> Properties conf = new Properties(); -URL url = Resource.getURL("TopiaContextImpl.properties"); -conf.load(new FileInputStream(new File(url.toURI()))); - -Permet de charger un fichier contenant les informations de connexion à la base -et de configuration de Topia. - ->>> TopiaContext rootContext = TopiaContextFactory.getContext(conf); - -Récupère le context de départ pour la création de sous context pour la gestion -des entités. - ->>> TopiaContext transaction = rootContext.beginTransaction(); - -Création d'un sous context pour la gestion des entités. - ->>> transaction.commitTransaction(); - -Validation de l'état du context, les modifications des entités sont reportées -dans la base de données. - ->>> transaction.rollBackTransaction(); - -Invalidation de l'état du context, les modifications des entités ne sont pas -reportées dans la base de données. - ->>> transaction.closeContext(); - -Relâche la connexion JDBC d'un sous context et de ses sous contexts sans -validation de l'état des contexts. - ->>> rootContext.closeContext(); - -Relâche l'ensemble des ressources (cache, pools, ...) et relâche la connexion -JDBC des sous contexts avec validation de l'état des contexts. - -Manipulation des entités -~~~~~~~~~~~~~~~~~~~~~~~~ - ->>> PersonDAO personDAO = <nom modele>DAOHelper.getPersonDAO(transaction); - -Récupération d'un DAO pour accéder à une entité. - ->>> Person person = personDAO.findByTopiaId(id); - -Les méthodes find permettent de récupérer une ou plusieures entités selon différents -critères. - ->>> person.setName("tutu"); - -Manipulation de l'entité par les getters et setters. - ->>> Person person = personDAO.create(); - -Création d'une entité. Si vous utilisez l'instanciation classique java avec le -new, l'entité n'est pas persistée. - ->>> personDAO.update(person); - -Modification d'un entité. - ->>> personDAO.delete(person); - -Suppression d'une entité. - -Exemple -~~~~~~~ - -:: - - Properties conf = new Properties(); - URL url = Resource.getURL("TopiaContextImpl.properties"); - conf.load(new FileInputStream(new File(url.toURI()))); - - TopiaContext rootContext = TopiaContextFactory.getContext(conf); - - TopiaContext transaction = rootContext.beginTransaction(); - PersonDAO personDAO = ModelHelper.getPersonDAO(transaction); - - Person person = personDAO.create(); - person.set...(...); - person.set...(...); - personDAO.update(person); - - person.get...(...); - person.get...(...); - - personDAO.delete(person); - - transaction.commitTransaction(); - transaction.closeContext(); - - rootContext.closeContext(); - -.. _Eugene: http://maven-site.nuiton.org/eugene/ Deleted: trunk/topia-persistence/src/site/rst/index.rst =================================================================== (Binary files differ) Added: trunk/topia-persistence/src/site/rst/index.rst =================================================================== --- trunk/topia-persistence/src/site/rst/index.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/index.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,112 @@ +.. - +.. * #%L +.. * ToPIA :: Persistence +.. * +.. * $Id: index.rst 2251 2011-04-16 10:09:55Z bleny $ +.. * $HeadURL: http://svn.nuiton.org/svn/topia/trunk/topia-persistence/src/site/rst/index.r... $ +.. * %% +.. * Copyright (C) 2004 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 of the +.. * License, or (at your option) any later version. +.. * +.. * This program is distributed in the hope that it will be useful, +.. * but WITHOUT ANY WARRANTY; without even the implied warranty of +.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.. * GNU General Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - +ToPIA +===== + +.. contents:: + +Présentation +------------ + +ToPIA, pour Tools for Portable and Independant Architecture, est un framework +d'abstraction des plateformes techniques. + +C'est à dire ? +~~~~~~~~~~~~~~ + +Le cycle de développement en Y traditionnel peut être représenté de la manière +suivante : + +Les deux branches, la branche fonctionnelle, porteuse de la solution logique, et +la branche technique, qui définit la plateforme technique sur laquelle la +solution sera implantée, se rejoignent en amont de la conception détaillée et du +codage. Cette projection peut être accompagnée de génération de code, mais il +reste toujours une certaine quantité de code écrite à la main. + +Cette séparation des responsabilités et ce processsus donne pleine satisfaction +lors du développement initial d'un logiciel. La vie d'un logiciel commence +toutefois au moment de sa mise en production et les évolutions qui y seront +apportées sont de deux natures : + - Évolutions fonctionnelles : Ajout de fonctionnalités, correction de bugs, ... + - Evolutions techniques : Changement de bases de données, changement de techno + sur les UI, nouveaux accès (SOAP ?), ... + +Si les évolutions fonctionnelles sont prises en compte par la nature itérative +des processus de développement, les évolutions techniques sont elles difficiles. + +Comment passer d'hibernate à JDO, de Swing au client léger, des EJB aux +conteneurs légers ? En supprimant les dépendances de votre code sur les briques +techniques, en codant sur une plateforme technique abstraite, interfaces et +facades au travers desquels vous pourrez manipuler les différentes solutions +techniques que vous retiendrez. Hibernate et JDO ne sont que deux API d'accès +aux données; Swing et client léger, des UI; les EJB et les conteneurs légers, +des logiques métiers déportées... + +Et ToPIA alors ? +~~~~~~~~~~~~~~~~ + +ToPIA propose une telle plateforme. Vous codez en regard d'une API qui abstrait +la distribution (1-tiers ?, 2-tiers ?, 3-tiers ?, n-tiers ? quels protocoles +d'accès ?), la persistence (quelles bases bien sûr, mais également quel +framework ?, quelle API de requètage (EJB-QL, JDO-QL, ... ?), quel méchanisme +transactionnel ?), quelle UI ? Puis vous projettez votre application sur la +palteforme de votre choix. + +Fonctionnement classique +------------------------ + +Le framework ToPIA permet dans un projet de générer la partie métier de l'application, +c'est à dire les classes JAVA ainsi que le mapping Hibernate pour la persistance. +Cela représente un travail considérable en moins pour le développeur et une +flexibilité importante dans les évolutions futures de la parties métier. + +L'utilisation du framework ToPIA se découpe en plusieurs phases, elles sont +itératives : + 1. Création du diagramme de classe sur ArgoUML_ par exemple + 2. Exportation du modèle en XMI + 3. Génération des fichiers JAVA et Hibernate par Eugene_ + 4. Implentation des méthodes + +ToPIA-service +------------- + +Le framework ToPIA peut être complèté par une multitude de services. Il existe +actuellement trois : + + - `service pour la sécurité`_ : permet la gestion des authentification et des + autorisations. Il repose sur le mécanisme de JAAS. + - `service pour la gestion des mises à jour`_ : permet de mettre à jour une version + de base à partir d'un modèle versionné. + - `service de réplication`_ : permet de répliquer des données de base à base. + - ``service pour la gestion d'un historique`` : permet de conserver l'ensemble des + actions réalisées sur la base de données (**plus maintenu depuis la 2.3.3**). + - ``service pour la recherche`` : permet de rechercher un mot clé parmis les entités + de l'application. Il repose sur la librairie lucene d'apache (**plus maintenu depuis la 2.3.3**). + +.. _service pour la sécurité: ../topia-service-security +.. _service pour la gestion des mises à jour: ../topia-service-migration +.. _service de réplication: ../topia-service-replication +.. _Eugene: http://maven-site.nuiton.org/eugene/ +.. _ArgoUML: http://argouml.tigris.org/ Property changes on: trunk/topia-persistence/src/site/rst/index.rst ___________________________________________________________________ Added: svn:executable + * Deleted: trunk/topia-persistence/src/site/rst/project.rst =================================================================== --- trunk/topia-persistence/src/site/rst/project.rst 2011-04-16 16:25:22 UTC (rev 2260) +++ trunk/topia-persistence/src/site/rst/project.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -1,34 +0,0 @@ -.. - -.. * #%L -.. * ToPIA :: Persistence -.. * -.. * $Id$ -.. * $HeadURL$ -.. * %% -.. * Copyright (C) 2004 - 2011 CodeLutin, Chatellier Eric -.. * %% -.. * This program is free software: you can redistribute it and/or modify -.. * it under the terms of the GNU Lesser General Public License as -.. * published by the Free Software Foundation, either version 3 of the -.. * License, or (at your option) any later version. -.. * -.. * This program is distributed in the hope that it will be useful, -.. * but WITHOUT ANY WARRANTY; without even the implied warranty of -.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.. * GNU General Lesser Public License for more details. -.. * -.. * You should have received a copy of the GNU General Lesser Public -.. * License along with this program. If not, see -.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. -.. * #L% -.. - -Liste de projets similaires ou se rapprochant -============================================= - -subPersistence --------------- - -http://subpersistence.sourceforge.net/ - -Librairie d'abstraction de libraire de mapping O/R -Supporte Hibernate pour l'instant. Semble vouloir supporter aussi Castor. Deleted: trunk/topia-persistence/src/site/rst/security.rst =================================================================== --- trunk/topia-persistence/src/site/rst/security.rst 2011-04-16 16:25:22 UTC (rev 2260) +++ trunk/topia-persistence/src/site/rst/security.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -1,52 +0,0 @@ -.. - -.. * #%L -.. * ToPIA :: Persistence -.. * -.. * $Id$ -.. * $HeadURL$ -.. * %% -.. * Copyright (C) 2004 - 2010 CodeLutin -.. * %% -.. * This program is free software: you can redistribute it and/or modify -.. * it under the terms of the GNU Lesser General Public License as -.. * published by the Free Software Foundation, either version 3 of the -.. * License, or (at your option) any later version. -.. * -.. * This program is distributed in the hope that it will be useful, -.. * but WITHOUT ANY WARRANTY; without even the implied warranty of -.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.. * GNU General Lesser Public License for more details. -.. * -.. * You should have received a copy of the GNU General Lesser Public -.. * License along with this program. If not, see -.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. -.. * #L% -.. - -======== -sécurité -======== - -Implantation de la sécurité -=========================== - -La sécurité est un simple objet java qui hérite de TopiaHelper - -Il se met alors listener sur tous les events vetoables et lève des exceptions -si la personne qui essaie de charger/créer/modifier/supprimer l'objet n'en a pas -le droit. - -Le service de sécurité vient avec son fichier de configuration. Dans ce fichier -il y a les paramètres utiles au service pour retrouver les informations sur les -droits. - -TopiaHelper est en fait une interface qui contient la méthode -init(TopiaContext, Properties) - - -package -------- - -:org.nuiton.topia.security: pour tout ce qui touche a la sécurité - (TopiaAuthenticationHelper, TopiaAuthorisationHelper, LoginModule, Filter, ...) -:org.nuiton.topia.security.entities: pour les entities utiles à la définition - de la sécurité (user, group, permission) Deleted: trunk/topia-persistence/src/site/rst/tagvalues.rst =================================================================== --- trunk/topia-persistence/src/site/rst/tagvalues.rst 2011-04-16 16:25:22 UTC (rev 2260) +++ trunk/topia-persistence/src/site/rst/tagvalues.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -1,78 +0,0 @@ -.. - -.. * #%L -.. * ToPIA :: Persistence -.. * -.. * $Id$ -.. * $HeadURL$ -.. * %% -.. * Copyright (C) 2004 - 2011 CodeLutin -.. * %% -.. * This program is free software: you can redistribute it and/or modify -.. * it under the terms of the GNU Lesser General Public License as -.. * published by the Free Software Foundation, either version 3 of the -.. * License, or (at your option) any later version. -.. * -.. * This program is distributed in the hope that it will be useful, -.. * but WITHOUT ANY WARRANTY; without even the implied warranty of -.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.. * GNU General Lesser Public License for more details. -.. * -.. * You should have received a copy of the GNU General Lesser Public -.. * License along with this program. If not, see -.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. -.. * #L% -.. - -Tag values -========== - -Topia templates are customizable using tag values. - -Here are current tag values defined in topia. They can be defined in source -model or model property file. - -Topia tag values ----------------- - -+--------------------------+-----------+----------------------------------------------------+ -| Name | Category | Description | -+==========================+===========+====================================================+ -| orderBy | Hibernate | Define order-by attribute in hibernate mapping for | -| | | a specific relation | -+--------------------------+-----------+----------------------------------------------------+ -| dbName | Hibernate | Database table name | -+--------------------------+-----------+----------------------------------------------------+ -| dbSchema | Hibernate | Database schema | -+--------------------------+-----------+----------------------------------------------------+ -| length | Hibernate | Attribute length in database | -+--------------------------+-----------+----------------------------------------------------+ -| annotation | all | Add annotation on attribute | -+--------------------------+-----------+----------------------------------------------------+ -| copyright | all | Generated files header copyright | -+--------------------------+-----------+----------------------------------------------------+ -| access | hibernate | Field access type | -+--------------------------+-----------+----------------------------------------------------+ -| i18n | entity | Generate i18n ??? | -+--------------------------+-----------+----------------------------------------------------+ -| naturalId | hibernate | Generate hibernate naturalId | -+--------------------------+-----------+----------------------------------------------------+ -| naturalIdMutable | hibernate | Tell hibernate if a natural id key is mutable | -+--------------------------+-----------+----------------------------------------------------+ -| inverse | hibernate | To configure with part of a N-N relation is inverse| -+--------------------------+-----------+----------------------------------------------------+ -| lazy | hibernate | Hibernate multiple attribute fetch property | -| | | (default to ''hibernate default value'') | -+--------------------------+-----------+----------------------------------------------------+ -| notNull | hibernate | Hibernate attribute not null property | -| | | (default to ''hibernate default value'') | -+--------------------------+-----------+----------------------------------------------------+ -| hibernateProxyInterface | hibernate | To not generate proxy information in | -| | | hibernate mappings. | -+--------------------------+-----------+----------------------------------------------------+ - - -Eugene tag values ------------------ - -Eugene contains also his tag values. See `eugene documentation`_ for more détails. - -.. _eugene documentation: http://maven-site.nuiton.org/eugene/ Copied: trunk/topia-persistence/src/site/rst/user/FAQ.rst (from rev 2250, trunk/topia-persistence/src/site/rst/FAQ.rst) =================================================================== --- trunk/topia-persistence/src/site/rst/user/FAQ.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/user/FAQ.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,60 @@ +.. - +.. * #%L +.. * ToPIA :: Persistence +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2004 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 of the +.. * License, or (at your option) any later version. +.. * +.. * This program is distributed in the hope that it will be useful, +.. * but WITHOUT ANY WARRANTY; without even the implied warranty of +.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.. * GNU General Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - +=== +FAQ +=== + +Problème lors du chargement d'une entity +======================================== + +Le chargement utilise les méthodes Set des propriétés, il faut donc faire +attention si on les surcharge. + +Il faut faire attention lors de l'ajout, sur l'entity, de méthodes qui ont la +même signature que des méthods Set de propriétés avec juste des arguments +différents, car elles peuvent être utilisées à la place de la vrai méthode +pour quelque valeur (par exemple null). + +Faire fonctionner les Web Services Topia via RMI +================================================ +L'utilisation des Web Services sur RMI impose la génération de classes sauvées +sur disque. +Elle sont construites à la volée et sauvées dans le dossier "./topiagen". + +Ce dossier doit donc se trouver dans le classpath. + +Comment commit (ou rollback) une transaction directement à partir d'un DAO ? +============================================================================ + +Contrairement à ce que l'on pourrait croire aux premiers abords, les méthodes commitTransaction() +et rollbackTransaction() disponibles dans les DAO ne sont pas prévus à cet effet. Il faut toujours +utiliser le contexte pour commit (ou rollback) une transaction. Donc pour le faire à partir d'un DAO : +dao.getContext().commitTransaction() // on récupère le context (transaction sur le DAO) et on commit. +Le principe reste identique pour le rollback. +Pour revenir sur les méthodes commitTransaction() et rollbackTransaction() disponibles sur le DAO, elles +servent de "callback" au moment du commit (ou rollback) de la transaction. Le context se chargera d'appeler +tous les commitTransaction() des DAO, ceci afin de permettre un traitement spécifique au DAO au moment du commit. +Ce traitement peut donc être effectué directement à partir du dao via cette méthode sans passer par le context. + Property changes on: trunk/topia-persistence/src/site/rst/user/FAQ.rst ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/topia-persistence/src/site/rst/user/ModelGeneration.rst (from rev 2250, trunk/topia-persistence/src/site/rst/ModelGeneration.rst) =================================================================== --- trunk/topia-persistence/src/site/rst/user/ModelGeneration.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/user/ModelGeneration.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,111 @@ +.. - +.. * #%L +.. * ToPIA :: Persistence +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2004 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 of the +.. * License, or (at your option) any later version. +.. * +.. * This program is distributed in the hope that it will be useful, +.. * but WITHOUT ANY WARRANTY; without even the implied warranty of +.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.. * GNU General Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - +Génération des modèles +---------------------- + + +Le module "topia-persistence" de topia est capable de +générer la persistence à partir d'un modèle UML. + +Nous allons détailler ici comme inclure la génération dans le +cycle de compilation maven. + + +Architecture maven +------------------ + ++---------------------------------+-----------------------------------------+ +| src/main/xmi/mymodel.zargo | exemple de modele UML avec argoUML | ++---------------------------------+-----------------------------------------+ +| src/main/xmi/mymodel.properties | fichier de propriétés attaché au modele | ++---------------------------------|-----------------------------------------+ + + +Configuration du pom.xml +------------------------ + +Pour générer les sources dans la phase "generate-sources" de maven, et utiliser +les sources générées, et faut configurer le pom. + +Plugin eugene +============= + +:: + +<plugin> + <groupId>org.nuiton.eugene</groupId> + <artifactId>maven-eugene-plugin</artifactId> + <!-- la version peut être plus récente --> + <version>1.0.0</version> + <executions> + <execution> + <id>Generator</id> + <phase>generate-sources</phase> + <configuration> + <srcDirUml>src/main/xmi</srcDirUml> + <srcXmiDest>target/generated-sources/xmi/</srcXmiDest> + <fullPackagePath>org.company.package</fullPackagePath> + <extractedPackages>org.company.package</extractedPackages> + <srcGenDest>target/generated-sources/objectmodel/</srcGenDest> + <includes>**/*.objectmodel</includes> + <templates>org.nuiton.topia.generator.TopiaMetaGenerator</templates> + <destDirGen>target/generated-sources/java</destDirGen> + <defaultPackage>org.company.package</defaultPackage> + </configuration> + <goals> + <goal>zargo2xmi</goal> + <goal>xmi2objectmodel</goal> + <goal>generate</goal> + </goals> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.nuiton.topia</groupId> + <artifactId>topia-persistence</artifactId> + <!-- la version peut être plus récente --> + <version>2.2.0</version> + <scope>runtime</scope> + </dependency> + </dependencies> +</plugin> + +Pour plus d'information à propos d'eugene, merci de consulter le site : +http://maven-site.nuiton.org/eugene/ + +Dépendances du projet +===================== + +Il faut enfin ajouter "topia-persistence" en dépendance du projet : + +:: + +<dependency> + <groupId>org.nuiton.topia</groupId> + <artifactId>topia-persistence</artifactId> + <!-- la version peut être plus récente --> + <version>2.2.0</version> + <scope>compile</scope> +</dependency> Property changes on: trunk/topia-persistence/src/site/rst/user/ModelGeneration.rst ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/topia-persistence/src/site/rst/user/TopiaQuery.rst (from rev 2250, trunk/topia-persistence/src/site/rst/TopiaQuery.rst) =================================================================== --- trunk/topia-persistence/src/site/rst/user/TopiaQuery.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/user/TopiaQuery.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,543 @@ +.. - +.. * #%L +.. * ToPIA :: Persistence +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2004 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 of the +.. * License, or (at your option) any later version. +.. * +.. * This program is distributed in the hope that it will be useful, +.. * but WITHOUT ANY WARRANTY; without even the implied warranty of +.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.. * GNU General Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - +TopiaQuery +========== + +:Author: Florian Desbois +:Contact: topia-devel@list.nuiton.org ou topia-users@list.nuiton.org +:Revision: $Revision$ +:Date: $Date$ + +L'objet TopiaQuery permet de créer plus simplement des requêtes HQL pour éviter +les concaténations complexes lors de l'utilisation de la méthode **find** +du TopiaContext. + +Chacune des parties de la requête sont indépendantes et seront concaténés au +moment de l'exécution. Il est donc possible d'ajouter des éléments à la +requête à n'importe quel moment de sa construction (from, select, where, order, +group, ...). + +La TopiaQuery peut donc être construite à un endroit et exécutée à un autre. +Une même requête peut également être réutilisée pour être passée en sous-requête +ou exécutée plusieurs fois à la suite avec certains légers changement de +paramètres. + +.. contents:: + +Modèle exemple +-------------- + +Ci-dessous un modèle simple utilisé pour les exemples de cette documentation. + +.. image:: modelForTopiaQuery.png + +Instantiation +------------- + +La TopiaQuery nécessite obligatoirement une entité référence pour être exécutée. +Cette entité correspondra à l'élément principal du FROM de la requête et si +nécessaire sera ajouté automatiquement au SELECT. + +Il y a plusieurs façons d'instancier la TopiaQuery : + +Directement depuis un DAO :: + + TopiaContext transaction = rootContext.beginTransaction(); + BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); + TopiaQuery query = dao.createQuery(); + +ou depuis un topiaContext :: + + TopiaContext transaction = rootContext.beginTransaction(); + TopiaQuery query = transaction.createQuery(Boat.class, "B"); + +L'intérêt de passer par un DAO est de pouvoir par la suite executer la requête +avec ce même DAO. Il est également possible d'utiliser des alias pour l'élément +principal de la requête pour pouvoir plus facilement gérer les cas de jointure. +Il suffit de préciser l'alias au moment de l'instanciation :: + + TopiaContext transaction = rootContext.beginTransaction(); + BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); + TopiaQuery query = dao.createQuery("E"); + +Ajout d'éléments au WHERE +------------------------- + +Les méthodes de base nécessaires concernent l'ajout d'élements dans le WHERE de la +requête. Plusieurs méthodes sont disponibles suivant les besoins pour ajouter +simplement un élément au where :: + + TopiaQuery query = boatDAO.createQuery(); + + // Recherche sur l'immatriculation du navire : immatriculation = 142154 + query.addEquals("immatriculation", 142154); + + // Recherche toutes les dates de construction < 2006 + query.addWhere("buildYear", Op.LT, 2006); + + // Recherche des navires ayant un nom + query.addNotNull("name"); + + // depuis 2.3.4 + // Recherche des navires n'ayant pas de nom + query.addNull("name"); + + // Recherche des navires ayant une date de construction 2003, 2004 ou 2006 + query.addEquals("buildYear", 2003, 2004, 2006); + + // depuis 2.3.4 + // Recherche entre deux dates + TopiaQuery queryContact = contactDAO.createQuery(); + Calendar dateBegin = new GregorianCalendar(2010,2,3); + Calendar dateEnd = new GregorianCalendar(2010,5,6); + queryContact.addBetween("creationDate", dateBegin.getTime(), dateEnd.getTime()); + + // depuis 2.3.4 + // Utilisation d'une sous-requête (les paramètres de la sous-requête seront + // ajoutés automatiquement à la requête principale en gérant les doublons + // (sur la valeur et la clé)). + // Le ? correspond à l'endroit ou sera injecté la requête, attention aux + // parenthèses. + queryContact.addSubQuery("boat IN elements(?)", query); + +Il est fortement conseillé d'utiliser les constantes des entités pour les noms +de leurs propriétés :: + + query.addEquals(Boat.IMMATRICULATION, 142154); + query.addNotNull(Boat.NAME); + ... + +La TopiaQuery peut être chaînée, les méthodes permettant l'ajout d'éléments +renvoient toutes la même TopiaQuery avec l'élément ajouté :: + + TopiaContext transaction = rootContext.beginTransaction(); + BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); + dao.createQuery().addEquals(Boat.IMMATRICULATION, 142154).addNotNull(Boat.NAME); + +Opérateurs +---------- + +Une enum interne à la TopiaQuery permet de manipuler les opérateurs nécessaires +aux ajouts dans le WHERE : + +- TopiaQuery.Op.EQ : Opérateur = +- TopiaQuery.Op.GT : Opérateur > +- TopiaQuery.Op.GE : Opérateur >= +- TopiaQuery.Op.LIKE : Opérateur LIKE +- TopiaQuery.Op.LT : Opérateur < +- TopiaQuery.Op.LE : Opérateur <= +- TopiaQuery.Op.NOT_NULL : Opérateur IS NOT NULL +- TopiaQuery.Op.NULL : Opérateur IS NULL +- TopiaQuery.Op.NEQ : Opérateur != + +Autres parties de la requête +---------------------------- + +Ajout d'élément au FROM +~~~~~~~~~~~~~~~~~~~~~~~ + +Il est souvent nécessaire d'ajouter une autre entité au FROM de la requête, +pour ce faire, il existe deux méthodes : + +- addFrom(Class entityClass) : ajoute une entité au FROM + (Ex : addFrom(Contact.class);) + +- addFrom(Class entityClass, String alias) : ajoute une entité au FROM avec un + alias (Ex : addFrom(Contact.class, "C");) + +C'est généralement la dernière méthode qui sera la plus utilisé, l'utilisation +des alias facilitant grandement les liaisons entre les entités. + +Depuis la 2.3.4, deux méthodes ont été rajoutés pour le cas des jointures : + +- addJoin(Class entityClass, String alias, boolean fetch) : utilise un inner + join pour lier une entité à celle de la requête. Concrètement l'opérateur + JOIN Hql sera utilisé : 'FROM Contact C JOIN C.boat' :: + + TopiaContext transaction = rootContext.beginTransaction(); + ContactDAO dao = ModelDAOHelper.getBoatDAO(transaction); + TopiaQuery query = dao.createQuery("C").addJoin("C.boat", null, false); + +- addLeftJoin(Class entityClass, String alias, boolean fetch) : même chose que + le addJoin sauf que l'opérateur LEFT JOIN Hql sera utilisé. + + +Voir le `Chargement des donnees` pour l'utilisation du fetch. + +Ajout d'élément au SELECT +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Deux méthodes sont disponibles pour le cas du SELECT, une méthode addSelect +qui se chargera d'ajouter une propriété au SELECT, et une méthode setSelect +qui définira directement quel est le SELECT souhaité. Pour le cas du addSelect, +la méthode gère automatiquement l'entité principale utilisé pour instancier +la requête, il n'est donc pas nécessaire de l'ajouter manuellement. + +TODO : find an example + +Le setSelect quant à lui est utilisé pour les aggregations par exemple ou +pour récupérer des parties précises du résultat :: + + TopiaContext transaction = rootContext.beginTransaction(); + BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); + // On souhaite connaître le nombre de résultats uniquement + TopiaQuery query = dao.createQuery(). + addNotNull(Boat.NAME). + setSelect("COUNT(*)"); + +autre exemple :: + + // On souhaite récupérer uniquement les noms des navires + TopiaQuery query = dao.createQuery(). + addNotNull(Boat.NAME). + setSelect(Boat.NAME); + +Note + Pour l'ajout d'une contrainte sur l'unicité des résultats, vous pouvez + utiliser la méthode addDistinct() qui permet l'ajout du mot clé DISTINCT sur + le SELECT de la requête. + +Ajout d'élément au GROUP BY +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Dans certains cas, il peut être nécessaire d'utiliser un GROUP BY +pour les aggregations :: + + TopiaContext transaction = rootContext.beginTransaction(); + ContactDAO dao = ModelDAOHelper.getContactDAO(transaction); + // On souhaite connaître le nombre de contacts par navire + TopiaQuery query = dao.createQuery(). + setSelect("COUNT(*)"). + addGroup(Contact.BOAT); + +Ajout d'élément au ORDER BY +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Il est possible également d'ajouter un ordre aux résultats :: + + TopiaContext transaction = rootContext.beginTransaction(); + BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); + // Tous les noms des navires triés + TopiaQuery query = dao.createQuery(). + addNotNull(Boat.NAME). + setSelect(Boat.NAME). + addOrder(Boat.NAME); + +Une autre méthode est disponible pour l'ordre descendant : addOrderDesc. +Cependant rien ne vous interdit la syntaxe suivante :: + + addOrder(Boat.NAME, Boat.BUILD_YEAR + " desc"); + +Requête complexe +---------------- + +L'intérêt majeur de la TopiaQuery est de pouvoir la manipuler à travers des +méthodes tout en lui ajoutant des éléments suivant certaines conditions. +Il peut être également utile d'utiliser une TopiaQuery comme sous-requête d'une +autre. De plus certains mots clés comme EXISTS ou encore l'utilisation de +méthode HQL ne possèdent pas leurs propres méthodes. Vous pouvez cependant +utiliser la méthode de base **addWhere(String str)** qui permet l'ajout au WHERE +directement (avec ajout automatique des parenthèses). Dans ce cas, il est +souvent nécessaire d'ajouter des paramètres HQL à la requête (:monParam) qui +devront être ajouté à la TopiaQuery en utilisant la méthode +**addParam(String name, Object value)**. Ex :: + + TopiaContext transaction = rootContext.beginTransaction(); + ContactDAO dao = ModelDAOHelper.getContactDAO(transaction); + Date beginDate = ... + Date endDate = ... + TopiaQuery query1 = dao.createQuery("C"). + addWhere("C." + Contact.VALIDATION + " IS NOT NULL OR " + + "C." + Contact.CREATION_DATE + " BETWEEN :begin AND :end"). + addParam("begin", beginDate).addParam("end", endDate); + +La méthode **fullQuery()** permettra de récupérer la requête sous forme +de chaîne pour pouvoir la manipuler comme sous-requête. Il est possible +également de récupérer les paramètres via la méthode **getParams()** pour +les rajouter à la requête global :: + + // suite du code précédent + // On souhaite la date de création la plus récente sur la requête précédente + query1.setSelect("MAX(C." + Contact.CREATION_DATE + ")"); + + // Préparation de la deuxième requête + TopiaQuery query2 = dao.createQuery("C2"); + + // sélection spécifique pour un navire + if (immatriculation != null) { + query2.addEquals("C2." + Contact.BOAT + "." + Boat.IMMATRICULATION, + immatriculation); + + // Ajout d'une condition sur le navire dans la première requête + query1.addWhere("C." + Contact.BOAT + " = C2." + Contact.BOAT); + } + + // Utilisation de la première requête comme sous-requête + query2.add("C2." + Contact.CREATION_DATE + " = (" + query1.fullQuery() + ")"); + // Ajout des paramètres nécessaires de la première requête dans la deuxième + query2.addParams(query1.getParams()); + +Depuis la 2.3.4, la méthode **addSubQuery(String statement, TopiaQuery subquery)** +permet de faciliter l'injection d'une sous-requête notamment pour la gestion +des paramètres automatiquement (avec prise en charge des doublons) :: + + // Même chose que précédemment en utilisant la méthode addSubQuery + query2.addSubQuery("C2." + Contact.CREATION_DATE + " = (?)", query1); + +La requête sous forme HQL :: + + SELECT C2 FROM Contact C2 + WHERE C2.boat.immatriculation = :immatriculation + AND C2.creationDate = (SELECT MAX(C.creationDate) FROM Contact C + WHERE (C.validation IS NOT NULL OR + C.creationDate BETWEEN :begin AND :end) + AND C.boat = C2.boat); + +Attention + Il ne faut pas utiliser la méthode addEquals(String str, Object value) pour + une comparaison entre deux propriétés comme précédemment : + *query1.addWhere("C." + Contact.BOAT + " = C2." + Contact.BOAT)*. + L'appel *query1.addEquals("C." + Contact.BOAT, "C2." + Contact.BOAT)* ne + fonctionnera pas comme souhaité. + +Résultats +--------- + +Plusieurs méthodes sont disponibles pour récupérer les résultats de la requête. +Pour chaque méthode, il est nécessaire de l'appeler avec le contexte +topia. La méthode de base est la méthode execute() qui renvoie +une liste non typé à l'instar de la méthode find(...) du TopiaContext. Il +est cependant possible de récupérer directement un objet, un entier (pour +un aggregat par exemple) ou une chaîne de caractères suivant le select de la +requête. Pour le count très utile dans de nombreux cas, il est mis à disposition +la méthode **executeCount()** qui se chargera de remplacer temporairement le +select par un COUNT(*). L'avantage c'est que votre requête ne perd pas son +SELECT d'origine pour pouvoir être par exemple executé de façon différente par +la suite. + +Note + Si la requête contient un DISTINCT (via la méthode addDistinct()), le + executeCount() gèrera automatiquement la contrainte sur la requête : + "SELECT COUNT(DISTINCT B) FROM Boat B ..." + +Limitation des résultats +~~~~~~~~~~~~~~~~~~~~~~~~ + +Il est possible de limiter le nombre de résultats lors de l'exécution pour +optimiser la requête dans le cas d'une pagination par exemple. Pour ce faire +il faut utiliser les méthodes **setLimit(int start, int end)** et/ou +**setMaxResults(int max)** :: + + // 18 premiers résultats + query.setLimit(0, 17); + // équivalent à + query.setMaxResults(18); + // résultats du 50ème au 60ème + query.setLimit(49, 59); + +// depuis 2.3.4 + +Pour éviter d'embarquer ces paramètres à chaque fois qu'ils sont nécessaires +lors d'un filtrage paginée, un bean, *EntityFilter* est disponible. +Il contient les attributs suivants : + +- startIndex : index de début des résultats. + +- endIndex : index de fin des résultats. + +- orderBy : propriétés à ordonner (l'ajout des mots clés 'asc' et 'desc' est + possible). + +- referenceId : identifiant d'une référence utile à la requête. + +- referenceProperty : nom de la propriété correspondant à la valeur du referenceId. + +Exemple : Nous souhaitons les contacts 30 à 60 triés par 'creationDate' décroissant et +'personName' croissant pour un navire donné par son topiaId :: + + EntityFilter filter = new EntityFilter(); + filter.setStartIndex(30); + filter.setEndIndex(60); + filter.setOrderBy("creationDate desc, personName"); + filter.setReferenceId(boat.getTopiaId()); + // ou filter.setReference(boat); + filter.setReferenceProperty("boat"); + + TopiaQuery query = contactDAO.createQuery().addFilter(filter); + +L'intérêt de l'EntityFilter est de pouvoir l'instancier et le manipuler directement +depuis votre interface (Swing, Web, ...) et de l'utiliser sur une requête métier. +La méthode **addFilter(EntityFilter filter)** permettra d'injecter les paramètres +s'ils possèdent une valeur. + +Note + L'ordre définit par défaut est celui de création par ordre décroissant : + *topiaCreateDate desc*. + +Utilisation des DAO +~~~~~~~~~~~~~~~~~~~ + +Les DAO fournissent également quelques méthodes permettant de récupérer plus +facilement les résultats avec le type souhaité : + +- **countByQuery(TopiaQuery query)** : compte le nombre de résultats de la + requête. +- **existByQuery(TopiaQuery query)** : renvoie vrai si la requête à retourner + au moins 1 résultat. +- **findByQuery(TopiaQuery query)** : renvoie une entité (un seul résultat) +- **findAllByQuery(TopiaQuery query)** : renvoie une liste d'entités +- **findAllMappedByQuery(TopiaQuery query)** : renvoie une map d'entités avec + pour clé le topiaId de l'entité. +- **findAllMappedByQuery(TopiaQuery query, Class keyClass, String keyProperty)** : + renvoie une map d'entités avec pour clé la propriété passée en argument. + +Exemple :: + + TopiaContext transaction = rootContext.beginTransaction(); + BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); + TopiaQuery query = dao.createQuery(); + ... + // pour vérifier l'existance de résultat + boolean hasResult = dao.existByQuery(query); + + // pour savoir le nombre de résultats + int count = dao.countByQuery(query); + + // pour récupérer les résultats + Map<String, Boat> boatMap = dao.findAllMappedByQuery(query); + // ou + List<Boat> boatList = dao.findAllByQuery(query); + // ou juste le premier résultat + Boat boat = dao.findByQuery(query); + // ou avec pour clé l'immatriculation du navire (unique) + Map<Integer, Boat> boatMapImma = dao.findAllMappedByQuery(query, + Integer.class, Boat.IMMATRICULATION); + + +Résultats complexes +~~~~~~~~~~~~~~~~~~~ + +Certains cas de requête peuvent avoir des résultats plus complexes, notamment +lorsqu'il s'agit de propriétés de différentes entités ou avec l'utilisation d' +aggrégats (AVG, SUM, COUNT). Dans ce cas il faut utiliser la méthode de base +**findByQuery(TopiaQuery query)** depuis une transaction +qui renverra une liste non typée. Lorsqu'il y a plus d'un élément dans le +select la liste renvoyée est une List<Object[]>, le tableau pour chaque ligne +correspondant aux valeurs des résultats. Exemple :: + + TopiaContext transaction = rootContext.beginTransaction(); + ContactDAO dao = ModelDAOHelper.getContactDAO(transaction); + String boatImma = Contact.BOAT + "." + Boat.IMMATRICULATION; + // On souhaite le nombre de contacts par navire + TopiaQuery query = dao.createQuery(). + setSelect(boatImma, "COUNT(*)").addGroup(boatImma); + + List<Object[]> results = transaction.findByQuery(query); + // Parcours des résultats + for (Object[] result : results) { + Integer immatriculation = (Integer)result[0]; + Long count = (Long)result[1]; + } + +Note + Les aggrégats renvoient principalement un type Long et non Integer. + +Chargement des donnees +---------------------- + +Généralement une fois la requête exécutée, la transaction utilisée est directement +fermée (topiaContext.closeContext()). Dans ce cas, il est souvent nécessaire de +charger certaines entités pour éviter les malencontreuses LazyException d'Hibernate. +Plusieurs possibilités s'offrent à vous : + +Chargement automatique +~~~~~~~~~~~~~~~~~~~~~~ + +Hibernate permet de déclarer explicitement que certaines relations doivent se +charger dès la récupération des entités. Il faut pour cela utiliser le tagValue +*lazy* dans le fichier de properties du modèle. Par exemple pour charger +le navire associé à chaque contact récupéré via une requête, il faut préciser :: + + myapp.entity.Contact.attribute.boat.tagvalue.lazy=false + +(*myapp.entity.Contact* étant le nom qualifié de la classe Contact) + +Ainsi chaque contact récupéré aura automatiquement son navire associé de chargé. + +**Attention** cependant, il ne faut pas abuser du tagvalue *lazy* car sinon Hibernate +risque de charger une bonne partie de votre base de données à chaque fois, ce qui +peut s'avérer extrêment coûteux. Cette utilisation doit être limitée au cas d'une +simple association comme c'est ici le cas, le Boat chargé étant **indispensable** +à l'utilisation du Contact. + +Chargement manuel +~~~~~~~~~~~~~~~~~ + +La TopiaQuery fournit deux méthodes intéressantes pour le chargement manuelle : + + - addLoad(String...) : permet de charger les relations une fois la requête + exécutée. + + - addFetch(String...) : permet de charger les relations directement au moment + de la requête en utilisant une jointure et le mot clé 'FETCH' Hql. + +Le addLoad est pour le moment limité à des relations unitaires (autant que votre +modèle vous le permet, ex : entityA.entityB.entityC) ou à une seule relation +multiple directe ou indirecte (entityA.entitiesB). Si nous prenons le cas du +modèle d'exemple, il est possible de charger le navire associé aux contacts en +utilisant : queryContact.addLoad(Contact.BOAT); + +Dans le cas du addLoad, plusieurs requêtes seront exécutées suivant le nombre +de Contact résultats. Il est dans ce cas plus judicieux d'utiliser le addFetch +qui chargera directement les Boat au moment de la récupération des Contact : +queryContact.addFetch(Contact.BOAT); L'alias peut s'avérer indispensable pour +l'utilisation du addFetch, voir la javadoc pour l'utilisation des arguments. + +Note + Les méthodes de jointures permettent de faire un fetch directement : + addJoin(String property, String alias, boolean fetch); + Voir la partie de la documentation concernant le FROM de la requête. + +Attention + Hibernate ne supporte pas plus de 3 ou 4 jointures suivant leurs complexités ! + Il est donc important de limiter l'utilisation des fetch aux cas simples. + +Que choisir ? +~~~~~~~~~~~~~ + +- Relation unitaire (N-1) obligatoire : utiliser le tagValue *lazy* + +- Requête relativement simple (moins de deux jointures) : utiliser le addFetch + +- Requête complexe : utiliser le addLoad + +- Si addLoad non utilisable (trop de chargement de collections) : effectuer un + chargement manuel en parcourant les résultats. Pour le chargement d'une + entité simple, il suffit d'utiliser le getter correspondant pour la charger, + tandis que pour une collection, l'appel à la méthode size associée permet de + charger l'intégralité des éléments. + + + Property changes on: trunk/topia-persistence/src/site/rst/user/TopiaQuery.rst ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: trunk/topia-persistence/src/site/rst/user/continue_devel.rst =================================================================== --- trunk/topia-persistence/src/site/rst/user/continue_devel.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/user/continue_devel.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,32 @@ +========================== +Continuer le développement +========================== + +Vous avez maintenant les clés pour développer votre application. Voici quelques +éléments qui vous permettront de poursuivre les développements. + +Gestion des évènements +====================== + +TODO + +Les visiteurs d'entités +======================= + +TODO + +Écrire une migration +==================== + +TODO + +Débugguer l'application +======================= + + * Ajouter ``-Deugene.verbose`` sur la ligne de commande pour voir ce que + EUGene fait pendant la phase de génération. + + * Ne pas hésiter à examiner les fichiers ``.hbm.xml`` générés pour voir + s'ils correspondent bien à ce que vous attendiez. De même, on + peut examiner le fichier ``.objectmodel`` pour voir si l'interprétation + du fichier zargo est bien celle qu'on attend. Added: trunk/topia-persistence/src/site/rst/user/extend_model.rst =================================================================== --- trunk/topia-persistence/src/site/rst/user/extend_model.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/user/extend_model.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,111 @@ +================= +Étendre le modèle +================= + +Nous avons réussi à manipuler les entités d'un modèle simple. Voyons comment +rendre notre modèle plus complet pour nous rapprocher de l'utilisation de ToPIA +dans le contexte d'une véritable application. + +Ajouter une méthode à une entité +================================ + +Dans ArgoUML, vous pouvez ajouter une méthode sur une entité. Pour cela, +ajouter la méthode dans le modèle, sur l'entité elle-même. Si besoin, il +faudra ajouter au modèle les types des paramètres ou de la valeur de retour. + +ToPIA utilise le patron de conception `Generation Gap`_ pour séparer le code +généré du code écrit par le développeur. Ainsi, le ré-génération n'écrase +que du code généré et jamais du code utilisateur. Vous ne devez jamais +modifier les classe générées mais seulement toucher aux implémentations +qui héritent de ces classes. + +Vous remarquerez que ToPIA a bien ajouté la méthode dans l'interface de +l'entité mais à laisser l'implémentation abstraite. C'est donc à vous +d'écrire le code dans le Impl. + +Forcer le chargement d'une association +====================================== + + + +Utiliser une clé métier pour identifier les entité (naturalId) +============================================================== + +Chaque entité possède une cré primaire topiaId, mais dans certains cas il est +important d'avoir une notion d'unicité sur une ou plusieurs propriétés d'une +entité, ce qu'on appele une clé métier. Le comportement souhaité serait de +préserver l'unicité sur ces propriétés ainsi que la création d'un index pour +optimiser l'accès aux données. + +Il est donc nécessaire de préciser cette notion au niveau du modèle, cela +par le biais du tagValue (également propriété hibernate) **naturalId** :: + + fr.ird.observe.entities.referentiel.ParametrageTaillePoidsFaune.class.tagvalue.naturalIdMutable=false + fr.ird.observe.entities.referentiel.ParametrageTaillePoidsFaune.attribute.sexe.tagvalue.naturalId=true + fr.ird.observe.entities.referentiel.ParametrageTaillePoidsFaune.attribute.ocean.tagvalue.naturalId=true + fr.ird.observe.entities.referentiel.ParametrageTaillePoidsFaune.attribute.ocean.tagvalue.notNull=false + fr.ird.observe.entities.referentiel.ParametrageTaillePoidsFaune.attribute.espece.tagvalue.naturalId=true + +Ici, les propriétés "sexe", "ocean" et "espece" forment la clé métier de +l'entité "ParametrageTaillePoidsFaune". Par défaut les propriétés +d'une clé métier sont non null, mais il est possible de préciser dans certains +cas qu'une propriété peut l'être (comme ici avec "ocean"). + +Le naturalId provoque trois résultats : + +- création d'un index unique en base. +- vérification dans hibernate de l'intégrité de l'entité à la création : + il est donc nécessaire de créer l'entité avec des valeurs pour les propriétés + de la clé métier (méthode create sur le dao). +- impossibilité de modifier les valeurs de ces propriétés sur une entité + existante ; à moins de le préciser dans la configuration via le tagValue + "naturalIdMutable" placé à "true" (déconseillé). + + +Ajouter des requêtes complexes +============================== + +Ajouter une méthode à un DAO +---------------------------- + +Il est possible d'étendre un DAO avec des méthodes définies à partir du modèle +(méthode différente entre version 2.2 et 2.4). + +Il suffit de créer une interface contenant les méthodes à ajouter au dao. +Cette interface doit avoir le stéréotype <<dao>>. De plus l'interface doit +dépendre (lien de dépendance nommé explicitement 'dao') de la classe de l'entité. +Le DAOImpl ne sera pas généré et devra être défini à la charge du développeur. + +Exemple (présent dans topiatest.zargo dans les sources de topia-persistence) : + +Ajout d'une méthode findAllByCompany sur une entité Contact. Chaque société à un ensemble d'employés (Employee) qui ont des +contacts (Tel, Adresse, ...). Ces contacts ne sont pas unique à chaque employé. Il peut être intéressant de connaître directement +tous les contacts d'une société directement avec le DAO:: + + public class ContactDAOImpl<E extends Contact> extends ContactDAOAbstract<E> { + + @Override + public Set<Contact> findAllByCompany(Company company) throws TopiaException { + ... + } + + } + +Une erreur de compilation apparaîtra si ce fichier n'existe pas (car non généré). La signature de la méthode +est présente dans le DAOAbstract (ici ContactDAOAbstract), d'où le @Override. + +Note + L'ajout du throws TopiaException est automatique et n'a pas besoin d'être spécifié au niveau du modèle. + +Implémenter la méthode avec TopiaQuery +-------------------------------------- + +Vous pouvez, dans le DAO écrire vos requêtes directement en HQL, toutefois, l'API TopiaQuery vous +permet d'écrire les requêtes avec une API générée, qui suit les évolutions du modèle plutôt que +de coder le HQL en dur. + +Voir TopiaQuery_. + + +.. _Generation Gap: http://fr.wikibooks.org/wiki/Patrons_de_conception/Generation_gap +.. _TopiaQuery: TopiaQuery.html \ No newline at end of file Copied: trunk/topia-persistence/src/site/rst/user/howto.rst (from rev 2251, trunk/topia-persistence/src/site/rst/howto.rst) =================================================================== --- trunk/topia-persistence/src/site/rst/user/howto.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/user/howto.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,155 @@ +.. - +.. * #%L +.. * ToPIA :: Persistence +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2004 - 2011 CodeLutin, Chatellier Eric +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 of the +.. * License, or (at your option) any later version. +.. * +.. * This program is distributed in the hope that it will be useful, +.. * but WITHOUT ANY WARRANTY; without even the implied warranty of +.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.. * GNU General Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - +How to +====== + +Ce document a pour objectif de prendre en main le framework Topia. Le document +est constitué de 4 parties, la modélisation, la génération, la configuration et +l'utilisation. + +Modélisation +------------ + +La première étape constiste à réaliser le modèle UML soit avec Argouml +(http://argouml.tigris.org) soit avec Poséidon (http://www.gentleware.com). + +Le stérotype «entity» sur les classes permet de préciser que la classe est +persistée par Topia. D'autre stérotypes (extern, service, ...) sont disponibles +mais ne sont pas présentés. + +Le fichier de modélisation peut être complété par un fichier de configuration +nommé <nom fichier modélisation>.properties. Il contient des informations +techniques propres aux librairies utilisé par Topia. + +Exemple : + +:: + + # Précise comment est mappé un type + # model.tagvalue.<type java>=<type base de donnée> + model.tagvalue.java.lang.String=text + + # Précise le schema de la base de données par défaut + # model.tagvalue.dbSchema=<nom schéma> + model.tagvalue.dbSchema=test + + # Précise l'entête de l'ensemble des fichiers générés + # model.tagvalue.copyright=<valeur> + model.tagvalue.copyright=/* *##%\n Copyright (C) 2011 Code Lutin\n *##% */ + + # Force le chargement d'un attribut + # <nom paquetage>.<nom entité>.attribute.<nom attribut>.tagvalue.lazy=false + org.codelutin.Person.attribute.association.tagvalue.lazy=false + +Génération +---------- + +La génération des fichiers Topia se font par l'utilisation du plugin maven +Eugene_. Ce plugin est disponible sur le repository central. + +Configuration du plugin maven : + +:: + + <plugin> + <groupId>org.nuiton.eugene</groupId> + <artifactId>maven-eugene-plugin</artifactId> + <version>2.3.2</version> + <executions> + <execution> + <phase>process-sources</phase> + <!--Configuration of model generator--> + <configuration> + <inputs>zargo</inputs> + <fullPackagePath>org.nuiton.topiatest</fullPackagePath> + <defaultPackage>org.nuiton.topiatest</defaultPackage> + <extractedPackages>org.nuiton.topiatest</extractedPackages> + <templates> + org.nuiton.topia.generator.TopiaMetaTransformer + </templates> + </configuration> + <goals> + <goal>smart-generate</goal> + </goals> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.nuiton.topia</groupId> + <artifactId>topia-persistence</artifactId> + <version>2.5.2</version> + <scope>compile</scope> + </dependency> + </dependencies> + </plugin> + +Le plugin utilise Eugene_ avec les templates de génération de Topia, le +fichier argouml ou poséidon doit se trouver dans le répertoire +``src/main/xmi``. Les fichiers sont générés dans le répertoire +``target/generated-sources/java``. Il faut préciser au plugin les paquetages +à traiter avec le ``defaultPackage`` et ``extractedPackages``. + +Ajout dans des dépendances de Topia pour la compilation des fichiers générés : + +:: + + <dependency> + <groupId>org.nuiton.topia</groupId> + <artifactId>topia-persistence</artifactId> + <version>2.5.2</version> + <scope>compile</scope> + </dependency> + +Pour une classe modélisée, nous retrouvons 6 fichiers : + * Une interface + * Une classe abstraite + * Une implantation + * Une configuration hibernate + * Un DAO abstrait + * Une implantation du DAO + +Une classe Helper est aussi générée, permettant l'accès à l'ensemble des DAO. + +Configuration +------------- + +Un fichier contenant les informations de connexion à la base de données et de +configuration de Topia doit être créé au niveau des ressources du projet. +Par convention, ce fichier est nommé ``TopiaContextImpl.properties``. + + +Utilisation +----------- + +Implantation des méthodes +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Si des méthodes ont été définies dans le modèle de données, il faut créer +l'implantation correspondante. Le paquetage doit porter le même nom que celui de +la génération. + + + +.. _Eugene: http://maven-site.nuiton.org/eugene/ Property changes on: trunk/topia-persistence/src/site/rst/user/howto.rst ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: trunk/topia-persistence/src/site/rst/user/start.rst =================================================================== --- trunk/topia-persistence/src/site/rst/user/start.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/user/start.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,222 @@ +================================ +Démarrer un projet ToPIA - Maven +================================ + +Comment démarrer un projet à partir de rien. + +Créer le projet +=============== + +Pour commencer, il faut créer un projet maven en respectant les conventions +habituelles. Partons d'un projet maven vide : + +:: + + mvn archetype:generate -DgroupId=com.masociete -DartifactId=monapplication -DarchetypeArtifactId=maven-archetype-archetype + +Ajoutez un dossier ``src/main/xmi``, c'est ici que nous allons placer le modèle. + +:: + + topia-tutorial + ├── pom.xml + └── src + ├── main + │ ├── java + │ │ └── org + │ │ └── nuiton + │ │ └── topia + │ │ └── tutorial + │ │ └── library + │ ├── resources + │ │ ├── library-config.properties + │ │ └── log4j.properties + │ └── xmi + │ ├── library.properties + │ └── library.zargo + └── test + ├── java + └── resources + +Dans le pom, on ajoute ToPIA en dépendance, et on configure la génération : + +:: + + <properties> + <topiaVersion>2.5.4</topiaVersion> + <eugeneVersion>2.3.3</eugeneVersion> + </properties> + + <dependencies> + <dependency> + <groupId>org.nuiton.topia</groupId> + <artifactId>topia-persistence</artifactId> + <version>${topiaVersion}</version> + </dependency> + </dependencies> + + + <plugins> + + <!-- ... --> + + <plugin> + <groupId>org.nuiton.eugene</groupId> + <artifactId>maven-eugene-plugin</artifactId> + <version>${eugeneVersion}</version> + <configuration> + <inputs>zargo</inputs> + <resolver>org.nuiton.util.FasterCachedResourceResolver</resolver> + </configuration> + <executions> + <execution> + <id>generate-entities</id> + <phase>generate-sources</phase> + <configuration> + <!-- Corresponding to extracted package from zargo file --> + <fullPackagePath>org.nuiton.topia.tutorial.library</fullPackagePath> + <!-- DefaultPackage used for DAOHelper generation --> + <defaultPackage>org.nuiton.topia.tutorial.library</defaultPackage> + <templates> + org.nuiton.topia.generator.TopiaMetaTransformer + </templates> + </configuration> + <goals> + <goal>smart-generate</goal> + </goals> + </execution> + </executions> + </plugin> + + </plugins> + + +Créer le modèle +=============== + +Utiliser ArgoUML pour décrire le modèle +--------------------------------------- + +Avec ArgoUML, créez un nouveau modèle et enregistrez-le dans ``xmi``. Nous +allons créer un modèle simplifié pour une application de gestion de +bibliothèque. + +Nous avons modélisé les entités ``Book`` et ``Author`` avec les champs +appropriés. Faites attention à bien placer les entités dans le bon package, sinon +elles ne seront pas générées. Pour que ToPIA sache que ces classes décrivent +des entités qui ont vocation à être sauvées en base, il faut leur ajouter le +stéréotype ``entity``. + +N'oubliez pas de donner un nom et une version au modèle. + +Les données associées aux éléments du modèle +-------------------------------------------- + +Le modeleur n'est pas suffisant pour décrire toute les subtilités du modèle. +Le modèle se voulant indépendant de la plate-forme cible, on ne peut y inclure +directement des notions spécifiques à ToPIA. C'est pourquoi nous allons pouvoir +ajouter ces informations spécifiques via le fichier ``library-config.properties``. + + +C'est prêt ! +============ + +Il suffit de construire l'application avec maven. + +:: + + mvn compile + + +La compilation va provoquer la phase de génération. Si on examine le contenu +de notre dossier target : + +:: + + topia-tutorial + ├── pom.xml + ├── src + │ ├── main + │ │ ├── java + │ │ │ └── org + │ │ │ └── nuiton + │ │ │ └── topia + │ │ │ └── tutorial + │ │ │ └── library + │ │ ├── resources + │ │ │ ├── library-config.properties + │ │ │ └── log4j.properties + │ │ └── xmi + │ │ ├── library.properties + │ │ └── library.zargo + │ └── test + │ ├── java + │ └── resources + └── target + ├── classes + │ ├── library-config.properties + │ ├── log4j.properties + │ └── org + │ └── nuiton + │ └── topia + │ └── tutorial + │ └── library + │ ├── LibraryConfig.class + │ └── model + │ ├── AuthorAbstract.class + │ ├── Author.class + │ ├── AuthorDAOAbstract.class + │ . + │ . + │ . + └── generated-sources + ├── annotations + ├── java + │ └── org + │ └── nuiton + │ └── topia + │ └── tutorial + │ └── library + │ └── model + │ ├── AuthorAbstract.java + │ ├── AuthorDAOAbstract.java + │ ├── AuthorDAOImpl.java + │ ├── AuthorDAO.java + │ ├── AuthorImpl.hbm.xml + │ ├── Author.java + │ ├── BookAbstract.java + │ ├── BookDAOAbstract.java + │ ├── BookDAOImpl.java + │ ├── BookDAO.java + │ ├── BookImpl.hbm.xml + │ ├── BookImpl.java + │ ├── Book.java + │ └── LibraryDAOHelper.java + ├── models + │ ├── library.objectmodel + │ └── library.properties + └── xmi + ├── library.properties + └── library.xmi + + + +On peut voir que ToPIA a généré ``LibraryDAOHelper`` qui va nous permettre de +récupérer les différents DAO et, pour chaque entité de notre modèle : + * Une interface + * Une classe abstraite, qui implémente déjà tout le contrat + * Une implantation (vide, seulement les constructeurs) + * Un DAO abstrait + * Une implantation du DAO + * Un fichier de mapping hibernate (*.hbm.xml) + +Comme il s'agit d'une phase de compilation, maven va ajouter tout le code généré aux +classpath le code généré sera compilé et lié en même temps que le reste de votre application. +Tous les fichiers .class se retrouveront dans target/classes, dans la suite du processus, on +ne distingue plus le code généré du code utilisateur. + +Par la suite, si vous changez le modèle, tout sera re-généré. À chaque ``clean`` +via maven, tout ce qui a été généré est effacé. Vous pouvez donc re-généré autant +de fois que nécessaire. Attention, Maven ne détecte pas le changement du modèle +si le fichier .zargo a été modifié : il faut donc faire un clean à chaque fois +afin de forcer le re-génération du modèle dans sa dernière version. Added: trunk/topia-persistence/src/site/rst/user/start_using_api.rst =================================================================== --- trunk/topia-persistence/src/site/rst/user/start_using_api.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/user/start_using_api.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,112 @@ +====================== +Commencer à développer +====================== + +Nous pouvons maintenant ouvrir le projet dans un IDE et commencer à développer. + +Configurer une base de données embarquée +======================================== + +Pour assurer la persitance de nos entités, il faut faire appel à +un SGBD supporté par Hibernate. Pour cela, un peu de configuration JDBC est +nécessaire. Dans le fichier ``src/main/resources/library-config.properties``, on +définit + + +:: + + # Pour démarrer, on utilisera une base H2 + hibernate.connection.url=jdbc:h2:file:target/db/h2data + + # Configuration JDBC + hibernate.dialect=org.hibernate.dialect.H2Dialect + hibernate.connection.username=sa + hibernate.connection.password= + hibernate.connection.driver_class=org.h2.Driver + + # On demande à Hibernate de créer toutes les tables nécessaires + # au besoin + hibernate.hbm2ddl.auto=update + + # Un peu de config pour savoir ce que fait hibernate, cette directive + # affiche toutes les requêtes effectuées sur la base dans la console + hibernate.show_sql=true + + +Développer un premier service +============================= + +Gestion des transactions +------------------------ + +>>> Properties conf = new Properties(); +URL url = Resource.getURL("TopiaContextImpl.properties"); +conf.load(new FileInputStream(new File(url.toURI()))); + +Permet de charger un fichier contenant les informations de connexion à la base +et de configuration de Topia. + +>>> TopiaContext rootContext = TopiaContextFactory.getContext(conf); + +Récupère le context de départ pour la création de sous context pour la gestion +des entités. + +>>> TopiaContext transaction = rootContext.beginTransaction(); + +Création d'un sous context pour la gestion des entités. + +>>> transaction.commitTransaction(); + +Validation de l'état du context, les modifications des entités sont reportées +dans la base de données. + +>>> transaction.rollBackTransaction(); + +Invalidation de l'état du context, les modifications des entités ne sont pas +reportées dans la base de données. + +>>> transaction.closeContext(); + +Relâche la connexion JDBC d'un sous context et de ses sous contexts sans +validation de l'état des contexts. + +>>> rootContext.closeContext(); + +Relâche l'ensemble des ressources (cache, pools, ...) et relâche la connexion +JDBC des sous contexts avec validation de l'état des contexts. + +Manipulation des entités +------------------------ + +>>> PersonDAO personDAO = <nom modele>DAOHelper.getPersonDAO(transaction); + +Récupération d'un DAO pour accéder à une entité. + +>>> Person person = personDAO.findByTopiaId(id); + +Les méthodes find permettent de récupérer une ou plusieures entités selon différents +critères. + +>>> person.setName("tutu"); + +Manipulation de l'entité par les getters et setters. + +>>> Person person = personDAO.create(); + +Création d'une entité. Si vous utilisez l'instanciation classique java avec le +new, l'entité n'est pas persistée. + +>>> personDAO.update(person); + +Modification d'un entité. + +>>> personDAO.delete(person); + +Suppression d'une entité. + +Exemple complet +--------------- + +Un exemple complet dans MainTest_. + +.. _MainTest: http://svn.nuiton.org/svn/topia/trunk/topia-tutorial/src/test/java/org/nuito... \ No newline at end of file Copied: trunk/topia-persistence/src/site/rst/user/tagvalues.rst (from rev 2250, trunk/topia-persistence/src/site/rst/tagvalues.rst) =================================================================== --- trunk/topia-persistence/src/site/rst/user/tagvalues.rst (rev 0) +++ trunk/topia-persistence/src/site/rst/user/tagvalues.rst 2011-04-16 16:41:18 UTC (rev 2261) @@ -0,0 +1,78 @@ +.. - +.. * #%L +.. * ToPIA :: Persistence +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2004 - 2011 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 of the +.. * License, or (at your option) any later version. +.. * +.. * This program is distributed in the hope that it will be useful, +.. * but WITHOUT ANY WARRANTY; without even the implied warranty of +.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.. * GNU General Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - +Tag values +========== + +Topia templates are customizable using tag values. + +Here are current tag values defined in topia. They can be defined in source +model or model property file. + +Topia tag values +---------------- + ++--------------------------+-----------+----------------------------------------------------+ +| Name | Category | Description | ++==========================+===========+====================================================+ +| orderBy | Hibernate | Define order-by attribute in hibernate mapping for | +| | | a specific relation | ++--------------------------+-----------+----------------------------------------------------+ +| dbName | Hibernate | Database table name | ++--------------------------+-----------+----------------------------------------------------+ +| dbSchema | Hibernate | Database schema | ++--------------------------+-----------+----------------------------------------------------+ +| length | Hibernate | Attribute length in database | ++--------------------------+-----------+----------------------------------------------------+ +| annotation | all | Add annotation on attribute | ++--------------------------+-----------+----------------------------------------------------+ +| copyright | all | Generated files header copyright | ++--------------------------+-----------+----------------------------------------------------+ +| access | hibernate | Field access type | ++--------------------------+-----------+----------------------------------------------------+ +| i18n | entity | Generate i18n ??? | ++--------------------------+-----------+----------------------------------------------------+ +| naturalId | hibernate | Generate hibernate naturalId | ++--------------------------+-----------+----------------------------------------------------+ +| naturalIdMutable | hibernate | Tell hibernate if a natural id key is mutable | ++--------------------------+-----------+----------------------------------------------------+ +| inverse | hibernate | To configure with part of a N-N relation is inverse| ++--------------------------+-----------+----------------------------------------------------+ +| lazy | hibernate | Hibernate multiple attribute fetch property | +| | | (default to ''hibernate default value'') | ++--------------------------+-----------+----------------------------------------------------+ +| notNull | hibernate | Hibernate attribute not null property | +| | | (default to ''hibernate default value'') | ++--------------------------+-----------+----------------------------------------------------+ +| hibernateProxyInterface | hibernate | To not generate proxy information in | +| | | hibernate mappings. | ++--------------------------+-----------+----------------------------------------------------+ + + +Eugene tag values +----------------- + +Eugene contains also his tag values. See `eugene documentation`_ for more détails. + +.. _eugene documentation: http://maven-site.nuiton.org/eugene/ Property changes on: trunk/topia-persistence/src/site/rst/user/tagvalues.rst ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Modified: trunk/topia-persistence/src/site/site_fr.xml =================================================================== --- trunk/topia-persistence/src/site/site_fr.xml 2011-04-16 16:25:22 UTC (rev 2260) +++ trunk/topia-persistence/src/site/site_fr.xml 2011-04-16 16:41:18 UTC (rev 2261) @@ -38,25 +38,32 @@ </breadcrumbs> <menu ref="parent"/> - + + <menu name="Tutoriel" inherit="top"> + <item name="Démarrer avec ToPIA et Maven" href="user/start.html" /> + <item name="Commencer à développer avec l'API ToPIA" href="user/start_using_api.html" /> + <item name="Étendre le modèle" href="user/extend_model.html" /> + <item name="Continer le développement" href="user/continue_devel.html" /> + </menu> + <menu name="Utilisateur" inherit="top"> <item name="Presentation" href="index.html" /> - <item name="Utilisation" href="howto.html" /> - <item name="Génération des modèles" href="ModelGeneration.html"/> - <item name="Tag values" href="tagvalues.html" /> - <item name="TopiaQuery" href="TopiaQuery.html"/> - <item name="Gestion des evenements" href="event.html"/> - <item name="FAQ" href="FAQ.html"/> + <!--item name="Utilisation" href="user/howto.html" /> + <item name="Génération des modèles" href="user/ModelGeneration.html"/> + <item name="Tag values" href="user/tagvalues.html" /--> + <item name="TopiaQuery" href="user/TopiaQuery.html"/> + <item name="FAQ" href="user/FAQ.html"/> </menu> <menu name="Developpeur"> - <item name="Todo" href="Todo.html"/> - <item name="Mapping hibernate" href="HibernateMapping.html"/> - <item name="Isolation" href="Isolation.html"/> - <item name="Schema migration" href="SchemaMigration.html"/> - <item name="Securité" href="security.html"/> - <item name="TopiaContextFactory" href="Devel.html"/> - <item name="Projets similaires" href="project.html"/> + <item name="Todo" href="devel/Todo.html"/> + <item name="Mapping hibernate" href="devel/HibernateMapping.html"/> + <item name="Isolation" href="devel/Isolation.html"/> + <item name="Schema migration" href="devel/SchemaMigration.html"/> + <item name="Securité" href="devel/security.html"/> + <item name="TopiaContextFactory" href="devel/Devel.html"/> + <item name="Projets similaires" href="devel/project.html"/> + <item name="Gestion des evenements" href="user/event.html"/> </menu> <menu name="Téléchargement">
participants (1)
-
bleny@users.nuiton.org