Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Prochaine révision
Révision précédente
enseignement:tp:bd:tp-orm:2015 [2015/09/18 17:03]
ecoquery créée
enseignement:tp:bd:tp-orm:2015 [2015/09/25 17:47] (Version actuelle)
rthion [Introduction]
Ligne 1: Ligne 1:
 ====== Mise en oeuvre de mappings Objet/Relationnels ====== ====== Mise en oeuvre de mappings Objet/Relationnels ======
  
-** Enonce en cours de modification **+Ce TP est à réaliser en binômes. Il est à rendre pour le **05/10/2015** via un projet forge (voir [[#rendu|la section Rendu]]). 
 + 
 +=== Mises à jour de cette page=== 
 + 
 +  * 22/10/2015: ajout @OrderColumn dans les remarques, exécution de l'application via maven
  
 === Evaluation === === Evaluation ===
  
-Le TP sera évalué en deux fois. Une première évaluation sur le code produit, en particulier, mais pas uniquement, l'implémentation des méthodes de la classe ''RecetteORMDAO''. Une deuxième évaluation aura lieu sous la forme d'une évaluation écrite (réalisée en cours ou en TD) portant sur des points techniques du TP.+Le TP sera évalué en deux fois. Une première évaluation sur le code produit, en particulier, mais pas uniquement, l'implémentation des méthodes de la classe ''RecetteORMDAO''. Une deuxième évaluation aura lieu sous la forme d'une évaluation écrite (réalisée en cours ou en TD, la date sera communiquée en avance par mail) portant sur des points techniques du TP.
  
-<note important>Afin de pouvoir évaluaer fonctionnellement le code rendu, il est demandé de ne pas modifier la signature des méthodes publiques fournies dans le projet de base. Il est par contre possible, et parfois nécessaire, d'ajouter d'autres méthodes aux classes existantes.</note>+<note important>Afin de pouvoir évaluer fonctionnellement le code rendu, il est demandé de ne pas modifier la signature des méthodes publiques fournies dans le projet de base. Il est par contre possible, et souvent nécessaire, d'ajouter d'autres méthodes et/ou d'autres champs aux classes existantes. Pour les classes ne comportant pas de constructeur, il est demandé d'ajouter un constructeur vide si vous ajoutez votre propre constructeur avec arguments.</note>
  
 +=== Rendu ===
  
 +Il est demandé de créer un projet forge pour ce TP. On poussera (via ''hg push ...'') la version finale du TP vers ce projet au plus tard le **05/10/2015**. On passera par [[http://tomusss.univ-lyon1.fr|tomuss]] afin de communiquer l'identifiant du projet forge: il faudra remplir la case ''Forge_TP1'' de l'UE MIF18 Gestion de Données pour le Web, avec l'identifiant du projet forge. Par exemple si l'url mercurial de votre projet est ''https://forge.univ-lyon1.fr/hg/p34567890-mif18-tp1'':
 +  * Il faut saisir ''p34567890-mif18-tp1''
 +  * Il **ne faut pas** saisir ''https://forge.univ-lyon1.fr/hg/p34567890-mif18-tp1'', ni ''http://forge.univ-lyon1.fr/project/p34567890-mif18-tp1''
  
 ===== Introduction ===== ===== Introduction =====
Ligne 16: Ligne 24:
  
 Quelques liens: Quelques liens:
-  * [[http://java.sun.com/javaee/5/docs/api/|API JEE 5]] -> package ''javax.persistence''+  * [[https://docs.oracle.com/javaee/7/api/|API JEE 7]] -> package ''javax.persistence''
   * [[http://en.wikipedia.org/wiki/Java_Persistence_API|JPA]]   * [[http://en.wikipedia.org/wiki/Java_Persistence_API|JPA]]
 +  * [[https://en.wikibooks.org/wiki/Java_Persistence|Wikibook sur JPA]]
   * [[https://www.hibernate.org/|Hibernate]]   * [[https://www.hibernate.org/|Hibernate]]
-  * [[http://java.sun.com/javaee/5/docs/tutorial/doc/bnbpz.html|Tutoriel JPA]] en anglais+  * [[http://docs.oracle.com/javaee/7/tutorial/partpersist.htm#BNBPY|Tutoriel JPA]] en anglais
   * {{:enseignement:bdav:mapping-objets-relationnel-xml.pdf|Transparents du cours ORM}}   * {{:enseignement:bdav:mapping-objets-relationnel-xml.pdf|Transparents du cours ORM}}
   * [[enseignement:tp:bd:tp-orm|Un ancien TP sur les ORM]]   * [[enseignement:tp:bd:tp-orm|Un ancien TP sur les ORM]]
 +
 +==== Contexte: gestion d'une base de recettes ====
 +
 +Dans ce TP on considèrera une application permettant de gérer une base de recettes de cuisine. 
 +L'application permettra d'ajouter des ingrédients et des recettes et, dans une certaine mesure, de les modifier.
 +
 +Un projet embryonnaire est fourni et décrit plus en détails ci-dessous. Dans le cadre de ce TP, il faudra compléter les classes des packages ''univlyon1.recettes.modele'' et ''univlyon1.recettes.dao''. La classe ''RecetteApp'' et les classes du package ''univlyon1.recette.actions'' n'ont pas à être modifiées.
  
 ===== Projet embryonnaire ===== ===== Projet embryonnaire =====
  
-Maven est un utilitaire de compilation/exécution/test de projet Java qui sera utilisé dans le cadre des TP de l'UE.+Maven est un utilitaire de compilation/exécution/test de projet Java qui sera utilisé dans le cadre de ce TP.
 Configurer Maven comme indiqué [[enseignement:aide:logiciels#maven|dans l'aide]]. Configurer Maven comme indiqué [[enseignement:aide:logiciels#maven|dans l'aide]].
 Voir également le [[enseignement:tp:forge-maven|TP maven/forge]]. Voir également le [[enseignement:tp:forge-maven|TP maven/forge]].
  
-Télécharger et décompresser le projet de base: {{:enseignement:tp:bd:tp-orm:inf1018m-orm.zip|}} ou mieux le cloner depuis la forge+Si ce n'est déjà fait, créer un nouveau projet forge pour ce TP et le cloner. 
-<code shell+Récupérer ensuite dans ce dépôt local le contenu du projet de base: 
-hg clone https://forge.univ-lyon1.fr/hg/inf1018m-orm+<code sh
 +hg pull https://forge.univ-lyon1.fr/hg/inf1018m-orm 
 +hg update
 </code> </code>
 +
 +En cas de problème d'accès à la forge, télécharger et décompresser le {{:enseignement:tp:bd:tp-orm:inf1018m-orm.zip|projet de base}}  dans un autre répertoire. Effectuer ensuite depuis le dépôt de votre projet un ''hg pull xxx'' où xxx est le répertoire ou vous avez extrait l'archive téléchargée.
  
 Un projet Maven possède deux répertoires de sources: src/main et src/test. Le premier contient les classes "métier" alors que le second ne contient que le code de test. Un projet Maven possède deux répertoires de sources: src/main et src/test. Le premier contient les classes "métier" alors que le second ne contient que le code de test.
  
-Dans Eclipse, il faut importer le projet en utilisant ''Import existing maven project''. Le projet peut être directement ou vert dans Netbeans. Il est également possible d'utiliser IntelliJ en important le projet et en spécifiant d'utiliser un type de projet maven à l'import.+Dans Eclipse, il faut importer le projet en utilisant ''Import existing maven project''. Le projet peut être directement ouvert dans Netbeans/IntelliJ.
  
-<note tip>Il est possible d'utiliser la ligne de commande plutot que l'IDE. Pour compiler et tester le mapping depuis le répertoire du projet((à priori ''inf1018m-orm'')), faire:<code>mvn test</code></note>+<note tip>Il est possible d'utiliser la ligne de commande plutôt que l'IDE. Pour compiler et tester le mapping depuis le répertoire du projet((à priori ''inf1018m-orm'')), faire:<code>mvn test</code> 
 + 
 +Pour lancer l'application, faire (après avoir mis à jour votre dépôt via une des deux méthodes ci-dessus si vous avez commencé le TP lundi 21/09) <code>mvn exec:java</code>  
 +</note>
  
 Le fichier ''pom.xml'' contient les dépendances sur les bibliothèques nécessaires au TP. Le fichier ''pom.xml'' contient les dépendances sur les bibliothèques nécessaires au TP.
Ligne 45: Ligne 68:
  
  
-==== Base de donnée et schema relationnel ====+==== Base de donnée et schéma relationnel ====
  
 === Installation et démarrage de la base H2 === === Installation et démarrage de la base H2 ===
  
-[[http://h2datadase.com|H2]] est une base de donnée Java qui sera utilisée dans ce TP((Le TP fonctionne aussi sous d'autres SGBD comme PostgreSQL à condition d'adapter le fichier ''persistence.xml''. Il est cependant demandé de le faire fonctionner sur H2 pour faciliter le travail de correction)). Télécharger et décompresser le fichier [[http://liris.cnrs.fr/~ecoquery/files/h2-2014-08-06.zip|h2-2014-08-06.zip]] et lancer la console H2 à l'aide du fichier ''h2.sh'' ou ''h2.bat''. Une page web s'ouvre. Utiliser la configuration ''Generic H2 (Server)''.+[[http://h2datadase.com|H2]] est une base de donnée Java qui sera utilisée dans ce TP((Le TP fonctionne aussi sous d'autres SGBD comme PostgreSQL à condition d'adapter le fichier ''persistence.xml''. Il est cependant demandé de le faire fonctionner sur H2 car c'est cette base qui sera utilisée pour tester le rendu)). Télécharger et décompresser le fichier [[http://liris.cnrs.fr/~ecoquery/files/h2-2014-08-06.zip|h2-2014-08-06.zip]] et lancer la console H2 à l'aide du fichier ''h2.sh'' ou ''h2.bat''. Une page web s'ouvre. Utiliser la configuration ''Generic H2 (Server)''.
 <note important> <note important>
 Vérifier la configuration: Vérifier la configuration:
Ligne 58: Ligne 81:
 </note> </note>
 Tester la connexion, puis se connecter. Tester la connexion, puis se connecter.
 +
 +<note warning>La console H2 peut avoir du mal à démarrer. Si le navigateur de s'ouvre pas: essayer de décompresser H2 sur le disque local dans ''C:\Temp'' ou dans ''/tmp''. Si le navigateur s'ouvre mais n'affiche rien, changer l'adresse IP (avant le '':8082'') en ''localhost''.</note>
  
 === Mise en place du schéma === === Mise en place du schéma ===
Ligne 97: Ligne 122:
  
 Un embryon de modèle objet correspondant aux données en base peut être trouvé dans le package ''univlyon1.recettes.modele''. Un embryon de modèle objet correspondant aux données en base peut être trouvé dans le package ''univlyon1.recettes.modele''.
-Ces classes contiennent un certain nombre de méthodes publiques utilisées par l'application fournie.+Ces classes contiennent un certain nombre de méthodes publiques utilisées pour implémenter l'application fournie
 +Dans le cadre de ce TP, il faudra compléter ces classes en les annotant via JPA.  
 +Il sera aussi nécessaire de leur ajouter des méthodes et/ou des champs. 
 + 
 +Voir la section [[#remarques_additionnelles|remarques additionnelles]] pour plus d'information sur les annotations JPA.
  
 === DAO === === DAO ===
  
 L'interaction avec la base de donnée est encapsulée dans la classe ''RecetteORMDAO''. L'interaction avec la base de donnée est encapsulée dans la classe ''RecetteORMDAO''.
-Les méthodes de cette classes sont vides+Les méthodes de cette classes ont été laissées sont vides et sont à compléter dans le cadre du TP.
  
-** FIXME suite à réviser **+Certaines méthodes pourront être implémentées en utilisant des requêtes nommées écrites dans le langage [[http://docs.oracle.com/javaee/7/tutorial/persistence-querylanguage.htm#BNBTG|JPQL]] brièvement présenté en cours. 
 + 
 +Voir la section [[#remarques_additionnelles|remarques additionnelles]] pour plus d'information sur les requêtes nommées en JPA.
  
 ===== Travail demandé ===== ===== Travail demandé =====
  
-  - Concevoir un modèle objet correspondant au modèle relationnel fourni et créer des classes Java correspondantes+  - Prendre en main le schéma relationnel, comprendre les clés (primaires et étrangères)
-  - Annoter les classes via des annotations du package ''javax.persistence'', afin d'établir les liens entre le modèle relationnel et votre modèle objet.  +  - Annoter les classes via JPA. Ci-dessous, une suggestion d'ordre pour compléter ces classes 
-    * Un début de classe Cinema annoté peut servir de point de départ+    * Classe ''Ingredients'' 
-    * Dans la mesure du possible, les associations devront être bidirectionnelles +    * Classe ''Recette'' sans les quantités ni les instructions
-      Dans le cas d'associations bidirectionnelles, la cohérence des informations en mémoire devra être garantie.+    * Liste d'instructions de la classe ''Recette'' et classe ''Instruction''. Remarque: cette classe n'a pas vocation à être une entité à part-entière
 +    * Classe ''Quantite'': bien réfléchir aux clés/identifiants et aux associations de cette classe. 
 +    Collection de quantités dans la classe ''Recette'' 
 +  - Réfléchir aux différentes requêtes qui seront nécessaires dans le cadre de l'implémentation du DAO. Ecrire ces requêtes dans des annotations ''@NamedQueries'' dans les classes/entités concernées par la requête((une seule annotation @NamedQuery par requêteleur portée étant globale)). 
 +  - Compléter la classe ''RecetteORMDAO'' en utilisant un ''EntityManager'' pour interagir avec la base de donnée. Cet ''EntityManager'' sera fourni au DAO via la méthode ''setEntityManager'' 
 + 
 +<note tip>Le test unitaire ''univlyon1.recettes.modele.MappingTest'' permettra au fur et à mesure de vérifier la conformité des annotations que vous écrivez. Cette classe est exécutable directement comme test JUnit dans Eclipse, Netbeans ou IntelliJ.</note> 
 + 
 +<note tip>Il est conseillé d'ajouter d'autres tests dans ''univlyon1.recettes.modele.MappingTest'' afin de vérifier le bon fonctionnement de ''RecetteORMDAO''.</note>
  
 ==== Remarques additionnelles ==== ==== Remarques additionnelles ====
  
-=== Tester le mapping ===+=== Annotations de mapping === 
 + 
 +  * Lorsqu’une entité/classe possède un identifiant portant sur plusieurs attributs, il faut créer une classe spécifique (qui n'est pas une entité) pour regrouper ces champs, et utiliser un champ de cette classe en lieu et place du groupe de champs servant d'identifiants dans votre modèle objet. Voir ''@EmbeddedId'', ''@Embbedable'',''@IdClass''. Voir également ''@ElementCollection''/''@CollectionTable'' si les éléments de la collection ne sont pas des entités. 
 +  * Les annotations ''@Column'', ''@JoinColumn'', ''@JoinColumns'' peuvent être dans le mapping 
 +  * Avec le paramètre ''mappedBy'', il est possible d'utiliser une valeur du type ''maCle.unChamp'' pour indiquer que la relation inverse est référencée à partir d'un champ dans une clé composée (i.e. en présence de ''@Embbedable''/''@EmbbeddedId''/''@IdClass''). 
 +  * L'annotation ''@Lob'' peut être utilisée pour les champs contenant de grandes données (type TEXT, CLOB ou BLOB). 
 +  * L'annotation ''@OrderColumn'' peut être utilisée pour spécifier l'ordre dans une liste. 
 +  * Dans le fichier ''persistence.xml'', changer ''hibernate.hbm2ddl.auto'' de ''validate'' à ''update'' permet au framework de modifier le schéma relationnel. Cela peut être utile pour comprendre à quoi correspond le mapping en cours de développement, mais cela écrase le schéma de l'énoncé. A la fin du TP, le mapping doit fonctionner avec le schéma de fourni plus haut.  
 + 
 +=== Requêtes nommées et ''EntityManager'' === 
 + 
 +Le langage [[http://docs.oracle.com/javaee/7/tutorial/persistence-querylanguage.htm#BNBTG|JPQL]] permet d'interroger les données à travers le modèle objet. Le [[http://docs.oracle.com/javaee/7/tutorial/persistence-querylanguage002.htm#BNBRG|tutoriel JEE]] fournit des exemples de définition et d'utilisation de ce type de requêtes. Remarque: l'annotation ''@PersistenceContext'' utilisée dans le tutoriel est inutile dans ce TP((Elle sert à injecter un ''EntityManager'' automatiquement via un framework qui n'est pas utilisé dans le TP. L'injection peut se faire à la main en appelant simplement la méthode ''setEntityManager'' de ''RecetteORMDAO'' comme par exemple dans ''RecetteApp'')). 
 + 
 +D'autres méthodes d' ''EntityManager'' seront utiles, comme ''find'', ''merge'', ''persist'' de la classe ''[[https://docs.oracle.com/javaee/7/api/index.html?javax/persistence/EntityManager.html|EntityManager]]''
  
-Le mapping relationnel objet peut être tester à travers le [[:enseignement:aide:apis#junit|TestCase JUnit]] placé dans ''src/test/java/mif18/orm/MappingTest.java''. 
-Cette classe est exécutable directement comme test JUnit dans Eclipse, Netbeans ou IntelliJ. 
  
-=== Divers === 
-  * Lorsqu’une entité/classe possède un identifiant portant sur plusieurs attributs, il faut créer une classe spécifique (qui n'est pas une entité) pour regrouper ces champs, et utiliser un champ de cette classe en lieu et place du groupe de champs servant d'identifiants dans votre modèle objet. Voir ''@EmbeddedId'', ''@Embbedable''. Voir également ''@ElementCollection'' si les éléments de la collection ne sont pas des entités. 
-  * Les annotations ''@Column'', ''@JoinColumn'', ''@JoinTable'' sont à utiliser dans le mapping 
-  * Avec le paramètre ''mappedBy'', il est possible d'utiliser une valeur du type ''maCle.unChamp'' pour indiquer que la relation inverse est référencée à partir d'un champ dans une clé composée (i.e. en présence de ''@Embbedable''/''@EmbbeddedId''). 
-  * Changer ''hibernate.hbm2ddl.auto'' de ''validate'' à ''update'' permet au framework de modifier le schéma relationnel. Cela peut être utile pour comprendre à quoi correspond le mapping en cours de développement, mais cela écrase le schéma de l'énoncé. A la fin du TP, le mapping doit fonctionner avec le schéma de fourni plus haut. En cas d'impossibilité, justifier les différences dans des commentaires appropriés dans les classes Java. 
-  * L'ordre suivant est suggéré dans la mise en place des classes et du mapping: 
-    * Classes Salle, Seance, Client, Reservation sans traiter les associations 
-      * il est possible pour cela d'utiliser des type primitifs comme ''int'' ou ''String'' pour les champs qui sont des clés étrangères. Ces champ seront remplacés par des champs désignant des classes du modèle le moment venu (par exemple un champ ''String cinema'' pourra plus tard être remplacé par un champ ''Cinema cinema'' 
-    * Association Salle <-> Cinema 
-    * Association Seance <-> Salle 
-    * Associations Reservation <-> Seance et Reservation <-> Client