Réalisation d'un projet
Introduction
Ce chapitre sert à définir une méthodologie simple pour la réalisation d’un projet avec JPA. Il décrit de manière itérative les différentes étapes à valider, allant de la mise en place du projet à la préparation de la livraison. Ainsi, ce chapitre conclut l’ouvrage en mettant en place les notions vues au cours des précédents chapitres, dans un contexte de développement.
La réalisation d’un projet peut être séparée en cinq thèmes :
-
La définition du projet
-
La mise en place du modèle
-
La réalisation du contrôleur
-
L’utilisation de JPA
-
La préparation de la livraison
1. Import du projet
Le projet final est téléchargeable depuis la page Informations générales (c’est le fichier Zip fourni contenant le projet PROJET_ENI_MAVEN.zip). Une fois le fichier ZIP récupéré, il faut l’importer dans NetBeans :
Lancez la fenêtre d’import de projet ZIP depuis le menu File - Import Project - From ZIP....
Sélectionnez le fichier à importer puis cliquez sur le bouton Import.
Le projet contient les différentes classes utilisées, ainsi que les différents fichiers de configuration et le script de création de base de données.
Définition du projet
La définition du projet consiste à se poser une suite de question sur l’application afin de déterminer comment JPA doit être implémenté et les différents modules annexes d’Hibernate à utiliser.
1. L’application dans le système d’information
Le but de la définition de l’application dans le système d’information est de positionner le rôle de l’application par rapport au système de gestion de base de données et aux divers outils qui ont accès aux données sans passer par l’application en elle-même.
a. Java SE ou Java EE
La question à se poser est : est-ce une application Java EE ou Java SE ? C’est-à-dire, est-ce qu’elle tourne sur un serveur d’applications (Tomcat, JBoss…) ou en stand-alone (client lourd, batch) ?
S’il s’agit d’une application Java SE, alors le contexte de persistance doit être géré par l’application et le mode de fonctionnement est forcément RESOURCE_LOCAL.
S’il s’agit d’une application Java EE, alors il est possible de travailler en RESOURCE_LOCAL ou en JTA en utilisant le conteneur Java EE. De plus, il faut vérifier qu’une version d’ORM est déjà implémentée en natif avec le serveur d’applications. En effet, certains serveurs ont déjà une version d’Hibernate intégrée, et afin d’uniformiser le système d’information, il est préférable d’utiliser dans l’application la même version d’ORM que celle du serveur.
Ainsi, cette première question permet d’apporter un début de réponse sur la version de l’ORM à utiliser ainsi que le mode de transaction utilisé (RESOURCE_LOCAL ou JTA).
b. Modification de données
La question à se poser est : est-ce que les données peuvent être modifiées par une autre application lors de l’utilisation nominale du système (hors mise à jour et maintenance) ?
Si les données peuvent être modifiées par une autre application, cela signifie qu’il risque d’y avoir une désynchronisation des données chargées dans le contexte de persistance...
Mise en place du modèle
La mise en place du modèle est la construction des différentes entités ainsi que leur personnalisation, et si besoin la création du métamodèle statique.
1. Création du modèle
La création du modèle correspond à la définition des différentes entités. Il est possible de les créer manuellement ou, si la base de données existe, d’utiliser un outil afin de les générer.
Dans cet exemple, nous allons utiliser les classes crées par l’outil de génération d’entités de NetBeans afin de gagner du temps. Les différentes étapes sont décrites au chapitre Pour aller plus loin, section Génération automatique - Génération des entités.
2. Personnalisation du modèle
Une fois les entités générées automatiquement, il y a plusieurs étapes à réaliser suivant le besoin :
-
Vérifier que les types sont les bons.
-
Vérifier les relations entre les entités.
-
Modifier equals() et hashCode().
-
Ajouter des requêtes nommées.
-
Mettre en place des générateurs spécifiques.
-
Utiliser les listeners d’entités (@PrePersist…).
-
Mettre en place la gestion du cache de second niveau.
Ces différentes opérations peuvent être effectuées en début de projet ou modifiées suivant les besoins plus tard.
a. Vérifier les types
Cette étape sert à vérifier que la génération automatique s’est bien déroulée. En effet, il est possible d’avoir un type de données en base qui ne correspond pas à celui voulu dans le modèle.
Par exemple, lors de la génération de l’entité PersonneDetail, l’élément sexe en base de données est un String alors que dans le modèle il faut utiliser une énumération. L’outil de génération automatique ne reconnaît pas cette information, il faut donc le modifier à la main et ajouter un convertisseur (cf. section Les contrôles entre JPA et la base de données - Les convertisseurs du chapitre Pour aller plus loin) ce qui donne dans l’entité :
@Column(name...
Réalisation des contrôleurs
La réalisation des contrôleurs est une étape cruciale qui va définir comment le reste de l’application travaille avec le modèle et les différentes opérations possibles. Ainsi, grâce aux différents contrôleurs d’entités, il va être possible de centraliser les opérations sur la base de données, principalement les CRUD (Create, Read, Update, Delete).
1. Création des contrôleurs
Avec NetBeans, la création des contrôleurs d’entités se fait de manière assez simple en utilisant les templates par défaut (cf. section Divers - MVC du chapitre Pour aller plus loin).
L’avantage des contrôleurs générés par NetBeans est qu’ils sont sécurisés au niveau des transactions. C’est-à-dire que lors de la persistance d’une entité, une transaction est démarrée au début de la méthode puis validée (ou annulée si une erreur s’est produite) à la fin.
L’inconvénient des contrôleurs générés par NetBeans est qu’ils empêchent la cascade. En effet, dans le cas d’une création d’une nouvelle entité, donc l’utilisation de la méthode create() du contrôleur de l’entité voulue, lorsqu’il y a une relation avec une autre entité, cette deuxième entité doit exister en base.
Cela vient du fait que le contrôleur généré vérifie que toutes les relations existent au moment de leur création.
Par exemple, sur le contrôleur de l’entité Personne, avant la création de l’entité, le contrôleur vérifie dans un premier temps que cette entité a un PersonneDetail qui existe en base avec la méthode getReference() :
public class PersonneControleur implements Serializable {
...
public void create(Personne personne) {
...
PersonneDetail personneDetail = personne.getPersonneDetail();
if (personneDetail != null) {
personneDetail = em.getReference(personneDetail.
getClass(), personneDetail.getIdPersonne()); ...
L’utilisation
L’utilisation est l’implémentation des différents contrôleurs au sein des différentes interfaces utilisateur telles que l’interface homme-machine, les web services, les batchs…
Dans la suite de ce chapitre, plusieurs méthodes montrent l’utilisation des contrôleurs générés par défaut et des contrôleurs personnalisés.
Une des spécificités des contrôleurs est qu’il est fortement conseillé de laisser la gestion des transactions à leur niveau. En effet, il peut être tentant de démarrer la transaction avant l’appel des méthodes des contrôleurs, mais cela signifie par exemple gérer la transaction au niveau de l’interface graphique, ce qui risque d’être un problème sur le long terme (maintenance, ajout de nouvelle fonctionnalité…).
1. Création
Lors de la création d’une entité, il y a plusieurs points à prendre en compte :
-
Est-ce qu’elle a des relations avec d’autres entités ?
-
Si elle a des relations, est-ce que les autres entités existent en base ?
-
Si les autres entités n’existent pas, est-ce qu’il y a des cascades mises en place ?
Ainsi, lors de la création d’une entité Personne ayant une relation avec une entité PersonneDetail qui n’existe pas, plusieurs cas peuvent survenir.
Par exemple, la classe com.eni.jpa.main.LanceurControleurNetBeans fournie avec le projet contient plusieurs cas d’utilisation des contrôleurs générés par NetBeans sans modification.
La méthode createPersonne1() montre ce qui se passe lors de l’essai de la création en cascade :
private static void createPersonne1() {
Personne p = new Personne();
p.setNom("nom");
p.setPrenom("prenom");
p.setPersonneDetail(new PersonneDetail());
p.getPersonneDetail().setPersonne(p);
PersonneJpaController ctrl =
new PersonneJpaController(JpaUtil.getEmf());
ctrl.create(p);
}
Cette méthode n’est pas la bonne car la création de l’entité Personne est faite avec une entité PersonneDetail qui n’existe...
La préparation de la livraison
La préparation de la livraison consiste à s’assurer que l’application sera exploitable en production. Par exemple, il peut y avoir des configurations différentes entre le serveur de développement et le serveur d’exploitation.
1. Vérification des fichiers de configuration
Lors du déploiement d’une application utilisant JPA, plusieurs fichiers de configuration existent et sont à vérifier car il peut y avoir des différences entre l’environnement de développement et l’environnement de production. Ainsi, ces vérifications peuvent être séparées en plusieurs catégories :
-
Les paramètres de connexion à la base de données.
-
La configuration du pool de connexions (c3p0).
-
La configuration de l’implémentation.
-
La configuration du cache de second niveau (ehcache).
a. Connexions à la base de données
Il est usuel que, lors du développement, une base de données spécifique soit utilisée, différente de celle de production. Ainsi, il faut penser à vérifier les paramètres de connexion. Ils sont généralement configurés dans un fichier nommé persistence.xml.
b. Pool de connexions (c3p0)
Pour diverses raisons (les performances, les paramètres de la base de données…), la...