Ceci est une ancienne révision du document !


Mise en oeuvre de mappings Objet/Relationnels

Ce TP est à réaliser en binômes.

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, la date sera communiquée en avance par mail) portant sur des points techniques du TP.

<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.</note>

Rendu

Il est demandé de créer un projet forge pour ce TP. On poussera (via hg push …) la version finale du TP au plus tard le 05/10/2015. On passera par 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:

Introduction

L'objectif de ce TP est de mettre en place un mapping Objet/Relationnel via l'API JPA.

Quelques liens:

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

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é dans l'aide. Voir également le TP maven/forge.

Télécharger et décompresser le projet de base: inf1018m-orm.zip ou mieux le cloner depuis la forge:

hg clone https://forge.univ-lyon1.fr/hg/inf1018m-orm

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 ouvert dans Netbeans/IntelliJ.

<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 projet1), faire:

mvn test

</note>

Le fichier pom.xml contient les dépendances sur les bibliothèques nécessaires au TP.

Le fichier src/main/resources/META-INF/persistence.xml contient les informations pour mettre en place le cadre de persistance.

Base de donnée et schéma relationnel

Installation et démarrage de la base H2

H2 est une base de donnée Java qui sera utilisée dans ce TP2). Télécharger et décompresser le fichier 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> Vérifier la configuration:

  • Pilote JDBC: org.h2.Driver
  • URL JDBC: jdbc:h2:tcp://localhost/~/test
  • Nom d'utilisateur: sa
  • Mot de passe: vide

</note> Tester la connexion, puis se connecter.

Mise en place du schéma

Le fichier src/main/resources/schema.sql du projet embryonnaire permet de mettre en place le schéma relationnel dans la base H2. Utiliser la console H2 dans le navigateur pour mettre en place ce schéma.

schema.sql
CREATE TABLE Recette(
  nom VARCHAR(255) PRIMARY KEY,
  description CLOB,
  url_image VARCHAR(1024)
);
 
CREATE TABLE Ingredient(
  nom VARCHAR(255) PRIMARY KEY,
  description CLOB
);
 
CREATE TABLE Quantite(
  recette VARCHAR(255) REFERENCES Recette(nom),
  ingredient VARCHAR(255) REFERENCES Ingredient(nom),
  quantite DOUBLE,
  unite VARCHAR(40),
  PRIMARY KEY (recette,ingredient)
);
 
CREATE TABLE Instruction(
  recette VARCHAR(255) REFERENCES Recette(nom),
  ordre INTEGER,
  description CLOB,
  PRIMARY KEY (recette,ordre)
);

Modele objet et DAO

Modele objet

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 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 pour plus d'information sur les annotations JPA.

DAO

L'interaction avec la base de donnée est encapsulée dans la classe RecetteORMDAO. Les méthodes de cette classes ont été laissées sont vides et sont à compléter dans le cadre du TP.

Certaines méthodes pourront être implémentées en utilisant des requêtes nommées écrites dans le langage JPQL brièvement présenté en cours.

Voir la section remarques additionnelles pour plus d'information sur les requêtes nommées en JPA.

Travail demandé

  1. Prendre en main le schéma relationnel, comprendre les clés (primaires et étrangères).
  2. Annoter les classes via JPA. Ci-dessous, une suggestion d'ordre pour compléter ces classes
    • Classe Ingredients
    • Classe Recette dans les quantités ni les instructions.
    • 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
  3. 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ête3).
  4. 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

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).
  • 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 JPQL permet d'interroger les données à travers le modèle objet. Le 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 TP4).

D'autres méthodes d' EntityManager seront utiles, comme find, merge, persist de la classe EntityManager

1)
à priori inf1018m-orm
2)
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
3)
une seule annotation @NamedQuery par requête, leur portée étant globale
4)
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