Vous êtes sur la page 1sur 136

Architectures client/serveur

Master Technologies de l'Internet 1 Eric Cariou


Universit de Pau et des Pays de l'Adour UFR Sciences Pau Dpartement Informatique Eric.Cariou@univ-pau.fr
1
re

anne

Tryptique d'une application

Prsentation

Services mtier

Persistance

Tryptique d'une application

Prsentation
Interface utilisateur pour interagir avec l'application

Interface classique type GUI (ex : traitement de texte) Interface Web, plus lgre

Persistance
Enregistrement sur support physique des donnes de l'application

Fichiers (binaires, XML, ...) Base de donnes


Simple Avec redondance pour fiabilit Multiples : fdration de bases de donnes ...

Tryptique d'une application

Services mtier
Intgre la logique mtier

Ex: un document est compos de sections, elles mmes composes de sous-sections ... Ex: crer un document, le modifier, ajouter des sections, l'enregistrer ...

Services offerts aux utilisateurs

Partieapplicative Sont intgres et cooprent pour le fonctionnement de l'application En anglais, on les appele aussi des tiers (tages)

Trois parties

Application 3 tiers quand les 3 parties sont clairement4 distinctes

Tryptique d'une application

Dans un contexte distribu


Les tiers sont / peuvent tre excuts sur des machines diffrente Certains tiers peuvent tre sous dcoups De nombreuses variantes de placement des tiers et de leur distribution Tout est sur la mme machine
Prsentation Services Mtiers Persistance 5

Modle centralis

Architecture 2 tiers

Architecture 2 tiers

Client / serveur de base, avec 2 lments


Client : prsentation, interface utilisateur Serveur : partie persistance, gestion physique des donnes Soit entirement cot client, intgrs avec la prsentation

Les services mtier / la partie applicative peuvent tre

La partie serveur ne gre que les donnes


Ex : traitement de texte avec serveur de fichiers distants Ex : application accdant une BDD distante

Soit entirement cot serveur


La partie client ne gre que l'interface utilisateur L'interface utilisateur peut mme tre excute sur le serveur

Fonctionnement mode terminal / mainframe L'utilisateur a simplement devant lui cran / clavier / souris pour interagir distance avec l'application s'excutant entirement sur le serveur

Soit dcoups entre la partie serveur et la partie client

Architecture 2 tiers

Client : prsentation + applicatif


Services Mtiers Persistance Serveur

Prsentation Client

Serveur : applicatif + gestion donnes


Services Mtiers

Prsentation Client

Persistance

Serveur 7

Architecture 2 tiers

Terminal : client intgre un minimum de la partie prsentation


Terminal

Prsentation

Services Mtiers Serveur

Persistance

Client

Applicatif : dcoup entre client et serveur


Applicatif Prsentation client Client Applicatif Persistance serveur Serveur 8

Architecture 3 tiers

Architecture 3 tiers
Les 3 principaux tiers s'excutent chacun sur une machine diffrente Prsentation

Machine client Serveur d'applications Serveur de (base de) donnes Services Mtiers Serveur applicatif Persistance Serveur 9 donnes

Applicatif / mtier

Persistance

Prsentation Client

Architecture 3 tiers sur le web

Architecture 3 tiers
Trs dveloppe de nos jours

Avec gnralement un fonctionnement au dessus du Web Navigateur web sur machine cliente

Couche prsentation

Client lger

Affichage de contenu HTML Serveur d'applications


Couche applicative / mtier

Serveur HTTP excutant des composants / lments logiciels qui gnrent dynamiquement du contenu HTML Via des requtes des BDD distantes

Couche persistance

Serveur(s) de BDD de donnes

10

Architecture n tiers

Architecture n tiers
Rajoute des tages / couches en plus La couche applicative n'est pas monolitique

Peut s'appuyer et interagir avec d'autres services Composition horizontale

Service mtier utilise d'autres services mtiers Les services mtiers peuvent aussi s'appuyer sur des services techniques

Composition verticale

Scurit, Transaction ...

Chaque service correspond une couche

D'o le terme de N-tiers 11

Architecture n tiers

Intrts d'avoir plusieurs services / couches (3 ou plus)


Rutilisation de services existants Dcouplage des aspects mtiers et technique et des services entre eux : meilleure modularit Facilite volution : nouvelle version de service Facilite passage l'chelle : volution de certains services On recherche en gnral un couplage faible entre les services

Permet de faire voluer les services un par un sans modification du reste de l'application

Inconvnients
En gnral, les divers services s'appuient sur des technologies trs varies : ncessite de grer l'htrognit et l'interoprabilit Utilisation de framework / outils supplmentaires Les services tant plus dcoups et distribus, pose plus de problmes lis la distribution

12

Logique de prsentation

Les tches lies la prsentation requirent

L'interaction avec l'utilisateur


Ralise par la GUI d'un client lourd : boutons, listes, menus, ... Ralise par le navigateur pour un client web

Via interaction plus basique : formulaires, liens vers des URLs ...

La logique de prsentation

Le traitement des donnes retournes par les services mtiers et leur prsentation destination de l'utilisateur Ralise par un client lourd qui gnralement fait directement l'appel des services mtiers sur le serveur Pour un client web

Navigateur se contente d'afficher du code HTML qui ne peut pas tre statique ici vu que le contenu dpend des donnes retournes Doit donc excuter du code qui rcupre les donnes retournes par les services mtiers et gnre dynamiquement du code HTML Logique de prsentation peut tre excute cot client ou cot serveur mais se fait gnralement dans un tiers part cot serveur

13

Persistance

Couche de persistance
Stockage et manipulation des donnes de l'application Plusieurs supports physique

Fichiers binaires, textes de base Fichiers XML Une base de donnes ou un ensemble de bases de donnes Ncessit d'envoyer distance des requtes (types SQL) et d'en rcuprer les rsultats Pour raliser cela

Pour ce dernier cas


Soit c'est natif dans le langage utilis (ex : PHP) Soit on passe par des frameworks ou des API ddis

14

Quelques standards / outils d'accs distance des BDD


Persistance

RDA (Remote Data Access) de l'ISO ODBC (Open Data Base Connectivity) de Microsoft JDBC (Java Data Base Connectivity) de Sun

Framework pour le langage Java

Fonctionnement gnral

Gestion de requtes SQL mais avec indpendance du SGBDR utilis (mySQL, PostgreSQL, Oracle ...) En gnral, seule la phase de connexion au SGBDR est spcifique

Existe galement des frameworks de plus haut niveau


Exemples : Hibernate (Sun, J2EE), NHibernate (libre, pour .Net) Principe gnral

On dfinit de manire abstraite (via XML par exemple) la structure des donnes manipuler L'outil gnre un ensemble d'oprations de manipulation de donnes (en java par exemple) utilisable dans un programme 15 L'outil fait en interne le lien avec le support physique (SGBDR ...) considr

Frameworks globaux

Une application 3/N tiers intgre un grand nombre de technologies


Prsentation : HTML, GUI ... Applicatif : objets, composants, scripts excutables, services ... BDD : fichiers XML, SGBDR, ... Protocoles de communication : RPC / RMI, HTTP

Pour faciliter l'intgration de ces technologies et le dveloppement d'applications

Editeurs offrent des frameworks globaux


J2EE / Java EE chez Sun .Net chez Microsoft Serveur permettant d'excuter les parties applicatives dans le contexte de ces framewoks

Serveur d'application

16

J2EE / Java EE : Java Entreprise Edition


Sun J2EE

Norme / standard dfini par Sun pour le langage Java Technologies intgres

Composants logiciels : EJB Applications orientes Web : JSP, servlet Communication distance : Java RMI, IIOP, JMS (Java Message Service : communication par message), Web Services Gestion donnes distantes : JDBC, JPA (Java Persistance API) Gestion d'annuaires (type LDAP) : JNDI Transactions : JTA Et bien d'autres ...

Existe plusieurs serveurs d'applications J2EE

Versions libres

GlassFish, JBoss, Apache Geronimo, Jonas ... Versions d'diteurs Sun Java System Application Server (bas sur GlassFish), IBM17 WebSphere, BEA WebLogic, Oracle Container for Java EE, ...

Solution Microsoft similaire J2EE

Microsoft .Net

Particularit : multi-langage

Permet interoprabilit d'lments crits en C, Java, C#, J#, Eiffel, VB, ... (plus de 20 langages) Traduction en code intermdiaire (MSIL) qui sera excut par la couche CLR (Common Language Runtime)

Cot Java, c'est le code Java qui tait converti en byte code excut par la machine virtuelle Java (JVM)

C'est une norme galement

La principale mise en oeuvre est bien sr de Microsoft et pour Windows, mais il existe quelques versions libres (implmentations souvent partielles)

Technologies intgres

Composants logiciels : COM+ Applications orientes Web : ASP .Net,


Communication distance : .Net remoting, MSMQ, Web services

Accs donnes : ADO .Net, ODBC ...

18

Architecture 3/4 tiers, contexte J2EE

Deux architectures gnrales contexte J2EE

Logique applicative

Ralise par composants EJB Communication via Hibernate ou JDBC pour attaquer BDD distante Avec client lger ou client lourd Client lger : navigateur web

Prsentation

Intrt : simplifie la prsentation (suffit d'un navigateur) Inconvnient : limite de l'interaction via HTML Application standard cot client, gre la logique de prsentation Intrt : plus grande possibilit en terme de prsentation et d'interaction Inconvnient : ncessite un dveloppement ddi via des API de widgets

Client lourd

Interaction avec la partie applicative sur le serveur


Via JSP / Servlet pour un client lger

S'occupe de la logique de prsentation

Direct si client lourd (via un middleware type RMI)

19

Architecture 3/4 tiers, contexte J2EE

Client lourd (3-tiers)


Client lourd Composants EJB Conteneur EJB SGBD Serveur donnes

Client lger (4-tiers)


Navigateur Web

Serveur J2EE Conteneur web Servlet / JSP logique de prsentation

logique mtier

Composants EJB Conteneur EJB Serveur J2EE

SGBD Serveur 20 donnes

Technologies Web : gnration dynamique HTML cot serveur JSP / Servlet

21

Technologies Web

Prsentation
Affichage document HTML + feuilles de styles S'excute dans un navigateur web : client lger Interaction avec l'utilisateur via des formulaires (listes, entres texte, boutons ...) et liens But : produire un contenu HTML

Applicatif
Selon les choix de l'utilisateur Selon les donnes afficher Ncessite d'xecuter du code qui va gnrer ces pages 22

Ncessite une gnration dynamique des pages HTML

Technologies Web

Excution de code : deux possibilits


Excution cot client

Le client tlcharge partir du serveur du code qui s'excute dans le navigateur du client Exemple : applet Java

Excution d'un programme Java (d'une forme particulire) au sein du navigateur Tlchargement peut tre lourd : chaque client doit tlcharger le code Problme de scurit car on excute localement du code venant d'un lment distant

Problmes

Excution cot serveur


Du code est excut cot serveur pour gnrer de manire dynamique la page HTML qui sera envoye au client 23 On va s'intresser ce type d'excution dans ce cours

Gnration pages dynamiques

Deux principes gnraux de fonctionnement, cot serveur

Langages de scripts

Double type de contenu dans une page HTML


Partie statique : balises HTML standards avec contenu textuel Partie dynamique : du code crit dans un langage de script Ce code gnre du code HTML standard

La page entremelle les parties statiques et dynamiques Quand un navigateur demande le contenu d'une page

La partie dynamique est excute et remplace par le HTML gnr Le navigateur du client reoit donc uniquement du code HTML

Excution d'un programme


Un programme complet s'excute et gnre du contenu HTML La page est entirement dynamique

Plus prcisment : les partie statiques existent mais elles sont intgres dans le code, pas crites directement en HTML standard

Le navigateur demande l'excution d'un programme et rcupre le code HTML gnr

La demande d'excution est transparente : utilise URL standard

24

Gnration pages dynamiques

Exemples de technologies
Langages de script

PHP

Langage interprt offrant l'avantage d'intgrer nativement les primitives de requtes SQL sur des BDD ASP et ASP .Net Solutions Microsoft JSP (Java Server Page) Solution Sun pour Java

Excution de programmes

CGI : Common Gateway Interface

Historiquement, une des premires solutions Solution Sun pour Java : excution de code Java respectant 25 certaines caractristiques

Servlet

Gnration pages dynamiques

Plateforme d'excution
Dans tous les cas, il faut pouvoir excuter du code et communiquer via HTTP avec le navigateur cot client Deux composants pour gnration de pages dynamiques

Serveur HTTP standard Elment (conteneur) d'excution des programmes ou des scripts

Exemples de serveurs / plateformes


Apache Tomcat

JSP, Servlet Logiciel libre ASP, ASP .Net Propritaire

Microsoft IIS

26

Servlet

Une servlet est un programme Java particulier


Classe qui hrite de HttpServlet

Equivalent d'une applet Java, mais cot serveur

Classe standard du point de vue de son contenu en terme d'attributs, mthodes ... Mais excution et interactions diffrentes d'un objet Java standard

Pas d'appel de constructeur, pas de main() A la cration de la servlet par le serveur d'excution

Appel par le serveur d'excution de la fonction init(ServletConfig) On peut y faire les actions qu'on ferait dans un constructeur Appel par le serveur d'excution de destroy() A redfinir si on veut effectuer certaines actions la suppression de la servlet

Quand la servlet est dtruite


27

Navigateur web cot client

Servlet

Envoie des requtes HTTP au serveur


GET, POST, PUT, DELETE, HEAD, OPTIONS, TRACE

Dans une servlet

A chaque requte correspond une mthode doXXX(...) hrite de la classe HttpServlet et qui sera appele selon la requte client

On rdfinit ces mthodes pour y placer le code excuter par la servlet En pratique, pas besoin de redfinir toutes les mthodes (GET et POST minimum) De manire plus gnrale (mais moins recommande), la mthode service(...) reoit toutes les requtes et peut tre redfinie directement (par dfaut elle redispatche aux doXXX(...) )

Exemple pour GET


doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException request : contient la description de la requte du client response : utiliser pour envoyer la rponse au client 28 Toutes les mthodes doXXX(...) ont la mme signature

Paramtres des doXXX(...)

HttpServletRequest request
Initialis par l'appel du client (le navigateur) Donnes / informations sur la requte envoye par le client On peut y rcuprer notamment

Valeurs entres pour un formulaire Une session pour grer un tat ddi chaque client Cookies du client envoys avec la requte Informations sur l'URL utilise pour l'appel de la servlet Login de l'utilisateur s'il s'est identifi Et de manire plus gnrale, tous les headers de l'appel

Identifiants du navigateur, type de requte (GET, PUT ...), type d'encodage support par le navigateur, ...

29

Paramtres des doXXX(...)

HttpServletResponse response

A initialiser et utiliser par la servlet pour gnrer le rsultat envoyer au navigateur client Dfinir le type MIME des donnes envoyes
Gnralemet du code HTML response.setContentType("text/html;charset=UTF-8"); Mais peut utiliser n'importe quel type MIME : image/gif, audio/mp3, application/pdf, ...

Rcuprer le flux de sortie pour envoyer les donnes


PrintWriter getWriter()

Flux texte, typiquement pour du HTML Flux binaire pour des images, vidos ...

ServletOutputStream getOutputStream

Ajouter/envoyer des donnes cot client


Cr un nouveau cookie (ou modifier un existant) Ajouter un header aux donnes envoyes

30

Caractristiques d'une servlet

Unicit d'une servlet


Une servlet n'est cre qu'en une seule instance Si plusieurs clients accdent l'URL d'une mme servlet

Appelle les mthodes sur cette instance unique Cet tat est permanent et conserv (tant que la servlet existe) Il est accd / modifi par tous les clients : tat global

Une servlet possde des attributs donc un tat


Etat associ un client

Temporaire : mode session


Pour chaque client, une session est cre

On peut lui associer des donnes via des couples cl (chaine) / objet

La session a une dure de vie configurable Exemple typique d'utilisation d'une session

Panier d'un utilisateur sur un site de vente en ligne : conserve les produits choisis par l'utilisateur pendant son parcours sur le site

Permanent : cookies du navigateur

31

Exemple basique de servlet


Exemple : servlet hello world

Gnre une page qui affiche hello word Gre et affiche un compteur qui est incrment chaque accs la servlet Le code qui suit a t cr sous Netbeans qui gnre un squelette de code

Note sur le code prsent

Ce squelette contient une mthode principale processRequest() qui contiendra le code principal de la servlet Les mthodes hrites doGet() et doPost() appellent directement cette mthode processRequest() avec les mmes paramtres

Une fois dploye sur le serveur, on accde une servlet via une URL HTTP
La notre est contenue dans le fichier HelloWorld.java URL sera de la forme : http://www.xxxxxx.fr/XXX/HelloWorld Note : peut choisir une URL d'accs la servlet diffrente 32

du nom de la servlet Java

Exemple : servlet hello world

Code de la servlet HelloWorld.java


public class HelloWorld extends HttpServlet { // compteur gr par la servlet protected int compteur = 0; protected void processRequest( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // out : flux de sortie mode texte qui contiendra le HTML response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); try { // on crit ligne par ligne le code HTML afficher chez le client out.println("<html>"); out.println("<head>"); out.println("<title>Servlet HelloWorld</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Servlet HelloWorld</h1>"); // on insre ici la valeur du compteur (en l'incrmentant au passage) out.println("<p>Nombre d'appels : "+(++compteur)+"</p>"); out.println("</body>"); out.println("</html>"); } finally { out.close();

33

} }

Exemple : servlet hello world

Exemple d'excution
Aprs 4 chargements de la servlet compteur passe 5

34

Exemple : servlet hello world

Code prcdent

Le compteur est global : commun tous les clients Passer par les donnes qu'on peut associer une session Modification de processRequest()
try { // rcupre la session associe au client HttpSession session = request.getSession(true); // rcupre le compteur associ la session Integer compteur = (Integer)session.getAttribute("compteur"); // si valeur null : attribut compteur n'existe pas, a signifie // que c'est la premire excution par le client, il faut crer le compteur if (compteur==null) { compteur = new Integer(1); session.setAttribute("compteur", compteur); // configure pour qu'une session dure 10 secondes max session.setMaxInactiveInterval(10); } (...) out.println("<p>Nombre d'appels : "+compteur+"</p>"); (...) // incrmente le compteur 35 session.setAttribute("compteur", new Integer(compteur.intValue()+1));

Variante pour grer un compteur local chaque client


Exemple : passage de paramtres

Autre exemple

Manipulation de rectangles avec 3 oprations


Cration d'un rectangle Dcalage du rectangle courant (non prsent en dtail pour gagner de la place) Calcul de la surface du rectangle courant

Implmentation

appeler la servlet avec ces paramtres Note : dans l'exemple, c'est une page JSP mais c'est du HTML standard, aucun code Java n'est inclus dans la page

Une page HTML contient un formulaire pour entrer les paramtres et

Servlet

Une servlet gre le rectangle et excute les 3 oprations en fonction des paramtres venant du formulaire On rcupre ces paramtres via : request.getParameter(nomParam) 36

Exemple : servlet rectangle

Code de la page HTML


<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <h1>Manipulation de rectangle avec une servlet</h1> <form action="RectServlet" method="post"> <p> <table border="0"> <tr> <td>X1 ou X dcalage</td> <td><input <tr> <td>Y1 ou Y dcalage</td> <td><input <tr> <td align="right">X2</td> <td><input <tr> <td align="right">Y2</td> <td><input </table></p>

name="x1"> name="y1"> name="x2"> name="y2">

</td> </td> </td> </td>

</tr> </tr> </tr> </tr>

<p><input type="radio" name="action" value="creer" checked="checked" /> Crer Rectangle<br /> <input type="radio" name="action" value="decaler" />Dcaler Rectangle<br /> <input type="radio" name="action" value="surface" />Calcul Surface</p> <p><input type="submit" value="Excuter"> <input type="reset" value="Remise zro></p> </form> </body> </html>

37

Exemple : servlet rectangle

Liens entre page HTML et la servlet


Le formulaire de la page HTML contient

Une action associe qui est l'appel de la servlet RectServlet 4 champs d'entre de noms x1, y1, x2, y2 Une liste de boutons radio dont selon le choix, on aura le paramtre action gal creer, decaler ou surface On rcupre ces 5 paramtres dans request Notamment le paramtre action qui prcisera quelle opration on veut appeler La servlet conservera le dernier rectangle cr (avec un premier rectangle dfini par dfaut) et les fonctions de dcalage et de surface seront appeles sur ce rectangle Pour simplifier, on met les fonctions mtiers (manipulation de rectangles) directement dans le code de la classe 38 de la Servlet

Dans le code de la servlet RectServlet.java


Exemple : servlet rectangle

Code de la servlet ServRectangle.java


public class RectServlet extends HttpServlet { // rectange manipul par la servlet protected Rectangle rectangle; public int calculSurface(Rectangle rect) { return ( (rect.x2 - rect.x1) * (rect.y2 - rect.y1)); } public Rectangle decalerRectangle(Rectangle rect, int x, y){ return new Rectangle(rect.x1 + x, rect.y1 + y, rect.x2 + x, rect.y2 + y); } public void init(ServletConfig config) throws ServletException { // initialisation par dfaut du rectangle rectangle = new Rectangle(10, 20, 30, 40); }

39

Exemple : servlet rectangle


Code de la servlet ServRectangle.java (suite)
protected void processRequest( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); try { // entte du document out.println("<html>"); out.println("<head>"); out.println("<title>Test de Servlet : RectServlet</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Servlet RectServlet</h1>"); // affichage du rectangle courant out.println("<p>Etat courant de mon rectangle:"+rectangle+"</p>"); // rcupre l'identifiant de l'action raliser String action = request.getParameter("action"); // calcul de surface du rectangle courant if (action.equals("surface")) int surface = calculSurface(rectangle); out.println("<p>Surface : "+surface+"</p>"); }

40

Exemple : servlet rectangle


Code de la servlet ServRectangle.java (fin)
// cration d'un rectangle if (action.equals("creer")) { int x1 = Integer.parseInt(request.getParameter("x1")); int y1 = Integer.parseInt(request.getParameter("y1")); int x2 = Integer.parseInt(request.getParameter("x2")); int y2 = Integer.parseInt(request.getParameter("y2")); rectangle = new Rectangle(x1, y1, x2, y2); } out.println("<p>Rectangle cr : "+ rectangle + "</p>");

catch (Exception e) { // en cas de problme, affiche un message out.println("<p><b>Erreur !!</b><br />"); out.println(e.toString()+"</p>"); } // fin du document : lien pour retour en arrire out.println("<p><a href=\""+request.getContextPath()+"\"> Retour</a></p>"); out.println("</body>"); out.println("</html>"); 41 out.close(); }

Exemple : servlet rectangle

Affichage de la page HTML


On remplit les 4 champs et slectionne crer

42

Exemple : servlet rectangle

Aprs clic sur excuter


Se retrouve sur la servlet qui cre alors un rectangle

43

Exemple : servlet rectangle

Slection de retour pour revenir la page HTML puis choix de calcul surface

44

Exemple : servlet rectangle

Aprs clic sur excuter


Excute la servlet avec l'opration de calcul surface On voit qu'elle s'applique sur le rectangle qu'on vient de crer et qui a donc t conserv

45

Java Server Page : JSP

Pages mixtes contenant la fois


Du code HTML statique Du code Java qui est excut dynamiquement et gnre du code HTML Les parties statiques et Java sont entremles pour former une page JSP Le navigateur client rcupre une page HTML standard contenant

Les parties statiques Les parties en Java remplaces par le code HTML qu'elles ont gnres Le serveur d'excution de la JSP la traduit d'abord en une servlet complte quivalente et c'est cette servlet qui est 46 excute

En pratique

JSP : insertion de code Java

Attributs implicites (non dclars) utilisables dans le code Java


Similaires ce qu'on aurait dans une servlet

out : flux de sortie texte dans lequel on crit le code HTML gnr par les parties de code Java request : paramtres de l'appel de la JSP / Servlet response : pour renvoyer la rponse au client session : la session spcifique au client courant config : configuration de la JSP page : l'instance de la JSP / Servlet (quivalent du this) exception : l'exception qui a t leve en cas de problme application : donnes communes toutes les JSP du serveur pageContext : contexte de la page (gestion d'attributs ...) 47

Spcifique au fonctionnement des JSP


Balises spciales pour insrer du code Java


JSP : insertion de code Java

Trois balises <% ... %>, <%! ... %> et <%= ... %> Peut insrer plusieurs de ces balises dans une mme page JSP JSP compile en Servlet donc unicit de la JSP galement Dclaration d'attributs et de mthodes Ils seront globaux tous les appels de la JSP pour tous les clients Scriplet : suite d'instructions Java qui sera excute chaque appel de la page JSP Si on y dclare des attributs, ils sont locaux chaque appel Evalue le expr et affiche le rsultat dans le code HTML Equivalent de <% out.print(expr) %>

Point important

<%! ... %>


<% ... %>


<%= expr %>


48

JSP : insertion de code Java

Balise spciale <%@ page .... %>


Informations gnrales sur la JSP

A utiliser si les valeurs par dfaut de la page sont modifier <%@ page import = java.util.Vector %> Par dfaut du text/html <%@ page contentType = ''image/png'' %> Excuter une JSP en cas d'erreur rencontre

Import de classes Java

Type MIME de la page


Gestion des erreurs

<%@ page errorPage=''erreur.jsp'' %> <%@ page isErrorPage=''true'' %>

Prciser qu'une JSP est ou pas une page d'erreur

49

Exemple : JSP hello world

Exemple basique de page JSP


Code statique HTML : affiche Hello World ! Code dynamique et code Java

Gestion d'un compteur local et d'un compteur global d'appel Affichage de ces 2 compteurs (via mlange code statique et dynamique)

Implmentation
Trois insertions de code Java pour grer les compteurs
1. <% ...%> : dclaration du compteur local 2. <%! ... %> : dclaration du compteur global et d'une mthode d'incrmentation de ce compteur 3. <% ... %> : incrmentation des 2 compteurs Puis affiche via des <%= ... %> les valeurs des compteurs 50

Exemple : JSP hello world

Code de la page JSP


<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP HelloWorld</title> </head> <body> <h1>Hello World!</h1> <% int nbLocal = 0; %> <%! int nbGlobal = 0; void incNbGlobal() { nbGlobal++; } %> <% nbLocal++; incNbGlobal(); %> <p>Compteur local : <%= nbLocal %> <br /> Compteur global : <%= nbGlobal %></p> </body> </html>

Lgende couleur : - Code excut localement - Code dclar globalement - Evaluation de la valeur des attributs - Code HTML statique

51

Exemple : JSP hello world

Exemple d'excution
Aprs 4 chargements de la servlet compteur global passe 5 mais le local est systmatiquement 1

52

Exemple : JSP hello world

Commentaires sur le code prsent


Dans dernire balise <% ... %>

Aurait pu remplacer incGlobalNb(); par directement globalNb++; Les attributs et mthodes dclares en global sont tous accessibles directement

Ne peut par contre pas dclarer une mthode pour incrmenter le compteur local

void incNbLocal { nbLocal++; } Ne peut pas dclarer de mthode dans une balise <%! ... %>

Ne contient qu'une suite d'instructions excuter L'attribut nbLocal est local et n'est pas connu dans le code global

Ne peut pas dclarer cette mthode dans la balise <% ... %>

53

Exemple : JSP rectangle

Mme exemple de gestion des rectangles


On a besoin d'une seule page JSP au total Elle fera l'affichage du formulaire avec HTML standard et contiendra le code Java des oprations (en vert) Elle s'auto-appellera pour l'excution de l'opration choisie

Code la page rectangle.jsp


<head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Rectangle</title> </head> <body> <%@page import="rect.*" %>

la classe Rectangle est dfinie dans un package rect

<h1>Manipulation de rectanges avec du JSP</h1>

54

Exemple : JSP rectangle

Code la page rectangle.jsp (suite)


<%! Rectangle rectangle = new Rectangle(10, 20, 30, 40); public int calculSurface(Rectangle rect) { return ( (rect.x2 - rect.x1) * (rect.y2 - rect.y1)); } public Rectangle decalerRectangle(Rectangle rect, int x, int y){ return new Rectangle(rect.x1 + x, rect.y1 + y, rect.x2 + x, rect.y2 + y); }

%>

<form action="rectangle.jsp" method="post"> <p> <table border="0"> <tr> <td>X1 ou X dcalage</td> <td><input <tr> <td>Y1 ou Y dcalage</td> <td><input <tr> <td align="right">X2</td> <td><input <tr> <td align="right">Y2</td> <td><input </table></p>

name="x1"> name="y1"> name="x2"> name="y2">

</td> </td> </td> </td>

</tr> </tr> </tr> </tr>

<p><input type="radio" name="action" value="creer" checked="checked" /> Crer Rectangle<br /> <input type="radio" name="action" value="decaler" />Dcaler Rectangle<br /> <input type="radio" name="action" value="surface" />Calcul Surface</p> 55

Exemple : JSP rectangle

Code la page rectangle.jsp (suite)


<p><input type="submit" value="Excuter"> <input type="reset" value="Remise zro></p> </form> <p>Rectangle courant : <%= rectangle.toString() %> </p> <% try { String action = request.getParameter("action"); // cas du premier affichage de la page : pas de paramtre // il n'y a pas d'actions excuter if (action == null) return; // cration d'un rectangle if (action.equals("creer")) { int x1 = Integer.parseInt(request.getParameter("x1")); int y1 = Integer.parseInt(request.getParameter("y1")); int x2 = Integer.parseInt(request.getParameter("x2")); int y2 = Integer.parseInt(request.getParameter("y2")); rectangle = new Rectangle(x1, y1, x2, y2); out.println("<p>Rectangle cr : "+rectangle + "</p>");

56

Exemple : JSP rectangle

Code la page rectangle.jsp (suite)


if (action.equals("surface")) { int surface = calculSurface(rectangle); out.println("<p>Surface : "+surface+"</p>"); } } // try catch (Exception e) { out.println("<p><b>Erreur !!</b><br />"); out.println(e.toString()+"</p>"); }

// calcul de surface du rectangle courant

%> </body> </html>

On utilise ici les attributs implicites


request : pour rcuprer les paramtres passs avec getParameter() out : flux de sortie pour gnrer du code HTML Utilisation du out comme avec une servlet Utilisation d'une balise <%= ... %> dans du code HTML

Deux faons de gnrer du code HTML en dynamique


57

Affichage par dfaut de la page rectangle.jsp

Exemple : JSP rectangle

On va remplir les 4 champs avec valeurs 45, 12, 59, 47 58 et lancer l'excution de crer rectangle

Exemple : JSP rectangle

Rsultat de la cration du rectangle

On excute maintenant partir de cette page calcul surface

59

Exemple : JSP rectangle

Rsultat du calcul de surface

60

Modle par dfaut d'excution


Excution concurrente

Servlet / page JSP est unique Serveur HTTP peut avoir plusieurs requtes d'accs la servlet/JSP par plusieurs clients la fois

Excution multi-threade par le serveur HTTP Plusieurs threads peuvent donc excuter en mme temps du code de la mme servlet/JSP

S'assurer qu'un seul thread la fois excute une servlet/JSP

Servlet

Implmentation de l'interface (vide) SingleThreadModel public class MaServlet extends HttpServlet implements SingleThreadModel Passe par les paramtres gnraux de la page : isThreadSafe <%@ page isThreadSafe="true" %>

JSP

Pour une gestion plus fine et plus prcise

Marquer des mthodes ou des parties de code de la servlet/JSP 61 avec synchronized

Communication inter-lments

Chaque servlet / JSP possde un tat global ou un tat local pour chaque client

Peut aussi vouloir avoir un tat global toutes les pages JSP ou les servlets gres par le serveur HTTP
Permet de dfinir des attributs comme pour une session, mais communs toutes les pages JSP gres par le serveur HTTP Exemple : code Java pour grer un compteur commun toutes les pages JSP

Attribut implicite application dans JSP


<% Integer compteur = (Integer)application.getAttribute("compteur"); if (compteur==null) { // on cre le compteur qui n'existait pas compteur = new Integer(0); application.setAttribute("compteur", compteur); out.println("<p>Cration du compteur ...</p>"); } application.setAttribute("compteur", ++compteur); 62 out.println("<p>Compteur global : "+compteur+"</p>"); %>

Communication inter-lments

Etat commun global au serveur HTTP


Autre technique : dfinir une classe accessible (dans mme package) par toutes les servlets / JSP

Y dfinir des attributs ou mthodes statiques Exemple pour le compteur

public class Compteur { protected static int compteur = 0; public synchronized static int nextValue() { return ++compteur; } }

On accde par exemple au compteur global dans une servlet ou une page JSP

out.println("<p>Nombre d'appels : "+Compteur.nextValue()+"</p>");

63

Dans une servlet ou une page JSP, possibilit

Relation entre servlets/JSP

D'appeler une autre servlet ou page JSP pour dlguer le traitement de la requte ou inclure un rsultat supplmentaire dans celui de la servlet/page JSP courante Servlet

Rcupre le request dispatcher

RequestDispatcher rd = request.getRequestDispatcher( "maServlet" );

Fait suivre le traitement de la requte ou inclus un traitement ralis par la servlet maServlet

rd.forward(request, response); rd.include(request, response);

Page JSP

Inclusion du rsultat d'une autre page

<jsp:include page=''maPage.jsp''></jsp:include>

Faire suivre le traitement de la requte une autre page JSP


<jsp:forward page=''maPage.jsp''></jsp:forward> Dans les 2 cas, peut passer des paramtres la page appele via inclusion 64 <jsp:param name=''compteur'' value=''12'' />

Relation entre lments

En cas d'erreur dans une page JSP, peut aussi excuter une page JSP particulire
Dans la page, insrer une redirection en cas d'erreur

<%@ page errorPage=''erreur.jsp'' %> En cas d'exception leve par une instruction Java, la page erreur.jsp est alors excute Prciser que l'on est une page d'erreur

Dans erreur.jsp

<%@ page isErrorPage=''true'' %> <p>Exception leve : <%= exception %> </p> L'attribut implicite exception est une exception Java classique, on peut appeler dessus des mthodes comme getMessage(), getCause(), printStackTrace(), ... 65

Peut alors rcuprer l'exception leve et par exemple l'afficher


Retour sur l'exemple des rectangles

Dans une JSP, une part importante du code est ddie simplement afficher le contenu d'objets
Mme avec des <%= ... %> a peut tre relativement lourd raliser Reprenons notre manipulation de rectangles

Exemple
La servlet RectServlet gre le rectangle courant et excute les actions associs Une page HTML affiche un formulaire pour rentrer les diffrents champs Si l'utilisateur veut modifier une des 4 valeurs de coordonne (y1 par exemple) du rectangle courant, il doit rentrer les 4 valeurs On pourrait remplir par dfaut les 4 champs avec le contenu du rectangle courant 66

Retour sur l'exemple des rectangles

Modifie RectServlet.java pour ajouter le rectangle en tant qu'attribut de la session


protected void processRequest(...) { HttpSession session = request.getSession(true); // premier appel de la servlet, on cre l'attribut rectangle if (session.getAttribute("rectangle") == null) session.setAttribute("rectangle", rectangle); if (action.equals("creer")) { // rcupre les paramtres x1, x2, y1, y2 dans la requte (...) rectangle = new Rectangle(x1, y1, x2, y2); out.println("<p>Rectangle cr : "+rectangle + "</p>"); // met jour l'attribut de la session avec le nouveau rectangle session.setAttribute("rectangle", rectangle); } 67 (...)

Retour sur l'exemple des rectangles

Transforme la page HTML associe en page JSP pour pouvoir rcuprer le rectangle associ la session

<%@page import = "rect.Rectangle" %> <% Rectangle rect =(Rectangle) session.getAttribute(''rectangle''); %> <h1>Manipulation de rectangle avec une servlet</h1> <form action="RectServlet" method="post"> <p> <table border="0"> <tr> <td>X1</td> <td><input name="x1" value="<%=rect.getX1() %>"></td> </tr> (...) On rcupre l'attribut rectangle associ la session On s'en sert pour mettre une valeur par dfaut dans les champs d'entre des 4 valeurs de coordonnes

68

Retour sur l'exemple des rectangles

Le code prsent semble pertinent ... mais ne marche pas

Au premier chargement de la JSP, aucun appel n'a encore t fait sur la Servlet : pas d'attribut rectangle associ la session

L'attribut rect vaut donc null et <%= rect.getX1() %> lve une exception <%@page import = "rect.Rectangle" %> <% Rectangle rect = (Rectangle) session.getAttribute(''rectangle''); String x1 = '''', x2= '''', y1 = '''', y2 = ''''; if (rect != null) { x1 = new Integer(rect.getX1()).toString(); (...) } %> <h1>Manipulation de rectangle avec une servlet</h1> <form action="RectServlet" method="post"> <p> <table border="0"> <tr> <td>X1</td> <td><input name="x1" value="<%= x1 %>"></td> 69 (...)

Il faut grer explicitement le cas o l'attribut n'est pas encore dfini

Retour sur l'exemple prcdent

Autre solution pour rcuprer le rectangle courant


Expression UEL (Unified Expression Language) Simplifie l'accs aux attributs (dans le sens des attributs associs une session)

La page JSP devient tout simplement <h1>Manipulation de rectangle avec une servlet</h1> <form action="RectServlet" method="post"> <p> <table border="0"> <tr> <td>X1</td> <td><input name="x1" value='' ${sessionScope.rectangle.x1}''></td>
(...)

Le champ d'entre X1 est initialis par le contenu de la proprit x1 de l'attribut rectangle associ la session Si l'attribut rectangle n'existe pas, ne gnre pas d'erreur, retourne simplement une chaine vide

Plus besoin de vrifier explicitement que l'attribut existe

70

UEL & JSTL

Unified Expression Language (UEL)

Langage d'expression permettant simplement dans une page JSP


De rcuprer des attributs associs des contextes

Attributs de la session, de l'application, du header ou de la requte HTTP ... Addition, multiplication, modulo ...

D'crire des expressions de calcul ou de test

Comparaisons de valeurs, oprateurs logiques (OU, ET ...)

Java Server Pages Standard Tag Library (JSTL)


Ensembles de balises offrant des fonctionnalits pour manipuler des fichiers XML, accs des BDDs, l'internationalisation ... Ensemble core permet notamment de manipuler simplement des ensembles de donnes, faire des tests et d'associer des balises HTML (ou autres) ces traitements ... Facilite grandement dans une page JSP l'affichage de donnes 71 retourns par la logique mtier

En combinant UEL et JSTL

Attribut

UEL : attributs, proprits

Instance d'une classe Java respectant quelques contraintes structurelles : Java Beans

Dfinit des proprits

Un attribut (de la classe) avec un getter et un setter associ

Dfinit un constructeur sans paramtre

On peut ensuite accder aux proprits des attributs via une notation pointe partir d'un certain contexte

Exemple : sessionScope.rectangle.x1

Contexte : sessionScope Attribut : rectangle Proprit : x1 ((Rectangle)sessionScope.getAttribute(''rectangle'')).getX1() On voit bien l'obligation d'avoir un getter/setter associ chaque proprit pour pouvoir y accder

Revient excuter de manire rflexive


Si l'attribut ou une de ses proprits n'est pas dfinie (valeur null) 72 gnre une chane vide

UEL : contextes et objets implicites

Objets implicites, dont certains similaires aux objets implicites JSP


pageContext, param, paramValues, header, headerValues, cookie, initParam Contextes (scope), partir desquels on peut associer des attributs

pageScope : la page JSP requestScope : la requte HTTP sessionScope : la session associe avec le navigateur client applicationScope : contexte global toutes les pages JSP du serveur

73

Accde aux donnes d'un tableau (array, list ...) ou d'une map via une notation indexe

UEL : tableaux et map

att[index]

Avec index qui est soit la cl pour une map, soit l'index pour un tableau Peut aussi tre le contenu d'une variable Pour un tableau, peut utiliser un index sous forme d'entier ou de chaine

Exemple : une servlet excute le code suivant

Rectangle rect1 = new Rectangle(10,10,20,20); Rectangle rect2 = new Rectangle(30, 30, 50, 50); HashMap<String, Rectangle> mapRect = new HashMap<String, Rectangle>(); Rectangle[] arrayRect = new Rectangle[2]; int index = 1; mapRect.put("premier",rect1); mapRect.put("second", rect2); arrayRect[0] = rect1; arrayRect[1] = rect2; session.setAttribute("mapRect", mapRect); session.setAttribute("arrayRect", arrayRect); session.setAttribute("index", index);

74

UEL : tableaux et map

La servlet forwarde la requte la page JSP

<p> Map -> "premier" : ${sessionScope.mapRect["premier"].x1}<br /> Map -> 'second' : ${sessionScope.mapRect['second'].x1}<br /> Map -> "troisieme" : ${sessionScope.mapRect["troisieme"].x1}<br /> Array -> 0 : ${sessionScope.arrayRect[0].x1}<br /> Array -> '1' : ${sessionScope.arrayRect['1'].x1}<br /> Array -> 2 : ${sessionScope.arrayRect[2].x1}<br /> Array -> index : ${sessionScope.arrayRect[sessionScope.index].x1}<br /> </p>

Affichage rsultant

Map -> "premier" : 10 Map -> 'second' : 30 Map -> "troisieme" : Array -> 0 : 10 Array -> '1' : 30 Array -> 2 : Array -> index : 30

Si des lments dans la map n'existent pas ou si on dpasse75 l'index max du tableau, renvoie une chaine vide

UEL : oprateurs

Oprateurs logiques
&& (ou and), || (ou or), ! (ou not) == (ou eq), != (ou ne), > (ou gt) ... +, -, *, / (ou div), % (ou mod) Types de nombre disponibles : entier et rel empty : renvoie vrai si valeur vide
Egale null, chaine vide, un tableau vide ou une map vide ? : choix conditionnel 76 test ? choixVrai : choixFaux

Oprateurs de comparaison Oprateurs de calcul

Divers

Pour utiliser du JSTL core dans une page JSP, insrer la balise suivante dans la page

JSTL : core

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> Au dploiement, ne pas oublier le lien vers la librairie (.jar) externe implmentant cet ensemble de balises <c:out value=''valeur'' /> <c:if test=''condition''> ... </c:if> <c:choose> <c:when test=''condition1''> ... </c:when> <c:when test=''condition2''> ... </c:when> ... <c:otherwise> ... </c:otherwise> </c:choose>

Affichage d'une valeur

Test d'une valeur

Choix conditionnels

77

JSTL : core

Parcours d'une liste / tableau


<c:forEach items=''laListe'' var=''eltCourant''> ... </c:forEach> items : la liste ou le tableau parcourir var : variable qui contiendra l'lment courant Comme pour une liste mais sur l'lment courant

Parcours d'une map


Accde sa cl via : eltCourant.key Accs sa valeur via : eltCourant.value

Autres tags existants


<c:forTokens>,<c:set>, <c:remove>, <c:catch>, <c:import>, <c:url>, <c:redirect>, <c:param>
78

JSTL : core

Exemple
<c:if test="${empty sessionScope.arrayRect[2].x1}"> Pas d'lment d'index 2 dans le tableau<br /><br /> </c:if> Surface des rectangles :<br /> <c:forEach items="${sessionScope.arrayRect}" var="rect"> -> <c:out value="${(rect.x2 - rect.x1) * (rect.y2 - rect.y1)}"/><br /> </c:forEach>

Affichage rsultant
Pas d'lment d'index 2 dans le tableau Surface des rectangles : -> 100 -> 400

79

Servlet vs JSP

Servlet

C'est du java standard qui est excut Les lignes out.println() servent gnrer le code HTML qui sera affich Problme : une bonne partie de ce code HTML est statique

Entte, affichage du titre ... Un peu lourd gnrer de la sorte

Page JSP

Permet de mlanger du code HTML standard avec du Java standard Meilleure dcoupage des diffrentes parties qu'avec des servlets Moins lourd programmer qu'une servlet

Simplification des affichages des donnes, surtout si combin avec UEL et JSTL Mais moins structur du point de vue du code Java

80

Servlet et JSP

Servlet / JSP
Technologie cot serveur permettant donc la gnration dynamique de page HTML Intrt est de profiter de la puissance d'un langage Objet Le code embarqu dans les Servlet / JSP n'intgre pas de prfrence le code et la logique mtier

En pratique

On s'appuie sur d'autres lments (composants EJB par exemple) Logique de prsentation

Pour un serveur applicatif Web, dcouper son rle en

Manire de prsenter et de gnrer les pages aux clients Appele par la logique applicative pour gnrer les pages

Logique mtier

81

Frameworks de persistance : introduction Hibernate

82

Problmatique

Exemple simple d'application


Grer une liste de personnes Programmation partie mtier / client en Java

Classe qui contient les informations sur une personne public class Personne { String nom; Int age; } Lors du stockage d'une personne, on lui associera un identifiant unique // mthodes d'accs aux attributs age et nom

Deux techniques de stockages de l'ensemble de personnes


Directement en Java via une HashMap Hashmap<Integer, Personne> personnes; Via un SGBD avec accs en SQL aux donnes

Stockage sous forme de tables SQL

personne (int id, varchar(20) nom, int age)

83

Problmatique

Code pour rcuprer une personne via son id


Pur Java
public Personne getPersonne(int id) throws InvalidIdException { // si la personne n'existe pas, lve exception if ( ! (personnes.containsKey(new Integer(id)))) throw new InvalidIdException("invalid index value : "+id); // sinon, retourne son identifiant return (personnes.get(new Integer(id)));

Manipule directement la HashMap personnes Code naturel, programmation Java standard


84

Problmatique

Java avec stockage BDD et accs via JDBC


public int getId(Personne p) throws InvalidIdException { try { Statement requete = connection.createStatement(); // requte SQL pour rechercher la personne ResultSet result = requete.executeQuery("SELECT NOM, AGE FROM PERSONNE WHERE ID=\""+id+"\""); // regarde si la requte a renvoy quelque chose : si a n'est pas // le cas, la personne n'existait pas if (!result.next()) throw new InvalidIdException("invalid index value : "+id); // sinon, partir du rsultat retourn, instancie une personne // avec les valeurs du rsultat else return new Personne(result.getInt("age"), result.getString("nom")); } catch(SQLException e) { System.err.println(e); } }

85

Problmatique

Java avec stockage BDD et accs via JDBC


Ncessite des requtes SQL

Utilisation d'un framework ddi : JDBC

Sort du format standard de reprsentation Java des donnes

Une requte de type SELECT retourne un ResultSet

C'est dire un ensemble de ligne de plusieurs colonnes

On accde aux lments du ResultSet en naviguant selon les lignes et les colonnes Peu pratique mais difficile de faire autrement vu ce que retourne de manire native les requtes SQL

Sauf passer par des SGBD objet-relationnel

86

Problmatique

Java avec stockage BDD et accs via JDBC


Au dela de l'accs faire distance

Qui complexifie forcment les choses mais ne peut pas y couper Cot BDD

Reprsentation des donnes trs diffrentes

Structure en table avec langage de requte ddi Rcupre toujours une sous-table via le rsultat de l'excution d'une requte de type SELECT Instances de classe (Personne ici) : objets Les objets sont associs entre eux et forment un graphe d'objet dans l'application

Cot Java

?
87

Problmatique

Doit tre capable de faire la correspondance d'une reprsentation une autre


Pas simple : d'une reprsentation objet une reprsentation relationnelle Le faire la main

Solution
Comme pour notre exemple Cot BDD, la structure de stockage intgrera des concepts objets Passage plus facile du programme au stockage dans la base Mais toujours besoin de faire des requtes explicites 88

Utiliser une base de donnes relationnelle oriente objet


Utiliser un framework de persistance

Framework de persistance

Principes
S'abstraire des problmatiques de stockage des donnes

Pouvoir manipuler directement des entits mtiers indpendamment de leur stockage physique La structure des classes utilises dans l'application Le stockage physique utilis par le support de persistance

Dfinition de mappings entre


Gnralement, un SGBD relationnel

Lors de l'excution de l'application


Cration, suppression, manipulation, collections d'objets ... grs de manire classique, programmation standard Le framework fait le lien entre le graphe d'objet en mmoire dans l'application et le stockage physique

Typiquement : envoi de requte SQL au SGBD pour rcuprer des donnes, les modifier, les ajouter / supprimer

89

Framework de persistance

Intrt des frameworks de persistance


Plus besoin de se proccuper du stockage physique et des problmes de correspondance Comme on le voit dans notre exemple de l'atelier

Ecriture des requtes SQL via JDBC est assez lourd L'implmentation des accs aux donnes peut reprsenter un temps important lors du dveloppement d'une application

On gagne ainsi en temps de dveloppement et en indpendance des supports physiques

Suffit de changer les rgles de mappings sans modifier le code de l'application

Hibernate

Framework de persistance libre pour le monde Java

NHibernate pour .Net

Standard de fait, trs utilis dans l'industrie Utilis galement par JPA (framework standard de persistance sous Java Java Persistence API)

90

Hibernate
Principes gnraux d'Hibernate
Dfinition des structures de donnes / entits manipules

Relation entre la structure cot BDD et la structure des entits


Via des fichiers XML Ou des classes Java annotes

Cot Java, l'entit est une classe Java dite persistante

Un POJO : Plain Old Java Objet


Classe Java totalement standard avec dfinition d'attributs, d'accesseurs, de constructeurs pour gestion donnes de l'entit Ne s'appuie donc pas sur des frameworks ou librairies particuliers, contrairement par exemple aux entits d'EJB

Persistante : son contenu est li avec les donnes physiques sur la BDD et est sauvegard dans cette BDD Dfinition, en XML, d'un ensemble de fichiers de configuration

Mapping d'une entit vers un support physique Configuration gnrale de l'accs au support physique

91

Hibernate

Principes gnraux d'Hibernate (fin)


Pour grer la persistance, on cre une session Hibernate Via cette session, peut

Rcuprer sous forme d'instances de POJO des donnes stockes par le support physique

Utilisation notamment d'HQL (Hibernate Query Language)

Modifier le contenu de ces POJO, leurs associations, en ajouter, en supprimer, ... Le framework fera le lien entre les modifications locales et le stockage physique

Fonctionne en mode transactionnel pour les modifications


1. Cration d'une transaction 2. Modification des objets 3. Validation de la modification (commit) ou annulation en cas de problme (rollback)

92

Exemple Hibernate

Exemple de gestion de sports et de disciplines


Un sport contient plusieurs disciplines Tables du SGBD (Oracle ici)

sport (code_sport , intitule) discipline (code_discipline, intitule, code_sport)

Ici cot Java, on choisira d'avoirdes objets de type Sport et Discipline


Avec les mmes structures de donnes que ce qui est stock dans la base Mais a n'est pas une obligation d'avoir exactement la mme chose (voir plus loin)

93

Exemple Hibernate

Contenu des tables pour l'exemple


Table sport

code | sport | intitule ------+----------1 | athletisme 2 | ski 3 | natation code | | code discipline | intitule | sport -----------+------------------+-----1 | 100 metres | 1 2 | 200 metres | 1 3 | saut en hauteur | 1 4 | saut en longueur | 1 5 | 100m 4 nages | 3 6 | 100m papillon | 3 7 | marathon | 1

Table discipline

94

Hibernate : ex. configuration gnrale

Configuration gnrale d'Hibernate


<hibernate-configuration> <session-factory> <property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property> <property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property> <property name="hibernate.connection.url">jdbc:oracle:thin:@scinfe099:1521:etud10</property> <property name="hibernate.connection.username">ecariou</property> <property name="hibernate.connection.password">toto</property> <property name="hibernate.show_sql">true</property> <mapping class="data.Sport" file="" jar="" package="" resource="data/Sport.hbm.xml"/> <mapping class="data.Discipline" file="" jar="" package="" resource="data/Discipline.hbm.xml"/> </session-factory> </hibernate-configuration>

On y trouve, notamment

Les paramtres de connexion la base Oracle (avec le type de driver utiliser)

On peut voir que l'accs en pratique se fera via JDBC Ex: data.Sport (classe Java) dont le mapping est prcis dans 95 Sport.hbm.xml

L'association d'un POJO avec son fichier de mapping

Hibernate : ex. de fichier de mapping

Fichier Sport.hbm.xml

<hibernate-mapping> <class name="data.Sport" table="SPORT" schema="ECARIOU"> <id name="codeSport" type="short"> <column name="CODE_SPORT" precision="4" scale="0" /> <generator class="assigned" /> </id> <property name="intitule" type="string"> <column name="INTITULE" length="20" /> </property> <set name="disciplines" inverse="true"> <key> <column name="CODE_SPORT" precision="4" scale="0" /> </key> <one-to-many class="data.Discipline" /> </set> </class> </hibernate-mapping>

Dans classe data.Sport, attributcodeSport correspond la colonne CODE_SPORT de la table SPORT Dfinition d'un ensemble nomm disciplines dans la classe data.Sport

Jointure avec la table discipline : toutes les disciplines de ce sport

96

Hibernate : ex. de POJO

POJO d'un sport, gnr partir du fichier de mapping


public class Sport implements java.io.Serializable { private short codeSport; private String intitule; private Set disciplines = new HashSet(0); public Sport() { } public Sport(short codeSport) { this.codeSport = codeSport; } public Sport(short codeSport, String intitule, Set disciplines) { this.codeSport = codeSport; this.intitule = intitule; this.disciplines = disciplines; } public short getCodeSport() { return this.codeSport; } public void setCodeSport(short codeSport) { this.codeSport = codeSport; } public String getIntitule() { return this.intitule; } public void setIntitule(String intitule) { this.intitule = intitule; } public Set getDisciplines() { return this.disciplines; } public void setDisciplines(Set disciplines) { this.disciplines = disciplines; }

Dfinition des attributs, avec getter et setter associs

Dfinition des constructeurs (avec un constructeur sans paramtre) 97


Redfinir mthodes equals() et hashcode() pour gestion dans collections

Hibernate : ex. accs aux donnes

Affichage de la liste des sports, avec pour chacun la liste de ses disciplines
// cration session Hibernate (et donc connexion au serveur Oracle) Session session = (new Configuration().configure().buildSessionFactory()).openSession(); // requte en HQL : rcupre la liste de tous les sports, // sous forme d'une liste Java Query query = session.createQuery("from data.Sport"); List sports = query.list(); // variables utilises pour le parcours de la liste des sports Set disciplines; Iterator itSport, itDisc; Sport sport; Discipline disc;

98

Hibernate : ex. accs aux donnes

Affichage de la liste des sports, avec pour chacun la liste des disciplines (suite)
// parcourt les sports itSport = sports.iterator(); while (itSport.hasNext()) { sport = (Sport) itSport.next(); System.out.println(sport.getCodeSport() + " -> " + sport.getIntitule()); // rcupre l'ensemble des disciplines du sport disciplines = sport.getDisciplines(); itDisc = disciplines.iterator(); // parcourt les disciplines while (itDisc.hasNext()) { disc = (Discipline) itDisc.next(); System.out.println(" "+disc.getCodeDiscipline() + " -> "+disc.getIntitule()); } 99

Hibernate : ex. accs aux donnes

Affichage rsultant de l'excution

1 -> athletisme 1 -> 100 metres 2 -> 200 metres 7 -> marathon 4 -> saut en longueur 3 -> saut en hauteur 2 -> ski 3 -> natation 6 -> 100m papillon 5 -> 100m 4 nages

Point intressant

A partir d'un objet de classe Sport, on accde directement sa liste de disciplines via getDisciplines() : ensemble d'objets

Les objets sont chargs partir de la base directement sans besoin de traitement particulier, c'est transparent Si on tait pass par du SQL via JDBC, on aurait du faire une requte explicite du type

SELECT * FROM DISCIPLINE WHERE CODE_SPORT=XX

100

Hibernate : ex. accs aux donnes

A l'excution, peut demander tracer les requtes SQL effectues, ce qui donne ici

Hibernate: select sport0_.CODE_SPORT as CODE1_0_, sport0_.INTITULE as INTITULE0_ from ECARIOU.SPORT sport0_ 1 -> athletisme Hibernate: select discipline0_.CODE_SPORT as CODE2_1_, discipline0_.CODE_DISCIPLINE as CODE1_1_, discipline0_.CODE_DISCIPLINE as CODE1_1_0_, discipline0_.CODE_SPORT as CODE2_1_0_, discipline0_.INTITULE as INTITULE1_0_ from ECARIOU.DISCIPLINE discipline0_ where discipline0_.CODE_SPORT=? 1 -> 100 metres 2 -> 200 metres 7 -> marathon 4 -> saut en longueur 3 -> saut en hauteur (...)

Premier SELECT : pour rcuprer la liste des sports Deuxime SELECT : pour rcuprer la liste des disciplines du sport courant

101

Hibernate : ex. accs aux donnes

Autre exemple : ajout d'une discipline au sport natation


try { // ouvre la session et une transaction session = (new Configuration().configure().buildSessionFactory()).openSession(); trans = session.beginTransaction(); // rcupre l'instance de sport correpondant natation (requte en HQL) query = session.createQuery("select sport from Sport sport where sport.intitule='natation'"); // ajout du relais 4 x 100 dans le sport natation en rendant l'objet persistant disc = new Discipline((short)8, sport, "relais 4 x 100"); session.persist(disc); // commit pour valider physiquement l'ajout trans.commit(); } catch (Exception e) { System.err.println("Erreur Hibernate : " + e); // problme : on annule la transaction trans.rollback(); } session.close();

102

Notes sur code d'ajout

Hibernate : ex. accs aux donnes


On passe une rfrence d'objet, on ne donne pas une cl identifiant un sport comme on le ferait avec SQL On est bien dans de la manipulation standard d'objets

On cre l'objet discipline disc avec l'objet sport en paramtre

Le persist() sur cet objet permet directement, sans traitement supplmentaire, de le rendre persistant (voir plus loin pour dtails)

C'est--dire l'enregistrer dans la BDD

Si on trace les requtes SQL, on obtient

Hibernate: select sport0_.CODE_SPORT as CODE1_0_, sport0_.INTITULE as INTITULE0_ from ECARIOU.SPORT sport0_ where sport0_.INTITULE='natation' Hibernate: insert into ECARIOU.DISCIPLINE (CODE_SPORT, INTITULE, CODE_DISCIPLINE) values (?, ?, ?)

La premire requte est un SELECT qui rcupre les donnes du sport natation La deuxime requte est un INSERT qui ajoute la discipline 103 qu'on vient de crer

Exemple plus dtaill

Modlisation mtier de l'application de sports avec ajout d'une classe / entit sportif

104

Exemple plus dtaill

Classes Sport et Disciplines

Reprend les mmes contenus qu'on vient de voir

Une discipline est associe un sport

Ajoute une entit Sportif

Un sportif pratique plusieurs disciplines et une discipline est pratique par plusieurs sportifs

Association bidirectionnelle * <-> * pratique entre les 2 classes Le nombre de disciplines se dtermine partir de l'association pratique Ex. en OCL : context Sportif def: nbDisciplines : int = pratique -> size()

Attribut nbDisciplines est driv


Un sportif a un nom et une adresse Association unidirectionnelle drive /sports entre Sportif et Sport

Les sports pratiqus par le sportif Se dtermine de l'association pratique en rcuprant les sports 105 de ces disciplines : pratique.sport -> asSet()

Exemple plus dtaill

Tables associes dans le SGBD


Conserve les tables sport et discipline dj vues

sport (code_sport, intitule) discipline (code_discipline, intitule, code_sport)

code_sport : cl trangre venant de sport

Donnes sur un sportif

Une adresse est spcifique un sportif : peut inclure les donnes de l'adresse avec les donnes du sportif

sportif(code_sportif, nom, rue, code_postal,ville)

Association entre disciplines et sportifs : ncessite une table d'association

pratique(code_sportif, code_discipline)

Cl primaire : combinaison de code_sportif et code_discipline Cls trangres : code_sportif de sportif et code_discipline 106 de discipline

Exemple plus dtaill

Point fondamental lors de l'utilisation d'un framework de persistance

Pas de ncessit/peu recommand d'avoir un mapping 1 vers 1 entre une table de la BDD et une classe cot mtier

On modlise d'un cot le mtier et de l'autre la BDD en s'attachant faire les meilleures modlisations selon le domaine

Cot mtier : structure logique et facilit de manipulation des donnes Cot BDD : optimiser la sauvegarde des donnes et performance d'accs

On dfinira ensuite les mappings adquats

Dans notre exemple

Les donnes de la classe Adresse et de la classe Sportif sont stockes via une seule table et non pas deux tables diffrentes La table d'association pratique n'a pas tre reprsente par une classe

107 L'attribut nbDisciplines est utile/pertinent seulement cot mtier

On aura directement des mthodes dans les classes Sportif et Discipline pour rcuprer les lments correspondants Le fichier de mapping permettra de directement grer cette association

Mapping pour la classe Sportif

Contenu de la classe Sportif : POJO


public class Sportif implements java.io.Serializable { private int codeSportif; private String nom; private Set disciplines = new HashSet(0); private int nbDisciplines; private Adresse adresse; public Sportif() { } (...)

Dfinition des attributs


Avec disciplines qui est une association cardinalit multiple donc utilise un Set Chaque attribut doit possder un getter et un setter Peut en dfinir d'autres en plus 108

Obligation d'un contructeur sans paramtre

Mapping pour la classe Sportif

Fichier de mapping pour la classe Sportif

<hibernate-mapping> <class name="data.Sportif" table="sportif" catalog="sports">

La classe persistante data.Sportif se base sur le contenu de la table sportif <id name="codeSportif" type="int"> <column name="code_sportif" /> <generator class="assigned" /> </id> Dfinition d'un attribut codeSportif correspondant la colonne code_sportif de la table La balise <id> prcise qu'on est en train de dfinir un attribut jouant le rle particulier d'identification de l'objet

Balise non obligatoire mais fortement recommande Par principe, elle sera en gnral lie la cl primaire de la table assigned : gr la main par celui qui cre les classes Peut utiliser d'autres valeurs pour une gnration automatique (voir plus loin)

La balise <generator> prcise comment l'identifiant est gnr


109

Mapping pour la classe Sportif

<property name="nom" type="string"> <column name="nom" length="20" /> </property>

Balise <property> dfinit une proprit au sens des Java Beans, concrtement, un attribut simple (autre qu'une collection, tableau ...) de la classe

Ici l'attribut nom mappe la colonne nom de la table

<property name="nbDisciplines" type="integer" formula = "(select count(*) from PRATIQUE p where code_sportif = p.code_sportif)" />

Champ formula (ou balise <formula>) permet de dfinir une formule (expression SQL) au lieu d'un mapping vers une colonne d'une table

Ici on compte le nombre de disciplines associes au sportif courant via une requte sur la table pratique L'appel du setter associ (setNbDisciplines) ne servira rien ... 110

Mapping pour la classe Sportif

<component name="adresse" class="data.Adresse"> <property name="rue" type="string"> <column name="rue" length="50" /> </property> <property name="codePostal" type="string"> <column name="code_postal" length="5" /> </property> <property name="ville" type="string"> <column name="ville" length="15" /> </property> </component>

Balise <component> dfinit un lment compos (relation UML de composition) dans la classe courante

Ici on dfinit un attribut adresse de classe Adresse qui contient les attributs rue, codePostal et ville mappant les colonnes quivalentes dans la table sportif (la table de la classe engloblante) La classe Adresse est dfinie comme un POJO car sera persitante public class Adresse implements java.io.Serializable { private String rue; private String codePostal; private String ville;

111

Mapping pour la classe Sportif

<set name="disciplines" inverse="false" table="pratique"> <key> <column name="code_sportif" not-null="true" /> </key> <many-to-many entity-name="data.Discipline"> <column name="code_discipline" not-null="true" /> </many-to-many> </set>

Balise <set> dfinit un ensemble de donnes Correspond ici au mapping d'une association avec une cardinalit multiple sur une autre table (ici pratique) Balise <key> : cl trangre sur la table avec laquelle on fait la jointure

Sur la table pratique, la cl trangre est code_sportif Balise <many-to-many> dfinit une association en * <-> *

On fait la jointure sur la colonne code_discipline de pratique Retournera des instances de la classe Discipline L'attribut disciplines de la classe Sportif correspond donc l'ensemble des disciplines trouves dans pratique avec le mme 112 code_sportif que le sportif courant

Association bidirectionnelle

Dans la classe Discipline, on trouvera l'association inverse, de discipline vers sportif


Dans la classe Discipline, attribut

private Set sportifs; <set name="sportifs" inverse="true" table="pratique"> <key> <column name="code_discipline" not-null="true" /> </key> <many-to-many entity-name="data.Sportif"> <column name="code_sportif" not-null="true" /> </many-to-many> </set> Ensemble de sportifs correspondant la jointure via la table pratique et la cl code_discipline 113

Dans le mapping de la classe Discipline

Association bidirectionnelle

Contrainte pour un mapping d'association bidirectionnelle

D'un des deux cots, on doit avoir un inverse = true dans la dfinition du set (et un false, par dfaut, de l'autre)

Ici c'est dans le mapping pour la classe Discipline

Dans les classes, pour assurer la bidirectionnalit, on doit faire un ajout dans les deux ensembles des deux lments

Classe Sportif

public void addDiscipline(Discipline disc) { this.disciplines.add(disc); disc.getSportifs().add(this) } public void addSportif(Sportif sportif) { this.sportifs.add(sportif); sportif.getDisciplines().add(this); }

Classe Discipline

114

Association et cardinalits

Quatre type d'associations, par jointure en prcisant la cl trangre


<one-to-one>

Un vers un Un vers plusieurs : sport vers discipline Plusieurs vers un : discipline vers sport Plusieurs vers plusieurs : entre discipline et sportif Ncessite une table d'association entre les 2 tables 115

<one-to-many>

<many-to-one>

<many-to-many>

Mapping pour la classe Sportif

Reste dfinir l'ensemble (driv) des Sports


Consiste rcuprer les sports des disciplines du sportif courant En SQL, jointure sur les 4 tables pratique, discipline, sportif et sport, en fonction de la valeur code_monSportif

select distinct(sport.code_sport), sport.intitule from discipline, pratique, sportif, sport where sportif.code_sportif = code_monSportif and discipline.code_discipline = pratique.code_discipline and pratique.code_sportif = sportif.code_sportif and sport.code_sport = discipline.code_sport

Difficile exprimer par un mapping Hibernate, on va passer par une requte

Rajoute dans la classe Sportif la mthode suivante

public Set<Sport> getSports() { ... }

Pas besoin d'un attribut sports car il ne sera pas persistant

116

Requte getSports()

Premire (mauvaise) implmentation

Utilisation de Java au maximum

public Set<Sport> getSports() { Set<Sport> sports = new HashSet<Sport>(); Iterator it = this.getDisciplines().iterator(); while (it.hasNext()) sports.add(((Discipline)it.next()).getSport()); return sports; } Parcourt les disciplines du sportif et rcupre pour chacun le sport associ On place ces sports dans un Set (qui par principe ne contiendra pas de doublon) On oblige en effet charger en mmoire (de la BDD vers le programme Java) toutes les disciplines du sportif alors qu'on n'en a pas besoin 117 Problme potentiel de performance

Trs mauvaise ide !

Bonne implmentation

Requte getSports()

Passer par une requte en HQL (Hibernate Query Language)


Equivalente celle qu'on aurait faite en SQL ... mais en plus simple
Set<Sport> sports = new HashSet<Sport>(); // cration de la requte Query query = session.createQuery( "select distinct(sport) from data.Sport sport, data.Discipline disc"+ "where disc.sport = sport and :leSportif in elements(disc.sportifs)"); // le sportif est l'objet courant query.setParameter("leSportif", this); // construit le set retourner partir de la liste rsultat de la requte Iterator it = query.list().iterator(); while (it.hasNext()) sports.add(it.next()); return sports; } public Set<Sport> getSports() {

Note : ne pas oublier de grer en plus les exceptions

118

Langage de requte HQL

Requte HQL prcdente


Se lit assez simplement : rcuprer la liste des sports des disciplines qui sont associes au sportif pass en paramtre Utilisation d'un paramtre nomm pour prciser le sportif

query.setParameter(''nomParam'', valeur); Avec la valeur pouvant directement tre un objet

Comme ici : c'est une instance de la classe Sportif

Excution de la requte

Appel de list() sur l'objet requte qui retourne la liste des rsultats On peut ensuite associer un itrateur cette liste Attention !

Il existe une mthode iterate() appelable directement sur l'objet requte Iterator it = query.iterate(); Cette mthode ne charge pas en mmoire les objets persistants retourns par la requte S'ils taient dj chargs, a marche, sinon on ne rcupre rien Donc privilgier l'usage de : Iterator it = query.list().iterate(); 119

Langage de requte HQL

HQL est un langage de requte aussi puissant que SQL et qui est en plus orient objet

Permet de manipuler directement des objets (instances de POJO)

Dfinir une variable sport correspondant une instance de la classe data.Sport : ... data.Sport sport ... Rcuprer l'objet sport associ une discipline : ... disc.sport ...

Permet de naviguer sur les associations entre objets

Mmes fonctionnalits que SQL, gestion du polymorphisme...

Au final, les requtes HQL sont gnralement (bien) plus simples que les requtes SQL quivalentes

Trace de la requte SQL excute

select distinct sport0_.code_sport as code1_7_, sport0_.intitule as intitule7_ from sports.sport sport0_, sports.discipline discipline1_ where discipline1_.code_sport=sport0_.code_sport and (? in (select sportifs2_.code_sportif from pratique sportifs2_ where discipline1_.code_discipline=sportifs2_.code_discipline)) 120 Deux requtes SELECT imbriques sur 4 tables

Langage de requte HQL

Si l'on sait qu'une requte ne renvoie qu'un seul rsultat

Peut utiliser uniqueResult() au lieu de list() pour rcuprer le rsultat

query = session.createQuery("select sport from data.Sport sport where sport.codeSport = '2' "); Sport sport = (Sport)query.uniqueResult(); if (sport == null) System.out.println("Pas de sport 2"); else System.out.println("Le sport 2 est : "+sport.getIntitule());

Si une requte slectionne plus d'une valeur, on rcupre un ensemble de tableaux, un tableau par rsultat

query = session.createQuery("select sportif.nom, sportif.adresse.ville from data.Sportif sportif"); Iterator it = query.list().iterator(); System.out.println("Nom des personnes avec leur ville"); while(it.hasNext()) { Object[] res = (Object[])it.next(); System.out.println("nom : " + res[0] + ", ville : " + res[1]); 121 }

Cycle de vie d'un objet persistant

Toutes les fonctions de gestion du cycle de vie d'un objet se font par rapport une session Hibernate ouverte Toute modification d'tat se fait en mode transactionnel

Rendre persistant un objet, modifier le contenu d'un objet persistant, supprimer un objet persistant, ... Schma gnral appliquer de prfrence

En cas d'erreur (exception leve) lors de la transaction, excuter systmatiquement un rollback pour annuler ce qui a pu tre modifi
session = (new Configuration().configure().buildSessionFactory()).openSession();

(...) try { trans = session.beginTransaction(); // faire les modifications voulues (...) // pas d'erreur, on commit trans.commit(); } catch (Exception e) { // problme : on annule tout if (trans != null) trans.rollback(); }

122

Cycle de vie d'un objet persistant

Plusieurs mthodes pour charger un objet persistant partir de la BDD


Excuter des requtes HQL comme on l'a vu Utiliser des requtes natives SQL

SQLQuery query = session.createSQLQuery(...); Connection conn = session.connection();

Rcuprer une connexion JDBC puis faire des requtes SQL

Utiliser l'API Criteria Si on connait l'identifiant d'un objet : load() ou get()


Charger le sportif d'identifiant gal 2

Sportif sportif = session.load(Sportif.class, 2); Si ne trouve pas l'objet (identifiant inexistant), load() lve une exception et get() renvoie null Contrairement get(), load() ne charge pas forcment tout de suite l'objet en mmoire, l'exception potentielle sera donc leve 123 seulement quand on accdera aux donnes de l'objet

Diffrence entre load() et get()


Cycle de vie d'un objet persistant

Crer un objet et le rendre persistant


Instantier de manire normale un POJO et positionner la valeur de ses attributs Si l'on ne veut pas grer soi mme la cl primaire associ au POJO dans la BDD

Dans fichier de mapping, balise <id>, balise <generator>, champ class peut prendre diffrentes valeurs

assigned : la charge de celui qui instancie l'objet de fixer la cl primaire (valeur par dfaut si aucun gnrateur n'est prcis) native : laisse le SGBD dterminer la cl primaire (valeur entire seulement) selon ses fonctionnalits uuid : identifiant sous forme de chaine, en utilisant l'adresse IP de la machine ....

Ensuite, on rend l'objet persistant via l'appel de persist() ou save() sur la transaction courante

Sport sport = new Sport(); sport.setIntitule(''pche''); session.persist(sport);

124

Cycle de vie d'un objet persistant

Crer un objet et le rendre persistant (suite)

Diffrence entre persist() et save()


save() ralise immdiatement la gnration de la cl mais l'enregistrement physique se fera plus tard persist() fait les deux actions simultanment et immdiatement Transaction trans = trans.beginTransaction(); Sport sport = new Sport(''pche''); Discipline disc = new Discipline(''mouche'', sport); session.persist(disc); trans.commit(); Ce code gnrera une exception car le sport associ la discipline n'a pas t rendu persistant

Attention aux dpendances entre objets crs

Il faut donc le faire explicitement Ou prciser dans les fichiers de mapping que la persistance se fait automatiquement en cascade Dans une dfinition d'association (<many-to-one>, ...) ajouter le champ : cascade = ''persist''

125

Dtacher / rattacher un objet

Cycle de vie d'un objet persistant

Tout objet persistant (charg depuis la BDD, instanti puis rendu persistant) est attach la session

L'tat de l'objet est li avec le contenu de la BDD tant que la session existe

Dans certains cas, on peut vouloir dtacher un objet


Mthodes evict() ou close() Il n'est plus associ la session mais existe encore en BDD

Ses modifications ne sont plus rpercutes sur la BDD

Peut ensuite rattacher l'objet la session et rpercuter ses modifs

Mthodes merge(), lock(), update(), saveOrUpdate()

Supprimer un objet persistant

Mthode delete() : session.delete(sport);

Le contenu de l'objet est supprim de la BDD (mais l'objet Java existe toujours lui, il n'a juste plus aucun lien avec la BDD) Dans fichier de mapping, utiliser au besoin des champs : cascade=''delete'' et cascade=''all-delete-orphan''

Attention aux dpendances entre objets lors de la suppression

126

Cycle de vie d'un objet persistant

Modifier un objet persistant

Modifier son contenu via l'appel des setters et autres accs aux collections

sportif.getAdresse().setRue(''rue Emile Guichenn''); sportif.getAdresse().setCodePostal(''64000''); sportif.getAdresse().setVille(''Pau''); sportif.addDiscipline(disc);

La dtection de la modification et la mise jour sur la BDD sont faites automatiquement par Hibernate

En pratique, la mthode flush(obj) est appele pour faire la mise jour physique

Recharger le contenu d'un objet persistant


Mthode refresh(obj) Il n'y a pas de raison d'appeler explicitement cette mthode vu que les modifications sont transmises, sauf si on sait qu'un trigger a t excut 127

Autres fonctionnalits de mapping

Collections

On a dfini des mappings correspondant des jointures retournant une collection java de type Set via une balise <set> On peut dfinir d'autres types de collections, correspondant aux types Java quivalents

bag, list, map, array, collections indexes ...

Balise <join>

Permet de mapper des donnes venant de plusieurs tables dans une seule classe cot Java Mappings pour une hirarchie d'hritage Trois stratgies possibles

Hritage

Une table unique pour toutes les classes Une table par classe logique (mapping pour la classe mre + mappings pour les classes filles) 128 Une table par classe concrte (pas de mapping pour la classe mre)

Performance

Concurrence & performances

Les performances sont principalement lies au chargement en mmoire des donnes Comme le graphe d'objets lis est potentiellement grand, on essaye de charger les objets uniquement la demande

Champ lazy=''true'' dans les mappings des collections Par dfaut, quand Hibernate charge un objet, il ne charge pas ses collections associes tant qu'on y accde pas

Exemple avec code prcdent, et sa trace, accdant aux sports et leurs disciplines

Un premier SELECT rcupre tous les sports


Pour chaque sport, un autre SELECT est excut pour rcuprer la liste des disciplines quand on y accde (au moment du sport.getDisciplines())

Gestion de la concurrence

Mmes fonctionnalits que dans les SGBD pour grer de manire prcise les accs concurrents : verrous sur donnes, ... 129 La gestion dtaille des transactions est importante

Mapping par annotation

Nos mappings se basent sur des couples de fichiers

La classe Java (le POJO) et son fichier XML de mapping

Peut aussi directement ajouter des annotations dans la classe Java pour prciser les mappings

@Entity @Table(name = "sport") @NamedQueries({@NamedQuery(name = "Sport.findAll", query = "SELECT s FROM Sport s"), @NamedQuery(name = "Sport.findByCodeSport", query = "SELECT s FROM Sport s WHERE s.codeSport = :codeSport"), @NamedQuery(name = "Sport.findByIntitule", query = "SELECT s FROM Sport s WHERE s.intitule = :intitule")}) public class Sport implements Serializable { private static final long serialVersionUID = 1L; @Id @Basic(optional = false) @Column(name = "code_sport") private Integer codeSport; @Column(name = "intitule") private String intitule; @OneToMany(mappedBy = "codeSport") private Collection<Discipline> disciplines; (...)

130

Conclusion sur Hibernate

Framework de persistance trs puissant (on n'en a vu qu'une introduction dtaille)


Indpendance des supports physiques Gestion des caractristiques objet (hritage ...) Politiques de chargements des objets ( la demande ...) Langage de requte HQL

Un SQL-like orient objet La gestion des donnes est principalement du Java natif, pas soucier de comment sont gres et accdes les donnes

Permet vraiment de se consacrer sur la logique mtier

Au niveau du programme en tout cas, car il faut quand mme concevoir la base de donne et les mappings Cot Java, on manipule donc directement les entits mtiers telles qu'on les a conues 131 Mme si on doit avoir en tte qu'elles ont une persistance en BDD

Documentation Hibernate

Site officiel d'Hibernate


http://www.hibernate.org Avec beaucoup de documentation

Traductions franaises du manuel de rfrence du site d'Hibernate


http://www.dil.univ-mrs.fr/~massat/docs/hibernate-3.1/reference/fr/html/index.html http://docs.jboss.org/hibernate/core/3.3/reference/fr/html/index.html

Livre
Hibernate 3.0 Gestion optimale de la persistance dans les applications Java/J2EE, Anthony Patricio, Eyrolles
132

Combinaison de Hibernate, servlets, pages JSP avec UEL et JSTL pour afficher les sportifs avec leurs disciplines et sports pratiqus
Page HTML via un lien envoie une requte la servlet SportServlet Servlet SportServlet.java (d'URL /Sports)

Exemple final

Rcupre via une requte HQL l'ensemble des sports Ajoute cet ensemble la requte HTTP reue par la servlet Puis fait suivre (forward) la requte HTTP la page afficherSports.jsp Rcupre l'ensemble des sports dans la requte HTTP Via UEL et JSTL, met en page leur affichage

Page afficherSports.jsp

La servlet ne gnre aucun code HTML, c'est le 133 rle de la page JSP qui on a forward la requte

Exemple final

Lien dans la page HTML

<a href="Sports?operation=listeSportif" target="operation"> Afficher la liste des sportifs</a> public List<Sportif> getListeSportifs() throws Exception { Session session = this.openHibernateSession(); Query query = session.createQuery("from data.Sportif"); return query.list(); } protected void processRequest( ... request, ... response) { String operation = request.getParameter("operation"); if (operation.equals("listeSportif")) { // rcupre la liste des sports et l'associe la requte HTTP request.setAttribute("sportifs", getListeSportifs()); // forwarde la requte la page JSP getServletConfig().getServletContext().getRequestDispatcher( "/afficheSportifs.jsp").forward(request,response); 134 } (...)

Code de SportServlet.java

Page JSP afficheSportifs.jsp

Exemple final

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <h2>Liste des sportifs et de ce qu'ils font</h2> <c:forEach items="${requestScope.sportifs}" var="sp"> <h3>${sp.nom}</h3> <p><b>Adresse : </b>${sp.adresse.rue} - ${sp.adresse.codePostal} ${sp.adresse.ville}</p> <c:choose> <c:when test="${empty sp.disciplines}"> <p><i>Ne pratique aucune discpline sportive</i></p> </c:when> <c:otherwise> <p><b>Liste des disciplines pratiques : </b></p> <ul> <c:forEach items="${sp.disciplines}" var="disc"> <li>${disc.intitule}</li> </c:forEach> </ul> <p><b>Liste des sports : </b> </p> <ul> <c:forEach items="${sp.sports}" var="sport"> <li>${sport.intitule}</li> </c:forEach> </ul> </c:otherwise> </c:choose> </c:forEach>

135

Exemple final

136

Vous aimerez peut-être aussi