Tp3 : ajout de relations dans le TP2

Transcription

Tp3 : ajout de relations dans le TP2
Tp3 : ajout de relations dans le TP2
1. Introduction
2. Ajout d'une relation 1-1 unidirectionnelle pour lier utilisateur et adresse
2.1. Création de l'entité Adresse
2.2. Ajout de la propriété "adresse" correspondant à la relation, dans la classe Utilisateur
2.3. Modification de la méthode "creerUtilisateursDeTest" pour créer des personnes avec des adresses
2.4. Affichage des adresses dans la page JSP
3. Passage en bi-directionnel : on veut pourvoir afficher la liste des personnes habitant une même ville
3.1. Affichage des utilisateurs par Adresse dans la page JSP
4. A vous de jouer !
Introduction
Cette fois-ci nous allons jouer avec les relations. Nous allons ajouter au TP2 des relations entre des
clients et des adresses.
Ajout d'une relation 1-1 unidirectionnelle pour lier utilisateur et
adresse
Nous allons ajouter une relation liant un utilisateur et une adresse. Plusieurs utilisateurs peuvent
habiter à la même adresse.
Comme une adresse peut être partagée par deux utilisateurs (John Lennon et Ringo Starr peuvent
habiter ensembles par exemple), on ne fera ni insertion, ni suppression en cascade.
Création de l'entité Adresse
Vous ajouterez au projet une classe entité Adresse, possèdant quelques propriétés. Dans cet exercice on
se limite pour le moment au nom de la ville et au code postal. On utilisera une annotation de la "Bean
Validation API" pour mettre des contraintes sur le code postal et sur le nom de la ville. Si jamais on
essaie de créer une Adresse avec des attributs ne respectant pas ces contraintes, ou si on fait un
setCity(...) ou setCodePostal(...) et que les paramètres ne sont pas valides, une exception sera levée.
@Entity
public class Adresse implements Serializable {
1
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@NotNull @Size(min=1)
private String ville;
@Pattern(regexp="[0-9]{5}") // On accepte les codes postaux du type "06410"
private String codePostal;
public Adresse() {}
public Adresse(String ville, String codePostal) {
this.ville = ville;
this.codePostal = codePostal;
}
... compléter avec les getters et setters pour chaque propriété
}
N'oubliez pas de générer les getters et setters pour chacune des propriétés.
Ajout de la propriété "adresse" correspondant à la relation, dans la classe
Utilisateur
Dans le fichier Utilisateur.java, ajoutez manuellement un attribut de type Adresse :
private Adresse adresse;
Normalement une petite lampe jaune doit apparaitre sur la gauche, car NetBeans a détecté que Adresse
était de type entité. En cliquant sur la lampe on va voir apparaitre un menu proposant d'ajouter une
annotation pour déclarer une relation entre entités:
2
Choisissez la première option, nous allons bien créer une relation 1-1 unidirectionnelle entre
Utilisateur et Personne. Normalement une annotation @OneToOne doit apparaître au-dessus de la
propriété.
Pensez à générer des getters et setters pour la propriété "adresse".
Modification de la méthode "creerUtilisateursDeTest" pour créer des
personnes avec des adresses
Nous allons commencer par modifier la méthode qui créée un utilisateur pour lui ajouter
systématiquement une adresse (on suppose que l'adresse est en base avant que l'utilisateur soit créé) :
public Utilisateur creeUtilisateur(String prenom, String nom, String login,
Adresse a) {
Utilisateur u = new Utilisateur(nom, prenom, login);
// On met à jour la relation, elle est déjà en base
u.setAdresse(a);
// On persiste l'utilisateur, la relation est déjà en base, cela va don
// ajouter une ligne dans la table des utilisateur avec une clé étrangè
// correspondant à l'adresse
em.persist(u);
return u;
}
Et donc voici la fonction qui créée des utilisateurs de test, modifiée pour qu'avant d'ajouter dans la base
de données des utilisateurs on ait ajouté quelques adresses, que l'on utilisera pour construire les
utilisateurs :
public void creerUtilisateursDeTest() {
// On cree des adresses et on les insère dans la base
Adresse biot = new Adresse("Biot", "06410");
em.persist(biot);
Adresse valbonne = new Adresse("Valbonne", "06560");
em.persist(valbonne);
Adresse nice = new Adresse("Nice", "06000");
em.persist(nice);
3
// Note : après un persist, les objets sont connectés
// John et Paul habitent à Biot
Utilisateur john = creeUtilisateur("John", "Lennon", "jlennon", biot);
Utilisateur paul = creeUtilisateur("Paul", "Mac Cartney", "pmc", biot);
Utilisateur ringo = creeUtilisateur("Ringo", "Starr", "rstarr", nice);
Utilisateur georges = creeUtilisateur("Georges", "Harisson", "georgesH"
}
Voilà, donc ci-dessus, dans un premier temps on fait des em.persis() sur des adresses. Puis on passe les
adresses à la méthode creeUtilisateur(). Rappel du cours : après un persist, un select les objets sont
"connectés" (on dit "managés" dans le jargon JavaEE). DOnc quand on fait, dans la méthode
creeUtilisateur, un u.setAdresse(a), a est bien un objet en base, connecté. Et quand in fait em.persist(u),
à ce moment là la relation dans la table des Utilisateur (uné clé étrangère correspondant à une clé
primaire dans la table des adresses, est ajoutée).
Exécutez votre projet, crééz des utilisateurs (soit c'est fait au déploiement si vous avez un
ContextListener, soit il faut cliquer sur le bouton "crééer 4 utilisateurs de test"), puis regardez l'état de
vos tables, et les données. Normalement vous devez avoir :
4
Affichage des adresses dans la page JSP
Si vous vous souveznez du cours, les relations de type 1-1 sont toujours gérées par défaut en mode
"agressif", c'est-à-dire que si on récupère en base un utilisateur (soit avec un em.find() pour le chercher
par son id, soit par un select), le contenu de ses relations est également chargé en mémoire. En d'autres
termes, pour notre exemple, un u.getAdresse().getVille() sur un utilisateur, si u n'est pas connecté, doit
afficher la ville puisque celle-ci aura été lue en mémoire après un em.find() ou un select().
Dans le cas d'un chargement "lazy" (fainéant), les relations ne sont lues en mémoire que si l'objet est
connecté et que après un get... sur la propriété de la relation. C'est le cas par défaut des relations 1-N et
N-N.
Pour afficher la ville et le code postal où habitent les Beatles, rien de plus simple, on va utiliser le
langage EL des pages JSP pour accèder à la propriété ville et à la propriété codePostal, de la propriété
adresse des utilisateurs.
Nous allons odifier comme suit les lignes affichant la liste des utilisateurs :
<!-- Zone qui affiche les utilisateurs si le paramètre action vaut listerCompte
<c:if test="${param.action == 'listerLesUtilisateurs'}" >
<h2>Liste des utilisateurs</h2>
<table border="10">
<!-- La ligne de titre du tableau des comptes -->
<tr>
<td><b>Login</b></td>
<td><b>Nom</b></td>
<td><b>Prénom</b></td>
5
<td><b>Ville</b></td>
<td><b>Code postal</b></td>
</tr>
<!-- Ici on affiche les lignes, une par utilisateur -->
<!-- cette variable montre comment on peut utiliser JSTL et EL
<c:set var="total" value="0"/>
<c:forEach var="u" items="${listeDesUsers}">
<tr>
<td>${u.login}</td>
<td>${u.firstname}</td>
<td>${u.lastname}</td>
<td>${u.adresse.ville}</td>
<td>${u.adresse.codePostal}</td>
<!-- On compte le nombre de users -->
<c:set var="total" value="${total+1}"/>
</tr>
</c:forEach>
<!-- Affichage du solde total dans la dernière ligne du tableau
<tr><td><b>TOTAL</b></td><td></td><td><b>${total}</b></td><td><
</table>
</c:if>
Notez qu'on a juste ajouté deux <TD> pour les en-têtes du tableau et qu'on a ajouté deux lignes dans la
boucle pour afficher la ville et le code postal :
<td>${u.adresse.ville}</td>
<td>${u.adresse.codePostal}</td>
Ces lignes sont exécutent un u.getAdresse().getVille() et un u.getAdresse().getCodePostal(). C'est le
principe des propriétés manipulées avec le langage EL.
6
Passage en bi-directionnel : on veut pourvoir afficher la liste des
personnes habitant une même ville
Cette fois ci on va juste changer le type de la relation. Effacez dans la classe Utilisateur.java
l'annotation existant pour la relation et choisissez dans le menu déroulant de l'ampoule jaune
"ManyToOne bidirectional", acceptez les valeurs par défaut dans la fenêtre dialogue qui apparait.
Remarquez que la classe Utilisateur.java ne change pas beaucoup, le choix dans le menu a ajouté
l'annotation @ManyToOne au lieu de @OneToOne :
@ManyToOne
private Adresse adresse;
Dans la classe Adresse.java en revanche les choses ont changé, les lignes suivantes ont été rajoutées :
@OneToMany(mappedBy = "adresse")
private List<Utilisateur> utilisateurs;
Là, nous vous conseillons ici une bonne pratique concernant les relations du côté "Many" :
1. Toujours initaliser la propriété avec une liste vide,
2. Ajouter un getter sur la propriété : getUtilisateurs()
3. Ajouter des méthodes addUtilisateur(...) et removeUtilisateur(...) dans la classe
Ces deux astuces vous simplifieront la vie et éviterons bien des erreurs. Voici donc les lignes qui sont
réellement à ajouter dans la classe Adresse.java :
@OneToMany(mappedBy = "adresse")
private List<Utilisateur> utilisateurs = new ArrayList<>();
...
...
public void addUtilisateur(Utilisateur u) {
utilisateurs.add(u);
}
public void removeUtilisateur(Utilisateur u) {
utilisateurs.remove(u);
7
}
public List<Utilisateur> getUtilisateurs() {
return utilisateurs;
}
Il reste à modifier la création des utilisateurs de test dans GestionnaireUtilisateurs.java, pour bien
affecter la relation des deux côtés. Voici la version modifée de la méthode creerUtilisateur(...) :
public Utilisateur creeUtilisateur(String prenom, String nom, String login,
Adresse a) {
Utilisateur u = new Utilisateur(nom, prenom, login);
// On met à jour la relation, elle est déjà en base
u.setAdresse(a);
// a est déjà en base et connectée, donc la ligne suivante modifie les
// données pour relier l'adresse à l'utilisateur
a.addUtilisateur(u);
// On persiste l'utilisateur, la relation est déjà en base, cela va don
// ajouter une ligne dans la table des utilisateur avec une clé étrangè
// correspondant à l'adresse
em.persist(u);
return u;
}
La ligne importante est a.addUtilisateur(u) ici, que l'on a rajoutée !
Affichage des utilisateurs par Adresse dans la page JSP
On va commencer par ajouter un lien <a href=""...></a> dans le tableau, sur l'affichage du nom de la
ville. En cliquant sur la ville, on affichera une nouvelle page qui affichera la liste des utilisateurs
habitant une ville donnée :
On modifie donc index.jsp en conséquence :
8
<td>
<a href="ServletUsers?action=listerUtilisateursParVille&idville=${u.adress
${u.adresse.ville}
</a>
</td>
On aura donc sur chaque nom de ville un lien vers l'URL
: ServletUsers?action=listerUtilisateursParVille&idville=${u.adresse.id}
Ce qui revient à appeler ServletUsers avec un GET, en passant les paramètres HTTTP suivants :
• action = listerUtilisateursParVille
• idVille = id de l'adresse (de la ville)
On ajoute dans la servlet un test pour traiter cette nouvelle action :
if (action.equals("listerLesUtilisateurs")) {
...
} else if (action.equals("listerUtilisateursParVille")) {
// on récupère le paramètre idVille
int idVille = Integer.parseInt(request.getParameter("idVille"))
// On récupère la liste des utilisateurs pour la ville
Collection<Utilisateur> liste = gestionnaireUtilisateurs.getUse
// et on passe le résultat à la JSP pour affichage...
request.setAttribute("listeDesUsers", liste);
forwardTo = "index.jsp?action=listerLesUtilisateurs";
message = "Liste des utilisateurs pour la ville No : " + idVill
} else if (action.equals("creerUtilisateursDeTest")) {
...
Ne manque qu'à voir l'implémentation de la méthode getUsersParVille(idVille) dans le gestionnaire
d'utilisateurs :
GestionnaireUtilisateurs.java, la méthode fait deux lignes :
9
public Collection<Utilisateur> getUsersParVille(int idVille) {
Adresse a = em.find(Adresse.class, idVille);
// a est connecté, le get va déclencher un select
return a.getUtilisateurs();
}
Voilà.... !
A vous de jouer !
Complétez l'adresse en ajoutant un numéro de rue, complétez l'utilisateur en ajoutant une liste de
numéros de téléphones sous forme de relations. On veut évidemment afficher le No de rue et la liste des
numéros de téléphones dans le tableau figurant dans la page JSP. Vous ajoutez à chaque utilisateur au
moins deux numéros de téléphones en précisant dans la classe Telephone.java une propriété indiquant
si c'est un mobile un fixe, etc.
Si vous êtres arrivés là, essayez de rajouter un formulaire pour ajouter un numéro de téléphone à un
utilisateur existant, ou bien pour en enlever un.
Récupéré depuis "http://miageprojet2.unice.fr/index.php?title=Intranet_de_Michel_Buffa/
Technologies_Web%2C_Master_1_Miage%2C_2012-2013/Tp3_:_ajout_de_relations_dans_le_TP2"
10

Documents pareils