Présenter le standard JPA pour la persistance des objets en Java.
Support de cours, partie 1 Support de cours, partie 2
L'API pour la persistance des objets Java (JPA 2.0) permet de rendre persistant des objets Java sans avoir besoin d'un serveur d'application. Ce TP utilise l'implémentation de référence pour JPA, EclipseLink.
Il est impossible en un seul TP de voir toutes les possibilités offertes par JPA. En particulier, ce TP n'aborde pas les entités détachées qui sont pourtant importantes dans la pratique lorsque l'application est distribuée sur plusieurs couches distantes.
Créer un nouveau projet de type "Java Application".
2 librairies doivent être ajoutées au projet :
Pour le driver JDBC, il suffit d'ajouter dans la librairie que vous avez créée dans le TP sur JDBC.
Pour l'implémentation de JPA, ajoutez la libraire "EclipseLink (JPA 2.0)" qui est préinstallée dans NetBeans. 3 jars devraient être installés (ouvrir l'entrée Libraries pour vérifier).
Pour avoir facilement la javadoc des classes de JPA depuis NetBeans, vous allez modifier la définition de la librairie "EclipseLink (JPA 2.0)"
Vous allez écrire les classes Java qui correspondent à la base de données des employés d'une entreprise. Vous allez utiliser la même base de données que pour le TP sur JDBC.
Classes :
Dans le deuxième exercice, pour illustrer les problèmes liés à l'héritage, vous ajouterez une classe Personne (avec un champ nom et un identificateur non significatif) dont hérite la classe Employe, et une classe Client (avec seulement une adresse pour simplifier) qui hérite aussi de Personne. La classe Adresse ne sera pas une entité mais une classe insérée (Embedded).
IMPORTANT : voici une description des associations que vos classes devront implémenter :
Pour vous faire gagner du temps, des squelettes de classes vous sont fournis dans un fichier zip. Pour le moment ne faites rien ; durant les exercices il vous faudra y ajouter des annotations ou même éventuellement d'autres informations. Dans ce zip vous trouverez aussi un fichier persistence.xml que vous devrez placer au bon endroit (dans un répertoire META-INF, dans le classpath) et modifier pour indiquer les bonnes informations pour la connexion à la base de données et pour ajouter des noms de classes entités. Des propriétés propres à EclipseLink ont été positionnées pour faire afficher des informations sur le déroulement de l'exécution de JPA, en particulier les ordres SQL générés (lisez la console pendant l'exécution du programme) et pour recréer les tables à chaque exécution (pratique pour tester mais, évidemment, à enlever en production) ; vous devrez enlever ou modifier la valeur de cette dernière propriété à partir d'un certain moment si vous voulez conserver les données déjà dans la base de données.
Dans la réalité on peut avoir besoin de changer le nom des tables créées automatiquement. Vous ferez générer les tables PROJET2, PARTICIPATION2 (remarquez le "2" final pour les 2 dernières tables) au lieu de PROJET et de PARTICIPATION. Toutes les autres tables auront les valeurs par défaut prévues par JPA pour les noms de tables ; par exemple, la table associée à la classe Departement s'appellera DEPARTEMENT (pour les différencier des classes, on mettra dans cet énoncé les noms des tables en majuscules).
Juste pour tester, vous allez travailler avec uniquement les départements, sans les autres classes.
Departement
dans la liste des classes gérées par JPA.Test1
? Et si vous modifiez le fichier persistence.xml pour ne pas supprimer toutes les tables à chaque nouvelle exécution ? Testez en remplaçant <property name="toplink.ddl-generation" value="drop-and-create-tables"/>
par <property name="toplink.ddl-generation" value="create-tables"/>
et en relançant Test1.Les classes
persistence.xml
Dernière question
Enlevez les commentaires que vous avez mis dans la question précédente dans la classe Departement pour tout ce qui est lié à l'association avec la classe Employe. Complétez les classes Personne, Employe et Client. Vous les utiliserez avec cette classe Test2.
Utilisez la stratégie "une seule table par arborescence d'héritage".
A la fin de l'exécution de cette méthode main, la base de données devra contenir les bonnes informations. Vérifiez-le ; en particulier, regardez bien la table des employés.
Définition de l'unité de
persistance
Les classes
Commencez par modifier le fichier persistence.xml pour ne pas écraser les
tables existantes : remplacez drop-and-create par create. Vous pouvez aussi en profiter pour changer le niveau de log pour que les sorties des requêtes ne soient pas noyées par les messages de log : vous pouvez passer à SEVERE
(et revenir à FINE
ou FINEST
si vous avez des problèmes).
Complétez les classes Projet et Participation
et Test4 dont la méthode main crée 3
employés, 2 projets et répartit
les 3 employés dans ces 2 projets. Attention, c'est pour cet exercice
qu'il faut penser à ne pas écraser des éventuelles tables PROJET et PARTICIPATION ; les tables devront s'appeler PROJET2 et PARTICIPATION2.
Voici la méthode de la classe Projet qui servira à ajouter un
employé dans
un projet :
public void ajouterParticipant(Employe employe, String fonction)
Le concepteur de l'application souhaite que l'entité Participation ne
soit pas
visible pour l'utilisateur de la classe Projet. Que devrez-vous faire pour rendre
persistantes les participations sans que ces participations ne soient visibles
?
Lancez l'exécution de Test4. Vérifier que tout s'est bien passé en allant voir directement dans les tables de la base de données.
Que faudrait-il modifier si un employé pouvait avoir plusieurs fonctions dans un même projet ?
Définition de l'unité de
persistance
Participation invisible
Les classes
Plusieurs fonctions dans un projet
Ecrivez une classe Test5 dont la méthode main
Récupérez tous les employés en dehors d'une transaction avec la requête "select e from Employe as e".
Faites afficher les noms de tous les employés.
Sans relancer une requête,
en utilisant seulement les associations des objets Employe
récupérés,
récupérez
tous les projets auxquels participent les employés. Faites afficher
la liste des noms des employés ; un nom par ligne, suivi de tous les projets
auxquels l'employé participe. Les noms des employés qui ne participent à aucun
projet devront être affichés.
En utilisant le logging de EclipseLink, regardez quelles sont les requêtes SQL lancées par EclipseLink et à quel moment. Modifiez le mode de récupération de l'association entre les employés et les participations pour voir l'impact sur les requêtes SQL.
Comment éviter le problème des N + 1 selects ?
Il est très important de comprendre les relations qui lient les contextes de persistance et les transactions. Dans cet exercice vous allez tester quelques situations particulières.
Avertissement pour ceux qui vont travailler avec un serveur d'applications (avec Java EE) : par défaut les contextes de persistance seront alors limités à une transaction et le comportement ne sera pas le même que dans cet exercice où le contexte de persistance et les transactions ne sont pas gérés par le container mais par l'application.
Ajoutez un attribut de version (@Version) dans l'entité Departement.
Recommencez le premier exercice en vous arrangeant pour que le nom du département soit limité à la longueur 25 dans la table DEPARTEMENT générée automatiquement.