Vous êtes sur la page 1sur 105

Version en ligne (../../../www.siteduzero.

com/informatique/tutoriels/programmation-en-java-api)

Tutoriel : Programmation en Java (API)


Table des matires
Programmation en Java (API) En premier : la base de donnes Une base de donnes, qusaco ? Laquelle utiliser Installation de PostgreSQL PostgreSQL Prparer sa BDD Crer la BDD Crer ses tables Se connecter sa BDD Faisons le point Connexion ! Es-tu l ? Fouiller dans sa BDD Le couple Statement - ResultSet Comment a fonctionne Entranons-nous Allons un peu plus loin Statement Les requtes prpares ResultSet 2 : le retour Aprs la lecture : l'dition Modifier des donnes Statement, toujours plus fort Grer les transactions manuellement N'avoir qu'une instance de sa connexion Pourquoi se connecter qu'une seule fois ? Le pattern singleton Le singleton dans tous ces tats TP : un testeur de requte Cahier des charges Quelques captures d'cran Correction Le pattern DAO (1/2) Avant toute chose Le pattern DAO : dfinition Premier test Le pattern DAO (2/2) Le pattern factory Fabriquer vos DAO D'une usine une multinationale

Programmation en Java (API)


Bonjour amis ZrOs.

Me revoici pour un autre big-tuto. Comme toujours, celui-ci concerne Java. Si vous ne connaissez rien ce langage, je vous invite lire ce tuto (http://www.siteduzero.com/tutoriel-3-10601-programmation-en-java.html). Par contre, si c'est un point particulier du langage, aux API standards prsentes dans le JDK que vous souhaitez vous intresser, vous tes la bonne place ! Nous allons voir ce qu'il vous faut pour utiliser des bases de donnes, comment faire de la programmation rseau... Nous nous baladerons aussi dans quelques frameworks (bote outils). Tout ceci est prsent dans le JDK, dans les API standards. Je vous propose d'en faire un tour d'horizon, le tout en partant de ZrO, bien videmment ! ;)

En premier : la base de donnes


Avant de voir comment Java utilise les bases de donnes, il nous en faut une ! Sinon, vous connaissez le proverbe : pas de bras, pas de chocolat... Nous allons donc voir quoi sert une base de donnes, mais aussi en installer une afin de pouvoir illustrer la suite de cette partie. Allez ! Zou...

Une base de donnes, qusaco ?


Lorsque vous ralisez un logiciel, un site web, ou je ne sais quoi d'autre, vous tes confronts, un moment ou un autre, une question : comment vais-je faire pour sauvegarder mes donnes ? Les bases de donnes (ou BDD) sont une alternative sre et prenne. Ce systme de stockage des donnes existe depuis trs longtemps et a fait ses preuves ! Ceux qui souhaiteraient en savoir plus sur les BDD peuvent suivre ce lien (http://fr.wikipedia.org/wiki/Base_de_donnes). Mais concrtement, comment a fonctionne ? Rsum l'extrme, il s'agit d'un systme de fichiers qui contiennent les donnes de votre application. Mais ces fichiers sont totalement transparents pour l'utilisateur d'une base de donnes, donc, totalement transparents pour VOUS ! Ces donnes sont ordonnes par "tables", c'est--dire par regroupements de plusieurs valeurs. C'est vous qui allez crer vos propres tables, en spcifiant quelles donnes vous souhaitez y intgrer. En fait, imaginez qu'une base de donnes est une gigantesque armoire tiroirs dont vous spcifiez les noms et qui contiendront une multitude de fiches dont vous spcifierez aussi leur contenu ! Je sais, un schma est toujours le bienvenu :

Dans cette base de donnes, nous avons deux tables : une qui a pour rle de stocker des personnes avec noms, prnoms et ges, et une table qui s'occupe de stocker des pays, avec leur nom et leur capitale ! Si je reprends ma comparaison de tout l'heure, la BDD symbolise l'armoire, chaque table un tiroir et chaque ligne de chaque table, une fiche de ce tiroir ! Ensuite, ce qui est formidable avec les BDD, c'est que vous pouvez les interroger en leur posant des questions via un langage. Vous pouvez leur demander des trucs comme : donne-moi la fiche de la table Personne pour le nom HERBY; donne-moi la fiche de la table Pays pour le pays France; ... Le langage qui vous permet d'interroger des bases de donnes est le langage SQL, o, en franais, "Langage de Requte Structures". Nous aurons l'occasion d'en faire un bref rappel lors du chapitre suivant... ;) Ainsi, grce aux BDD, vos donnes sont stockes, classes par vos soins et identifiables facilement sans avoir grer notre propre systme de fichiers. C'est vrai que c'est allchant, mais comment fait-on pour s'en servir ? On doit tlcharger quelque chose ? Oui, deux choses en fait : la base de donnes et ce qu'on appelle le SGBD.

Laquelle utiliser
Ben... il existe plusieurs bases de donnes et toutes sont utilises par beaucoup de dveloppeurs ! En voici une liste non exhaustive recensant les principales : PostgreSQL (http://www.postgresql.org/) MySQL (http://www.mysql.fr/) SQL Server (http://www.microsoft.com/france/serveur/sql/default.mspx) Oracle (http://www.oracle.com/) Access (http://www.microsoft.com/france/office/2007/programs/access/overview.mspx) ...

Toutes permettent de faire ce que je vous expliquais plus haut. Chacune a des spcificits : certaines sont payantes (Oracle) ; certaines sont assez laxistes avec les donnes qu'elles contiennent (MySQL) ; d'autres ont un systme de gestion trs simple utiliser (MySQL) ; ... C'est vous de faire votre choix en regardant sur le web ce que les utilisateurs en disent. Sinon, il y a un comparatif intressant, ici (http://fadace.developpez.com/sgbdcmp/). Pour le tuto sur JDBC, mon choix s'est port sur PostgreSQL. Alors continuons.

Installation de PostgreSQL
Vous pouvez tlcharger une version de PosteSQL ici. (http://wwwmaster.postgresql.org/download/mirrors-ftp?file=/binary/v8.3.0/win32/postgresql-8.3.0-1.zip) Celle-ci est pour Windows, mais pour les autres OS, vous pouvez faire un tour par-l (http://www.enterprisedb.com/products/pgdownload.do). Ensuite, je vous invite dcompresser l'archive tlcharge et excuter ce fichier :

partir de maintenant, si je ne vous spcifie pas de fentre particulire, vous pouvez laisser les rglages par dfaut. L'installation commence en vous demandant votre langue, choisissez la vtre :

On vous demandera, par la suite, de saisir un mot de passe pour l'utilisateur, comme ceci :

Et un autre pour le super-administrateur :

la fin de la pr-installation, on vous demandera si vous voulez excuter le "Stack Builder" ; ce n'est pas ncessaire, a permet juste d'installer d'autres logiciels en rapport avec PostgreSQL... Nous n'en avons pas besoin. ;)

Normalement, le serveur est install et je dirais mme qu'il en est de mme pour le SGBD ! Ah bon ? Oui, regardez dans le menu "Dmarrer" et allez dans "Tous les programmes", vous devriez avoir ceci dans l'encart "PostgreSQL 8.3" :

Il y a deux excutables qui permettent respectivement de lancer le serveur ou de l'arrter et le dernier, pgAdmin III, c'est notre SGBD ! Lancez-le, nous allons configurer notre serveur. C'est bon ? Vous tes prts ? Alors, dans le menu "Fichier", choisissez "Nouveau serveur" :

Ce qui vous amne ceci :

"Nom" correspond au nom de votre base de donnes ;

"Hte" correspond l'adresse du serveur sur le rseau ; ici, il est sur votre machine, nous mettons donc "localhost" ; vous n'avez pas besoin de toucher au port normalement, sinon la valeur du screen ; ensuite, le nom de l'utilisateur et son mot de passe que vous avez dfini. Voil, vous devriez avoir ceci devant les yeux :

Nous reviendrons sur tout ceci, mais vous pouvez lire que votre serveur, nomm "SDZ ", a une base de donnes appele "postgres" qui contient 0 table ! Simple et efficace ! Voil, nous avons install notre serveur, nous allons voir maintenant comment crer une base, des tables mais surtout faire un bref rappel sur ce fameux langage SQL... ^^ Pas de QCM pour ce chapitre, mais n'y prenez pas trop got... Tout ceci ne durera pas... :diable: Bon, rien de sorcier ici ! La plupart d'entre vous n'a peut-tre rien vu de nouveau, mais il fallait partir de ZrO... Ds le prochain chapitre, nous allons voir comment Java va "discuter" avec notre base de donnes...

PostgreSQL

Alors, maintenant, nous allons aborder la prise en main de cet outil qu'est PostgreSQL ! Dans ce chapitre, nous verrons comment crer une base de donnes, des tables, ajouter des contraintes de cls et d'intgrits... Enfin bref, tout ce dont vous allez avoir besoin pour suivre au mieux ce tutoriel. Ceci, bien sr, sans rentrer dans les dtails : c'est un tuto sur JDBC, pas sur PostgreSQL ou sur SQL ! Bon, il y a dj du taf, mine de rien...

Prparer sa BDD
Bon, vous tes connects votre BDD prfre et ce n'est pas parce que j'ai choisi PostgreSQL que vous avez d en faire autant... Cependant, celles et ceux qui n'ont pas fait le mme choix que moi peuvent aller directement vers le souschapitre sur SQL (sauf s'ils ont dj les bases, qu'ils aillent dans ce cas directement au chapitre suivant...). Dj, les bases de donnes servent stocker des informations, a, vous le savez ! :D Mais ce que vous ignorez peut-tre, c'est que, pour ranger correctement nos informations, nous allons devoir analyser celles-ci... Ce tuto n'est pas non plus un tuto sur l'analyse combine avec des diagrammes entits-associations... Dans le jargon, c'est ce dont on se sert pour crer des BDD, enfin, pour organiser les informations (tables et contenu de tables) ! Nous allons juste poser un thme et nous ferons comme si vous saviez faire tout a ! :- Pour ceux que la ralisation de modles entits-associations intressent, vous pouvez faire un tour ici (http://isi.developpez.com/DeUMLaSQL/). Voil : pour notre base de donnes, nous allons grer une cole, dont voici les caractristiques : cette cole est compose de classes ; chaque classe est compose d'lves ; chaque classe un professeur de chaque matire dispense par cette cole ; un professeur peut enseigner plusieurs matires et exercer ses fonctions sur plusieurs classes. Voil le point ZRO de toute base de donnes ! Vous vous rendez compte qu'il y a beaucoup d'informations grer. Bon, en thorie, nous devrions faire un dictionnaire des donnes, voir qui appartient quelle donne, poursuivre avec une modlisation faon MCD (Modle Conceptuel de Donnes) et simplifier le tout suivant certaines rgles pour terminer avec un MPD (Modle Physique de Donnes). Nous allons raccourcir le processus et je vais fournir un modle tout fait, que je vais tout de mme vous expliquer... :-

Tous ces beaux lments seront nos futures tables. De plus, les attributs dans celles-ci se nomment des "champs". Vous pouvez voir que tous les acteurs mentionns se trouvent symboliss dans ce schma (classe, professeur, lve...). Vous constaterez que ces acteurs ont un attribut nomm 'id', ceci correspond son identifiant : c'est un champ de type entier qui s'incrmentera pour chaque nouvelle entre, c'est aussi grce ce champ que nous crons des liens entre nos acteurs. Oui... Vous avez remarqu que j'avais colori des tables en bleu. ^^ Ces tables ont toutes un champ qui a une spcificit : un champ dont le nom se termine par '_k'. D'abord, vous devez savoir que la flche signifie 'a un', de ce fait, un lve 'a une' classe ! Bon, on te suit, mais pourquoi les autres tables ont deux champs comme a ? C'est simple, c'est parce que je vous ai dit qu'un professeur pouvait exercer plusieurs matires : dans ce cas, nous avons besoin de ce qu'on appelle une table de jointure. Ainsi, nous pouvons dire que tel professeur exerce telle ou telle matire et qu'une association prof-matire est assigne une classe ! ;) La donne que nous utiliserons pour lier des tables n'est autre que l'identifiant : id. De plus - difficile de ne pas avoir vu a - chaque champ un type (entier, double, date, boolean...). Nous avons tout ce dont nous avons besoin pour construire notre BDD !

Crer la BDD
Pour cette opration, rien de plus simple ! :D pgAdmin met votre disposition un outil qui facilite la cration de BDD et de tables (crer ses BDD et ses tables la mano, avec SQL, c'est un peu fastidieux...). Pour crer une nouvelle base de donnes, il vous suffit de faire un clic droit sur "Base de donnes" :

Vous devriez arriver sur cette pop-up :

Renseignez le nom de la base de donnes et choisissez l'encodage UTF-8. Cet encodage correspond un jeu de caractres tendu qui autorise les caractres spciaux ! Une fois ceci fait, vous devriez avoir quelque chose comme a :

Vous pouvez voir votre nouvelle base de donnes ainsi que le script SQL permettant de crer cette base. Il ne nous reste plus qu' crer les tables avec le bon type de donnes... Mme procdure que pour la squence, un clic droit sur le noeud "table" cette fois, comme ceci :

Crer ses tables


Nous allons maintenant nous attaquer la cration de nos tables afin de pouvoir travailler... Je vais vous montrer comment faire une table simple, histoire de... Et, pour les plus fainants, je vous fournirai le script SQL qui finira la cration des tables. ;) Nous commencerons par la table "classe", vu que c'est l'une des tables qui n'a besoin d'aucun lien vers une autre table... ;) Comme dit plus haut, il vous suffit de faire un clic droit sur "Table" Ensuite, PostgreSQL vous demande des informations sur votre future table : son nom ; le nom de ses champs ; le type de ses champs ; ... Ici, vous voyez le moment o vous devez renseigner le nom de votre table.

Ensuite, vous ajouterez des champs (j'ai ajout des prfixes mes champs pour ne pas avoir trop d'ambigut dans mes requtes SQL) :

Le champ "cls_id" est de type "serial" afin que celui-ci utilise une squence. Nous lui ajouterons en plus une contrainte de cl primaire. Ce champ est un "character varying" de taille 64 : ce champ pourra donc contenir 64 caractres. Nous mettons maintenant la contrainte de cl primaire sur notre identifieur :

Vous avez vu comment on cre une table avec PostgreSQL, mais je ne vais pas vous demander de faire a pour chacune d'entre elles. :- Je ne suis pas vache ce point... Nous devons voir comment on utilise les BDD avec Java, pas avec le SGBD... Cliquez sur "Ajouter".

Choisissez la colonne "cls_id" et cliquez sur "Ajouter". Validez le tout. Maintenant le deuxime champ :

Voici le code SQL de cette cration de table :

Je ne vais pas vous faire crer toutes les tables de cette manire... Le tuto est cens vous apprendre utiliser les BDD avec Java... Voici donc un fichier contenant le script SQL (medias/www.siteduzero.com_uploads_fr_ftp_cysboy_api_backEcole.zip) de cration des tables restantes ainsi que leurs contenus. Sympa, le gars. ^^ Le dit fichier est dans une archive, pensez la dcompresser avant... :- Il ne vous reste plus qu' ouvrir le fichier avec PostgreSQL en allant dans l'diteur de requtes SQL :

Vous pouvez prsent ouvrir le fichier que je vous ai fourni en faisant "Fichier / Ouvrir" et choisir le fichier .sql

Maintenant, excutez la requte en cliquant sur ce bouton (vous pouvez aussi appuyer sur F5) :

Fermez l'diteur de requte. Vous avez toute la base cre et, en plus, il y a des donnes. :magicien:

Je vous retrouve donc au prochain chapitre afin de commencer notre aventure. Voil, les bases sont poses ! Nous allons pouvoir attaquer svre dans JDBC... Let's go les ZrOs ! :pirate:

Se connecter sa BDD
Nous avons pris le temps de modliser et de crer notre base de donnes. Il est grand temps de prendre le taureau par les cornes et de voir comment accder tout ceci dans un programme Java. Inutile de prciser que savoir programmer en objets est plus que requis et que, mis part ce point, tout sera pris partir de ZrO. ;) En avant !

Faisons le point
Bon : vous avez utilis pgAdmin jusqu' maintenant. Le truc, c'est qu'il se passe des choses caches, peu avouables voire carrment obscnes entre pgAdmin et PostgreSQL. Non, je plaisante... mais il se passe effectivement des choses entre ces deux-l ! ^^ Le fait est que vous ne devriez plus faire l'amalgame entre BDD et SGBD ; par contre, vous devez encore ignorer que le SGBD effectue une connexion avec la BDD afin de pouvoir communiquer. Ceci pourrait se schmatiser par un dialogue du genre :

Les ZrOs qui ont dj install une imprimante savent que leur machine besoin d'un driver pour que la communication puisse se faire entre les deux acteurs ! Ici, c'est la mme chose ! :waw: pgAdmin utilise un driver pour se connecter la base de donnes. Vu que les personnes qui ont dvelopp

les deux soft travaillent main dans la main, pas de souci de communication mais qu'en sera-t-il avec Java ? En fait, avec Java, vous allez avoir besoin de ces drivers, mais pas sous n'importe quelle forme ! Afin de pouvoir vous connecter une base de donnes avec Java, il vous faut un fichier .jar qui correspond au fameux pilote. Il existe donc un fichier .jar qui permet de se connecter une base PostgreSQL ! Est-ce que a veut dire qu'il y a un fichier .jar par BDD ? Tout fait, il existe un fichier .jar pour se connecter : MySQL ; SQL Server ; Oracle ; ... Et si vous ne faites pas ceci, vous ne pourrez pas vous connecter ! Un bmol toutefois : vous pouvez aussi vous connecter une BDD en utilisant les pilotes ODBC prsents dans Windows, mais ceci ncessite d'installer les pilotes dans Windows et de les paramtrer dans les sources de donnes ODBC pour, par la suite, utiliser ces pilotes ODBC pour se connecter la BDD dans un programme Java ! Je ne parlerai pas de cette mthode puisqu'elle ne fonctionne que pour Windows ! Mais bon, pour ceux que le sujet intresse, allez voir par l ! (http://java.sun.com/j2se/1.3/docs/guide/jdbc/getstart/bridge.doc.html) D'accord, on voit bien le principe ! Mais alors... o trouve-t-on ce pilote pour Java ? Une simple recherche sur Google (http://www.google.fr/) comblera vos attentes avec une recherche du genre :

... pour PostgreSQL, ou :

pour MySQL... Enfin bref, il est assez facile de trouver les pilotes JDBC convoits. Sur la page de tlchargement des pilotes pour PostgreSQL, il y a la dernire version disponible ; j'ai pris la version JDBC4 :

La version JDBC4 offre des nouveauts et une souplesse dans l'utilisation de JDBC, mais j'avoue, je ne les connais pas trop... Vous trouverez un rapide aperu par ici ! (http://www.techfaq360.com/tutorial/jdbc/jdbc3_jdbc4.jsp)

Bon ! Tlchargez le fichier .jar, pour ceux qui auraient la flemme de faire une recherche sur Google, c'est par ici (http://jdbc.postgresql.org/download.html) ; et maintenant, que faire de cette archive ? Et comment on l'utilise ? Pour l'utilisation, nous y arrivons grand pas, mais une question se pose encore : o mettre l'archive ? Vous avez deux solutions : la mettre dans votre projet et l'inclure au CLASSPATH ; mettre l'archive de le dossier d'installation du JRE, dans le dossier "lib/ext". Le tout est de savoir si votre application est voue tre exporte sur diffrents postes, auquel cas l'approche CLASSPATH est encore la plus judicieuse (sinon, il faudra ajouter l'archive dans tous les JRE...) mais, nous, nous allons utiliser la deuxime mthode afin de ne pas surcharger nos projets ! Je vous laisse donc mettre l'archive tlcharge dans le dossier sus-mentionn. :)

Connexion ! Es-tu l ?
La base de donnes est prte, les tables sont cres et remplies et nous avons le driver ! Il ne nous reste plus qu' nous connecter, ENFIN ! C'est vrai que tu auras mis le temps... Eh, il faut ce qu'il faut ! Et encore, j'aurais pu vous faire rviser le SQL avant d'attaquer ! :diable: Je vous autorise crer un nouveau projet dans Eclipse avec une classe contenant une mthode p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ) . Voici le code source pour obtenir une connexion :

i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . D r i v e r M a n a g e r ; i m p o r tj a v a . u t i l . E n u m e r a t i o n ; i m p o r tj a v a . u t i l . P r o p e r t i e s ; p u b l i cc l a s sC o n n e c t{ p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ){ t r y{ C l a s s . f o r N a m e ( " o r g . p o s t g r e s q l . D r i v e r " ) ; S y s t e m . o u t . p r i n t l n ( " D R I V E RO K!" ) ; S t r i n gu r l=" j d b c : p o s t g r e s q l : / / l o c a l h o s t : 5 4 3 2 / E c o l e " ; S t r i n gu s e r=" p o s t g r e s " ; S t r i n gp a s s w d=" p o s t g r e s " ; C o n n e c t i o nc o n n=D r i v e r M a n a g e r . g e t C o n n e c t i o n ( u r l ,u s e r ,p a s s w d ) ; S y s t e m . o u t . p r i n t l n ( " C o n n e c t i o ne f f e c t i v e! " ) ; }c a t c h( E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } } }

Tout a pour avoir une connexion ? Oui. :- Nous allons dtailler un peu tout ceci... Dans un premier temps, nous avons cr une instance de l'objet Driver prsent dans le fichier .jar que nous avons tlcharg tout l'heure. Il est inutile de crer une vritable instance de ce type d'objet ; par-l, j'entends que faire ceci :
o r g . p o s t g r e s . D r i v e rd r i v e r=n e wo r g . p o s t g r e s . D r i v e r ( ) ;

n'est pas ncessaire. Du coup, nous utilisons la rflexivit (http://www.siteduzero.com/tutoriel-3-10431java-et-la-reflexivite.html) afin d'instancier cet objet. ce stade, il y a comme un pont entre votre programme Java et votre BDD, mais el trafique routier n'y est pas encore autoris ! Il faut qu'une connexion soit effective afin que votre programme et la BDD puissent communiquer. Ceci se fait avec l'autre ligne de code : C o n n e c t i o nc o n n=D r i v e r M a n a g e r . g e t C o n n e c t i o n ( u r l ,u s e r ,p a s s w d ) ; . Nous avons au pralable dfini trois String contenant respectivement : l'URL de connexion ; le nom de l'utilisateur ; le mot de passe utilisateur.

L'URL de quoi ? De connexion. Elle est indispensable Java pour se connecter n'importe quelle BDD. Cette URL se dcompose comme suit :

En vert, vous pouvez voir le dbut de l'URL de connexion. elle commence TOUJOURS par "jdbc:". Dans notre cas, nous utilisons PostgreSQL, la dnomination "postgresql:" suit le dbut de l'URL. Si vous utilisez une source de donnes ODBC, il faudrait avoir "jdbc:odbc:". En fait, ceci dpend du pilote JDBC : cela permet Java de savoir quel pilote utiliser ! On parle de protocole utilis. En bleu, vous trouverez la localisation de la machine physique sur le rseau ; ici, nous sommes en local, nous utilisons donc "//localhost:5432". Ah oui, le nom de la machine physique est suivi du numro de port utilis. ^^ En orange, pour ceux qui ne l'auraient pas devin, il s'agit du nom de notre base de donnes ! ;) Les informations en bleu et en orange dpendent du pilote JDBC utilis. Pour en savoir plus, consultez la documentation de celui-ci ! :) L'URL, le nom d'utilisateur, le mot de passe et le driver permettent ensemble de crer le pont de connexion et le trafic routier sur ce pont ! Donc, si vous excutez ce code, vous aurez :

Vous n'tes obligs de spcifier la totalit des informations pour l'URL... Mais il faudra au moins "jdbc:postgresql". Tout ceci lve une Exception en cas de problme ! L'avantage avec les fichiers .jar comme drivers de connexion, c'est que vous n'tes pas tenus d'initialiser le driver par rflexivit ou autre. Tout se passe en Java ! Vu qu'il y a un rappel du protocole utiliser dans l'URL de connexion, tout est parfait et Java s'en sort tout seul ! Ne vous tonnez pas si vous ne voyez plus C l a s s . f o r N a m e ( " o r g . p o s t g r e s q l . D r i v e r " ) ; par la suite... Bon, on arrive se connecter. Maintenant, avant de poursuivre, un QCM vous attend ! :pirate: Chapitre trs simple, n'est-ce pas ? Vous savez maintenant tablir une connexion avec une BDD. Nous allons maintenant voir comment faire joujou avec tout ceci !

Fouiller dans sa BDD


Nous continuons notre voyage initiatique au pays de JDBC en abordant la manire d'interroger notre BDD. Eh oui, une base de donnes n'est utile que si nous pouvons consulter, ajouter, modifier ou encore supprimer les donnes qu'elle comprend. Par contre, pour faire ceci, il tait IMPRATIF de se connecter. Mais vu que c'est chose faite, nous allons voir comment fouiner dans notre BDD.

Le couple Statement - ResultSet


Voici deux objets que vous utiliserez srement beaucoup ! En fait, ce sont ces deux objets qui permettent de rcuprer des donnes de la BDD ou de travailler avec celles-ci... :- Afin de vous faire comprendre tout ceci de faon simple, voici un exemple assez complet (mais pas trop quand mme) affichant le contenu de la table classe :
i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . D r i v e r M a n a g e r ; i m p o r tj a v a . s q l . R e s u l t S e t ; i m p o r tj a v a . s q l . R e s u l t S e t M e t a D a t a ; i m p o r tj a v a . s q l . S t a t e m e n t ; p u b l i cc l a s sC o n n e c t{ p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ){ t r y{ C l a s s . f o r N a m e ( " o r g . p o s t g r e s q l . D r i v e r " ) ; S t r i n gu r l=" j d b c : p o s t g r e s q l : / / l o c a l h o s t : 5 4 3 2 / E c o l e " ; S t r i n gu s e r=" p o s t g r e s " ; S t r i n gp a s s w d=" p o s t g r e s " ; C o n n e c t i o nc o n n=D r i v e r M a n a g e r . g e t C o n n e c t i o n ( u r l ,u s e r ,p a s s w d ) ; / / C r a t i o nd ' u no b j e tS t a t e m e n t S t a t e m e n ts t a t e=c o n n . c r e a t e S t a t e m e n t ( ) ; / / L ' o b j e tR e s u l t S e tc o n t i e n tl er s u l t a td el ar e q u t eS Q L R e s u l t S e tr e s u l t=s t a t e . e x e c u t e Q u e r y ( " S E L E C T*F R O Mc l a s s e " ) ; / / O nr c u p r el e sM e t a D a t a R e s u l t S e t M e t a D a t ar e s u l t M e t a=r e s u l t . g e t M e t a D a t a ( ) ; S y s t e m . o u t . p r i n t l n ( " \ n * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * " ) ; / / O na f f i c h el en o md e sc o l o n n e s f o r ( i n ti=1 ;i< = r e s u l t M e t a . g e t C o l u m n C o u n t ( ) ;i + + ) S y s t e m . o u t . p r i n t ( " \ t "+r e s u l t M e t a . g e t C o l u m n N a m e ( i ) . t o U p p e r C a s e ( )+" \ t* " ) ;

S y s t e m . o u t . p r i n t l n ( " \ n * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * " ) ; w h i l e ( r e s u l t . n e x t ( ) ) { f o r ( i n ti=1 ;i< = r e s u l t M e t a . g e t C o l u m n C o u n t ( ) ;i + + ) S y s t e m . o u t . p r i n t ( " \ t "+r e s u l t . g e t O b j e c t ( i ) . t o S t r i n g ( )+" \ t| " ) ; S y s t e m . o u t . p r i n t l n ( " \ n " ) ; }

r e s u l t . c l o s e ( ) ; s t a t e . c l o s e ( ) ;

}c a t c h( E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } } }

Voici ce que nous donne ce code :

Vous avez srement compris que j'ai simplement excut une requte SQL et rcupr les lignes trouves ! Mais dtaillons un peu plus ce qu'il s'est pass. ^^ Dj, vous aurez pu remarquer que j'ai spcifi l'URL complte pour la connexion : sinon comment voulez-vous savoir quelle BDD attaquer ?... La connexion la BDD mise part, les choses se sont passes en quatre tapes distinctes : cration de l'objet Statement ; excution de la rqute SQL ; rcupration et affichage des donnes via l'objet ResultSet ; fermeture des objets utiliss (bien que non obligatoire, c'est recommand). Tout a semble clair, mais tu ne pourrais pas nous en dire un peu plus sur ces objets ? Mais c'est ce que j'allais faire... ^^ Dtes-vous une chose : objet Statement => instruction SQL ! C'est cet objet qui excute les requtes SQL et qui retourne les rsultats. Ensuite, lorsque vous entendez ResultSet, c'est que votre requte SQL a retourn un certain nombre de lignes rcuprer et afficher...

Comment a fonctionne

Je vous ai fourni un morceau de code, il fonctionne, mais comment a marche ? Voici le moment o tout vous sera dvoil. Comme je vous le disais plus haut, l'objet Statement est l'objet qui vous permet de faire des requtes SQL. Celles-ci peuvent tre de type : CREATE ; INSERT ; UPDATE ; SELECT ; DELETE . Vous n'tes pas sans savoir que, selon le type de requte excute, celle-ci retourne un / des rsultat(s), dans le cas d'un SELECT, ou une validation / un message d'erreur dans les autres cas. L'objet Statement vous est fourni par l'objet Connection grce l'instruction c o n n . c r e a t e S t a t e m e n t ( ) ; . Nous verrons, dans le chapitre suivant, un peu plus de choses concernant l'objet Statement. Ce que j'ai fait ensuite, c'est demander mon objet Statement d'excuter une requte SQL de type SELECT. Vous la voyez, celle-ci :
S E L E C T*F R O Mc l a s s e

Cette requte me retournant un rsultat contenant beaucoup de lignes, elles-mmes contenant plusieurs colonnes, nous avons stock ce rsultat dans un objet ResultSet, objet permettant de faire diverses actions sur des rsultats de requtes SQL ! :) Aprs cette ligne de code : R e s u l t S e tr e s u l t=s t a t e . e x e c u t e Q u e r y ( " S E L E C T*F R O Mc l a s s e " ) ; , les rsultats sont stocks dans l'objet ResultSet et nous n'avons plus qu' afficher les donnes. Ici, j'ai utilis un objet de type ResulSetMetaData afin de rcuprer les "meta data" de ma requte. Comprenez ceci comme "rcuprer les informations globales de ma requte". Ici, nous avons utilis cet objet afin de rcuprer le nombre de colonnes renvoy par la requte SQL ainsi que leurs noms. Cet objet "meta data" permettent de rcuprer des informations trs utiles comme : le nombre de colonnes d'un rsultat ; le nom des colonnes d'un rsultat ; le type de donnes stock dans chaque colonne ; le nom de la table qui appartient la colonne (dans le cas d'une jointure de table) ; ... Vous voyez que ces informations peuvent tre utiles. Il existe aussi un objet DatabaseMetaData qui, lui, fournit des informations sur la base de donnes ! Vous comprenez mieux ce que signifie cette portion de code :

S y s t e m . o u t . p r i n t l n ( " \ n * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * " ) ; / / O na f f i c h el en o md e sc o l o n n e s f o r ( i n ti=1 ;i< = r e s u l t M e t a . g e t C o l u m n C o u n t ( ) ;i + + ) S y s t e m . o u t . p r i n t ( " \ t "+r e s u l t M e t a . g e t C o l u m n N a m e ( i ) . t o U p p e r C a s e ( )+" \ t* " ) ; S y s t e m . o u t . p r i n t l n ( " \ n * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * " ) ;

Nous nous servons de la mthode nous donnant le nombre de colonnes dans le rsultat afin de rcuprer le nom de la colonne grce son index ! ATTENTION : contrairement aux indices de tableaux, les indices de colonnes SQL commencent 1 ! Ensuite, nous rcuprons les donnes de notre requte en nous servant de l'indice des colonnes :
w h i l e ( r e s u l t . n e x t ( ) ) { f o r ( i n ti=1 ;i< = r e s u l t M e t a . g e t C o l u m n C o u n t ( ) ;i + + ) S y s t e m . o u t . p r i n t ( " \ t "+r e s u l t . g e t O b j e c t ( i ) . t o S t r i n g ( )+" \ t| " ) ; S y s t e m . o u t . p r i n t l n ( " \ n " ) ; }

Nous utilisons une premire boucle afin que, tant que notre objet ResultSet nous retourne des lignes de rsultats, nous parcourions ensuite chaque ligne via notre boucle f o r . La mthode n e x t ( ) permet de positionner l'objet sur la ligne suivante dans sa liste de rsultat ! Au premier tour de boucle, cette mthode positionne l'objet sur la premire ligne. Si vous ne positionnez pas l'objet rsultat et que vous tentez de lire des donnes, une exception sera leve ! Je suis parti du postulat que ne connaissons pas le type de donnes de nos colonnes, mais vu que nous les connaissons, ce code aurait tout aussi bien fonctionn :
w h i l e ( r e s u l t . n e x t ( ) ) { S y s t e m . o u t . p r i n t ( " \ t "+r e s u l t . g e t I n t ( " c l s _ i d " )+" \ t| " ) ; S y s t e m . o u t . p r i n t ( " \ t "+r e s u l t . g e t S t r i n g ( " c l s _ n o m " )+" \ t| " ) ; S y s t e m . o u t . p r i n t l n ( " \ n " ) ; }

On a le droit de faire a ? Tout fait ! Nous connaissons le nom de nos colonnes retournes par la requte SQL, nous connaissons aussi leurs types, il nous suffit donc d'invoquer la mthode adquat de l'objet ResultSet en utilisant le nom de la colonne rcuprer ! Par contre, si vous essayez de rcuprer le contenu de la colonne "cls_nom" avec la mthode g e t I n t ( " c l s _ n o m " ) , vous aurez une zolie exception ! Il existe une mthode g e t X X X ( ) par type primitif et quelques autres correspondant aux types SQL :

g e t A r r a y ( i n tc o l u m m n I n d e x ) ; g e t A s c i i ( i n tc o l u m m n I n d e x ) ; g e t B i g D e c i m a l ( i n tc o l u m m n I n d e x ) ; g e t B i n a r y ( i n tc o l u m m n I n d e x ) ; g e t B l o b ( i n tc o l u m m n I n d e x ) ; g e t B o o l e a n ( i n tc o l u m m n I n d e x ) ; g e t B y t e s ( i n tc o l u m m n I n d e x ) ; g e t C h a r a c t e r ( i n tc o l u m m n I n d e x ) ; g e t D a t e ( i n tc o l u m m n I n d e x ) ; g e t D o u b l e ( i n tc o l u m m n I n d e x ) ; g e t F l o a t ( i n tc o l u m m n I n d e x ) ; g e t I n t ( i n tc o l u m m n I n d e x ) ; g e t L o n g ( i n tc o l u m m n I n d e x ) ; g e t O b j e c t ( i n tc o l u m m n I n d e x ) ; g e t S t r i n g ( i n tc o l u m m n I n d e x ) ;

Et, la fin, nous fermons nos objets :


r e s u l t . c l o s e ( ) ; s t a t e . c l o s e ( ) ;

Avant de voir plus en dtail les possibilits qu'offrent ces objets, nous allons faire deux-trois requtes SQL afin de nous habituer la faon dont tout a fonctionne ! ;)

Entranons-nous
Le but du jeu est de me coder les rsultats que j'ai obtenus... Je vous laisse chercher dans quelle table... :p Vous tes prts ? C'est parti ! :ninja: Voici ce que vous devez me rcuprer en premier :

Cherchez bien... Bon, vous avez trouv ! Il n'y avait rien de compliqu ici, voici la correction, enfin, une suggestion de correction :
p a c k a g ec o m . s d z . e x o ; i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . D r i v e r M a n a g e r ; i m p o r tj a v a . s q l . R e s u l t S e t ; i m p o r tj a v a . s q l . R e s u l t S e t M e t a D a t a ; i m p o r tj a v a . s q l . S t a t e m e n t ; p u b l i cc l a s sE x o 1{ p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ){ t r y{ C l a s s . f o r N a m e ( " o r g . p o s t g r e s q l . D r i v e r " ) ; S t r i n gu r l=" j d b c : p o s t g r e s q l : / / l o c a l h o s t : 5 4 3 2 / E c o l e " ; S t r i n gu s e r=" p o s t g r e s " ; S t r i n gp a s s w d=" p o s t g r e s " ; C o n n e c t i o nc o n n=D r i v e r M a n a g e r . g e t C o n n e c t i o n ( u r l ,u s e r ,p a s s w d ) ; S t a t e m e n ts t a t e=c o n n . c r e a t e S t a t e m e n t ( ) ; R e s u l t S e tr e s u l t=s t a t e . e x e c u t e Q u e r y ( " S E L E C T*F R O Mp r o f e s s e u r "

) ; R e s u l t S e t M e t a D a t ar e s u l t M e t a=r e s u l t . g e t M e t a D a t a ( ) ; S y s t e m . o u t . p r i n t l n ( " -I lya"+r e s u l t M e t a . g e t C o l u m n C o u n t ( )+" c o l o n n e sd a n sc e t t et a b l e " ) ; f o r ( i n ti=1 ;i< =r e s u l t M e t a . g e t C o l u m n C o u n t ( ) ;i + + ) S y s t e m . o u t . p r i n t l n ( " \ t* "+r e s u l t M e t a . g e t C o l u m n N a m e ( i ) ) ;

S y s t e m . o u t . p r i n t l n ( " V o i c il e sn o m se tp r n o m s:" ) ; S y s t e m . o u t . p r i n t l n ( " \ n " ) ; w h i l e ( r e s u l t . n e x t ( ) ) { S y s t e m . o u t . p r i n t ( " \ t "+r e s u l t . g e t S t r i n g ( " p r o f _ n o m " )+" \ t| " ) ; S y s t e m . o u t . p r i n t ( " \ t "+r e s u l t . g e t S t r i n g ( " p r o f _ p r e n o m " ) +" \ t| " ) ; S y s t e m . o u t . p r i n t l n ( " \ n " ) ; } r e s u l t . c l o s e ( ) ; s t a t e . c l o s e ( ) ; }c a t c h( E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } } }

Allez, on complique la tche :

Hou... Ne vous faites pas exploser la cervelle tout de suite... On ne fait que commencer... :p Voici une possible solution ce rsultat :
p a c k a g ec o m . s d z . e x o ; i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . D r i v e r M a n a g e r ; i m p o r tj a v a . s q l . R e s u l t S e t ; i m p o r tj a v a . s q l . R e s u l t S e t M e t a D a t a ; i m p o r tj a v a . s q l . S t a t e m e n t ; p u b l i cc l a s sE x o 2{ p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ){ t r y{ C l a s s . f o r N a m e ( " o r g . p o s t g r e s q l . D r i v e r " ) ; S t r i n gu r l=" j d b c : p o s t g r e s q l : / / l o c a l h o s t : 5 4 3 2 / E c o l e " ; S t r i n gu s e r=" p o s t g r e s " ; S t r i n gp a s s w d=" p o s t g r e s " ; C o n n e c t i o nc o n n=D r i v e r M a n a g e r . g e t C o n n e c t i o n ( u r l ,u s e r ,p a s s w d ) ; S t a t e m e n ts t a t e=c o n n . c r e a t e S t a t e m e n t ( ) ; S t r i n gq u e r y=" S E L E C Tp r o f _ n o m ,p r o f _ p r e n o m ,m a t _ n o mF R O Mp r o f e s s e u r " ; q u e r y+ ="I N N E RJ O I Nj _ m a t _ p r o fO Nj m p _ p r o f _ k=p r o f _ i d " ; q u e r y+ ="I N N E RJ O I Nm a t i e r eO Nj m p _ m a t _ k=m a t _ i dO R D E RB Yp r o f _ n o m " ;

R e s u l t S e tr e s u l t=s t a t e . e x e c u t e Q u e r y ( q u e r y ) ; S t r i n gn o m=" " ; w h i l e ( r e s u l t . n e x t ( ) ) { i f ( ! n o m . e q u a l s ( r e s u l t . g e t S t r i n g ( " p r o f _ n o m " ) ) ) { n o m=r e s u l t . g e t S t r i n g ( " p r o f _ n o m " ) ; S y s t e m . o u t . p r i n t l n ( n o m+""+r e s u l t . g e t S t r i n g ( " p r o f _ p r e n o m " )+"e n s e i g n e:" ) ; } S y s t e m . o u t . p r i n t l n ( " \ t \ t \ t-"+ r e s u l t . g e t S t r i n g ( " m a t _ n o m " ) ) ; } r e s u l t . c l o s e ( ) ; s t a t e . c l o s e ( ) ; }c a t c h( E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } } }

Et le dernier pour la fin :

p a c k a g ec o m . s d z . e x o ;

i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . D r i v e r M a n a g e r ; i m p o r tj a v a . s q l . R e s u l t S e t ; i m p o r tj a v a . s q l . S t a t e m e n t ; p u b l i cc l a s sE x o 3{ p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ){ t r y{ C l a s s . f o r N a m e ( " o r g . p o s t g r e s q l . D r i v e r " ) ; S t r i n gu r l=" j d b c : p o s t g r e s q l : / / l o c a l h o s t : 5 4 3 2 / E c o l e " ; S t r i n gu s e r=" p o s t g r e s " ; S t r i n gp a s s w d=" p o s t g r e s " ; C o n n e c t i o nc o n n=D r i v e r M a n a g e r . g e t C o n n e c t i o n ( u r l ,u s e r ,p a s s w d ) ; S t a t e m e n ts t a t e=c o n n . c r e a t e S t a t e m e n t ( ) ; S t r i n gq u e r y=" S E L E C Tp r o f _ n o m ,p r o f _ p r e n o m ,m a t _ n o m ,c l s _ n o mF R O Mp r o f e s s e u r " ; q u e r y+ ="I N N E RJ O I Nj _ m a t _ p r o fO Nj m p _ p r o f _ k=p r o f _ i d " ; q u e r y+ ="I N N E RJ O I Nm a t i e r eO Nj m p _ m a t _ k=m a t _ i d " ; q u e r y+ ="I N N E RJ O I Nj _ c l s _ j m pO Nj c m _ j m p _ k=j m p _ i d " ; q u e r y+ ="I N N E RJ O I Nc l a s s eO Nj c m _ c l s _ k=c l s _ i dA N Dc l s _ i dI N ( 1 ,7 )" ; q u e r y+ ="O R D E RB Yc l s _ n o mD E S C ,p r o f _ n o m " ; R e s u l t S e tr e s u l t=s t a t e . e x e c u t e Q u e r y ( q u e r y ) ; S t r i n gn o m=" " ; S t r i n gn o m C l a s s=" " ; w h i l e ( r e s u l t . n e x t ( ) ) { i f ( ! n o m C l a s s . e q u a l s ( r e s u l t . g e t S t r i n g ( " c l s _ n o m " ) ) ) { n o m C l a s s=r e s u l t . g e t S t r i n g ( " c l s _ n o m " ) ; S y s t e m . o u t . p r i n t l n ( " C l a s s ed e"+n o m C l a s s+": " ) ; } i f ( ! n o m . e q u a l s ( r e s u l t . g e t S t r i n g ( " p r o f _ n o m " ) ) ) { n o m=r e s u l t . g e t S t r i n g ( " p r o f _ n o m " ) ; S y s t e m . o u t . p r i n t l n ( " \ t*"+n o m+""+r e s u l t . g e t S t r i n g ( " p r o f _ p r e n o m " )+"e n s e i g n e:" ) ; } S y s t e m . o u t . p r i n t l n ( " \ t \ t \ t-"+ r e s u l t . g e t S t r i n g ( " m a t _ n o m " ) ) ; } r e s u l t . c l o s e ( ) ;

s t a t e . c l o s e ( ) ; }c a t c h( E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } } }

Voil : maintenant que vous vous tes bien entrans, nous allons approfondir un peu tout ceci... Mais avant, le QCM des familles. :diable: C'est un chapitre riche mais pas trop compliqu... Prenez le temps de voir comment le tout s'articule autour des Resultset et tutti quanti. Les plus tmraires me retrouveront au prochain chapitre. :)

Allons un peu plus loin


Nous avons vu comment faire des requtes SQL, les excuter et les afficher. Le moment est venu de creuser un peu la question en allant un peu plus en profondeur... Nous allons revenir sur les objets Statement et ResultSet en dtaillant un peu le tout ! :)

Statement
Vous avez vu comment obtenir un objet Statement ; par contre, ce que vous ignorez, c'est que je ne vous ai pas tout dit... :- Je sais, je suis un vilain cysboy... Vous savez dj que, pour rcuprer un objet Statement, vous devez le demander gentiment un objet Connection, ceci en invoquant la mthode c r e a t e S t a t e m e n t ( ) . Je ne vous apprends rien, l ! Du moins j'espre... :D Par contre, ce que vous ne savez pas, c'est que vous pouvez spcifier des paramtres pour la cration de l'objet Statement... Ces paramtres permettent diffrentes actions lors du parcours des rsultats via l'objet ResultSet. Paramtres pour la lecture du jeu d'enregistrements : TYPE_FORWARD_ONLY : le rsultat n'est consultable qu'en avant. IMPOSSIBLE de revenir en arrire lors de la lecture ; TYPE_SCROLL_SENSITIVE : le parcours peut se faire en avant ou en arrire, le curseur peut se positionner n'importe o mais si des changements sont faits dans la base pendant la lecture, ces changements ne seront pas visibles ; TYPE_SCROLL_INSENSITIVE : comme le prcdent sauf que les changements sont directement visibles lors du parcours des rsultats. Paramtres concernant la possibilit de mise jour du jeu d'enregistrements : CONCUR_READONLY : les donnes sont consultables en lecture seule. Pas de mise jour des valeurs pour mettre la base jour ; CONCUR_UPDATABLE : les donnes sont modifiables et, lors d'une modification, la base est mise jour.

Par dfaut, les ResultSet issus d'un Statement sont TYPE_FORWARD_ONLY pour le type de parcours et CONCUR_READONLY pour les actions possibles. Ces paramtres sont des variables statiques de la classe ResultSet, vous savez donc comment les utiliser... ;) Voici comment crer un Statement permettant l'objet rsultat de pouvoir tre lu d'avant en arrire avec possibilit de modification :
S t a t e m e n ts t a t e=c o n n . c r e a t e S t a t e m e n t ( R e s u l t S e t . T Y P E _ S C R O L L _ I N S E N S I T I V E ,R e s u l t S e t . C O N C U R _ U P D A T A B L E ) ;

Facile... ^^ Vous avez appris crer des Statement avec des paramtres, mais saviez-vous qu'il existe un autre type de Statement ? Nous verrons comment utiliser les fonctionnalits des ResultSet juste aprs ce point...

Les requtes prpares


Il va falloir vous accrocher un tout petit peu... De tels objets sont crs exactement de la mme faon que des Statement classiques, sauf qu'au lieu d'avoir :
S t a t e m e n ts t m=c o n n . c r e a t e S t a t e m e n t ( ) ;

nous avons :
P r e p a r e d S t a t e m e n ts t m=c o n n . p r e p a r e S t a t e m e n t ( " S E L E C T*F R O Mc l a s s e " ) ;

Jusqu'ici, rien de particulier ! Cependant, une diffrence est dj effective ce stade : la requte SQL est pr-compile ! Ceci a pour effet que celle-ci s'excutera plus vite dans le moteur SQL de la BDD, c'est sr puisqu'il n'aura pas la compiler... :- En fait, en rgle gnrale, on utilise ce genre d'objet pour des requtes ayant beaucoup de paramtres ou des requtes pouvant tre excutes plusieurs fois... C'est tout ce qu'il y a comme diffrence ? Non, bien sr. Je vous ai dit dans le titre que nous allons prparer des requtes !. Il y a une diffrence de taille entre l'objet PreparedStatement et l'objet Statement : dans le premier, on peut utiliser des paramtres trous ! Quoi ? o_O Je me doutais que vous auriez du mal comprendre... En fait, vous pouvez insrer un caractre spcial dans vos requtes et remplacer ce caractre grce des mthodes de l'objet PreparedStatement en spcifiant sa place et sa valeur (son type tant dfini par la mthode utilise...). Voici un exemple :

p a c k a g ec o m . s d z . p r e p a r e ; i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . D r i v e r M a n a g e r ; i m p o r tj a v a . s q l . P r e p a r e d S t a t e m e n t ; i m p o r tj a v a . s q l . R e s u l t S e t ; i m p o r tj a v a . s q l . S t a t e m e n t ; p u b l i cc l a s sP r e p a r e{ p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ){ t r y{ C l a s s . f o r N a m e ( " o r g . p o s t g r e s q l . D r i v e r " ) ; S t r i n gu r l=" j d b c : p o s t g r e s q l : / / l o c a l h o s t : 5 4 3 2 / E c o l e " ; S t r i n gu s e r=" p o s t g r e s " ; S t r i n gp a s s w d=" p o s t g r e s " ; C o n n e c t i o nc o n n=D r i v e r M a n a g e r . g e t C o n n e c t i o n ( u r l ,u s e r ,p a s s w d ) ; S t a t e m e n ts t a t e=c o n n . c r e a t e S t a t e m e n t ( R e s u l t S e t . T Y P E _ S C R O L L _ I N S E N S I T I V E ,R e s u l t S e t . C O N C U R _ U P D A T A B L E ) ; / / O nc r en o t r er e q u t e S t r i n gq u e r y=" S E L E C Tp r o f _ n o m ,p r o f _ p r e n o mF R O Mp r o f e s s e u r " ; / / P r e m i e rt r o up o u rl en o md up r o f e s s e u r q u e r y+ ="W H E R Ep r o f _ n o m=? " ; / / D e u x i m et r o up o u ru ni dd ep r o f e s s e u r q u e r y+ ="O Rp r o f _ i d=? " ; / / O nc r en o t r eo b j e ta v e cl ar e q u t ee np a r a m t r e P r e p a r e d S t a t e m e n tp r e p a r e=c o n n . p r e p a r e S t a t e m e n t ( q u e r y ) ; / / O nr e m p l a c el et r o un u m r o1= >l en o md up r o f e s s e u r p r e p a r e . s e t S t r i n g ( 1 ," M A M O U D " ) ; / / O nr e m p l a c el et r o un u m r o2= >l ' i dd up r o f e s s e u r p r e p a r e . s e t I n t ( 2 ,2 ) ; / / O na f f i c h e S y s t e m . o u t . p r i n t l n ( p r e p a r e . t o S t r i n g ( ) ) ; / / O nr e m o d i f i el et r o un u m r o1 p r e p a r e . s e t S t r i n g ( 1 ," T O T O " ) ; / / O nr a f f i c h e S y s t e m . o u t . p r i n t l n ( p r e p a r e . t o S t r i n g ( ) ) ; / / O nr e m o d i f i el et r o un u m r o2 p r e p a r e . s e t I n t ( 2 ,1 5 9 7 5 3 ) ; / / O nr a f f i c h e S y s t e m . o u t . p r i n t l n ( p r e p a r e . t o S t r i n g ( ) ) ; p r e p a r e . c l o s e ( ) ; s t a t e . c l o s e ( ) ;

}c a t c h( E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } } }

Ce qui nous donne :

Je sais, a fait toujours a la premire fois... :p Je ne vous cache pas que ceci peut s'avrer trs utile. En effet ! Mais qu'y a-t-il comme mthode d'affectation de valeur ? C'est simple : vous vous souvenez de la petite liste de mthodes de l'objet ResultSet pour rcuprer des donnes ? peu de choses prs, la mme mais avec setXXX la place de getXXX . ;) Tout comme son homologue sans trou, cet objet peut prendre les mmes types de paramtres pour la lecture et pour la modification des donnes lues :
P r e p a r e d S t a t e m e n tp r e p a r e=c o n n . p r e p a r e S t a t e m e n t ( q u e r y , R e s u l t S e t . T Y P E _ S C R O L L _ I N S E N S I T I V E , R e s u l t S e t . C O N C U R _ R E A D _ O N L Y ) ;

Vous avez aussi une mthode retournant un objet ResultSetMetaData mais encore une mthode permettant de nettoyer les changements de valeur des trous : p r e p a r e . c l e a r P a r a m e t e r s ( ) ; . Si vous ajoutez cette mthode la fin de ce que je vous ai fait tout l'heure et que vous affichez nouveau le contenu de notre objet, vous aurez ceci :

Bon, je pense que le moment est venu de voir l'objet ResultSet plus en dtail...

ResultSet 2 : le retour
Nous allons voir comment se promener dans nos objets ResultSet, vu que nous avons vu comment permettre cela... ^^ En fait, l'objet de rsultat offre beaucoup de mthodes afin de pouvoir se promener dans les rsultats. Cela, si vous avez bien prpar l'objet Statement. Vous avez la possibilit de :

vous positionner avant la premire ligne de votre rsultat : r e s . b e f o r e F i r s t ( ) ; savoir si vous tes sur l'avant-premire ligne : r e s . i s B e f o r e F i r s t ( ) ; vous positionner sur la premire ligne de votre rsultat : r e s . f i r s t ( ) ; savoir si vous tes sur la premire ligne : r e s . i s F i r s t ( ) ; vous retrouver sur la dernire ligne : r e s . l a s t ( ) ; savoir si vous tes sur la dernire ligne : r e s . i s L a s t ( ) ; vous mettre aprs la dernire ligne de rsultat : r e s . a f t e r L a s t ( ) ; savoir si vous tes sur l'aprs-dernire ligne : r e s . i s A f t e r L a s t ( ) ; aller de la premire ligne la dernire : r e s . n e x t ( ) ; aller de la dernire ligne la premire : r e s . p r e v i o u s ( ) ; vous positionner sur une ligne prcise de votre rsultat : r e s . a b s o l u t e ( 5 ) ; vous positionner sur une ligne par rapport votre emplacement actuel : r e s . r e l a t i v e ( 3 ) . Je vous ai concoct un morceau de code mettant en oeuvre tout ceci... Vous devriez retrouver les informations vu que ce code est comment. ;)
p a c k a g ec o m . s d z . r e s u l t s e t ; i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . D r i v e r M a n a g e r ; i m p o r tj a v a . s q l . R e s u l t S e t ; i m p o r tj a v a . s q l . S t a t e m e n t ; p u b l i cc l a s sR e s u l t s e t{ p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ){ t r y{ / / / / T O U TC E C I ,V O U SC O N N A I S S E Z C l a s s . f o r N a m e ( " o r g . p o s t g r e s q l . D r i v e r " ) ; S t r i n gu r l=" j d b c : p o s t g r e s q l : / / l o c a l h o s t : 5 4 3 2 / E c o l e " ; S t r i n gu s e r=" p o s t g r e s " ; S t r i n gp a s s w d=" p o s t g r e s " ; C o n n e c t i o nc o n n=D r i v e r M a n a g e r . g e t C o n n e c t i o n ( u r l ,u s e r ,p a s s w d ) ; S t a t e m e n ts t a t e=c o n n . c r e a t e S t a t e m e n t ( R e s u l t S e t . T Y P E _ S C R O L L _ S E N S I T I V E ,R e s u l t S e t . C O N C U R _ U P D A T A B L E ) ; S t r i n gq u e r y=" S E L E C Tp r o f _ n o m ,p r o f _ p r e n o mF R O Mp r o f e s s e u r " ; R e s u l t S e tr e s=s t a t e . e x e c u t e Q u e r y ( q u e r y ) ; / / -

/ / * i n ti=1 ; S y s t e m . o u t . p r i n t l n ( " \ n \ t " ) ; S y s t e m . o u t . p r i n t l n ( " \ t L E C T U R ES T A N D A R D . " ) ; S y s t e m . o u t . p r i n t l n ( " \ t " ) ; w h i l e ( r e s . n e x t ( ) ) { S y s t e m . o u t . p r i n t l n ( " \ t N o m:"+r e s . g e t S t r i n g ( " p r o f _ n o m " )+"\ tp r n o m:" +r e s . g e t S t r i n g ( " p r o f _ p r e n o m " ) ) ; / / O nr e g a r d es in o u ss o m m e ss u rl ad e r n i r el i g n ed ur s u l t a t i f ( r e s . i s L a s t ( ) ) S y s t e m . o u t . p r i n t l n ( " \ t \ t *D E R N I E RR E S U L T A T! \ n " ) ; i + + ; } / / U n ef o i st e r m i n ,n o u sc o n t r l o n ss in o u ss o m m e sb i e nl ' e x t r i e u rd e sl i g n e sd er s u l t a t i f ( r e s . i s A f t e r L a s t ( ) ) S y s t e m . o u t . p r i n t l n ( " \ t N o u sv e n o n sd et e r m i n e r! \ n " ) ; S y s t e m . o u t . p r i n t l n ( " \ t " ) ; S y s t e m . o u t . p r i n t l n ( " \ t L e c t u r ee ns e n sc o n t r a i r e . " ) ; S y s t e m . o u t . p r i n t l n ( " \ t " ) ; / / N o u ss o m m e sd o n cl af i n / / N o u sp o u v o n sp a r c o u r i rl er s u l t a te ns e n sc o n t r a i r e w h i l e ( r e s . p r e v i o u s ( ) ) { S y s t e m . o u t . p r i n t l n ( " \ t N o m:"+r e s . g e t S t r i n g ( " p r o f _ n o m " )+"\ tp r n o m:" +r e s . g e t S t r i n g ( " p r o f _ p r e n o m " ) ) ; / / O nr e g a r d es io ne s ts u rl ap r e m i r el i g n ed ur s u l t a t i f ( r e s . i s F i r s t ( ) ) S y s t e m . o u t . p r i n t l n ( " \ t \ t *R E T O U RA UD E B U T! \ n " ) ; } / / O nr e g a r d es io ne s ts u rl ' a v a n t p r e m i r el i g n ed ur s u l t a t i f ( r e s . i s B e f o r e F i r s t ( ) ) S y s t e m . o u t . p r i n t l n ( " \ t N o u sv e n o n sd er e v e n i ra ud b u t! \ n " ) ;

S y s t e m . o u t . p r i n t l n ( " \ t " ) ; S y s t e m . o u t . p r i n t l n ( " \ t A p r sp o s i t i o n n e m e n ta b s o l ud uc u r s e u rl ap l a c eN "+i / 2+" . " ) ; S y s t e m . o u t . p r i n t l n ( " \ t " ) ;

/ / O n p o s i t i o n n el ec u r s e u rs u rl al i g n ei / 2 ,p e ui m p o r t eo o n e s t r e s . a b s o l u t e ( i / 2 ) ; w h i l e ( r e s . n e x t ( ) ) S y s t e m . o u t . p r i n t l n ( " \ t N o m:"+r e s . g e t S t r i n g ( " p r o f _ n o m " )+"\ tp r n o m:" +r e s . g e t S t r i n g ( " p r o f _ p r e n o m " ) ) ; S y s t e m . o u t . p r i n t l n ( " \ t " ) ; S y s t e m . o u t . p r i n t l n ( " \ t A p r sp o s i t i o n n e m e n tr e l a t i fd uc u r s e u r l ap l a c eN "+( i( i 2 ) )+" . " ) ; S y s t e m . o u t . p r i n t l n ( " \ t " ) ; / / O n m e tl ec u r s e u rl al i g n ea c t u e l l em o i n si 2 / / S in o u sr e c u l o n sd o n cd ei 2l i g n e s / / S in o u sn ' a v i o n sp a sm i sd es i g n em o i n s ,n o u sa u r i o n sa v a n c d ei 2l i g n e s r e s . r e l a t i v e ( ( i 2 ) ) ; w h i l e ( r e s . n e x t ( ) ) S y s t e m . o u t . p r i n t l n ( " \ t N o m:"+r e s . g e t S t r i n g ( " p r o f _ n o m " )+"\ tp r n o m:" +r e s . g e t S t r i n g ( " p r o f _ p r e n o m " ) ) ; r e s . c l o s e ( ) ; s t a t e . c l o s e ( ) ; }c a t c h( E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } } }

Voyez ce que donne ce code :

Je pense que la majorit des choses ont t vues ici... Par contre, faites bien attention l'endroit o vous vous situez dans le parcours de la requte ! Il y a des emplacements particuliers. Par exemple, si vous n'tes pas encore positionns sur le premier lment et que vous faites un r s . r e l a t i v e ( 1 ) , vous vous retrouvez sur le premier lment. De mme, un r s . a b s o l u t e ( 0 ) ; correspond un r s . b e f o r e F i r s t ( ) ! Donc, lorsque vous voulez spcifiez la place du curseur sur la premire ligne, vous utiliserez a b s o l u t e ( 1 ) ; et ceci, peu importe o vous vous trouvez !

Par contre, ceci ncessite que le ResultSet soit de type TYPE_SCROLL_SENSITIVE ou TYPE_SCROLL_INSENSITIVE , sinon vous aurez une exception ! Bon, rien de bien mchant ici... Je vous propose donc de clore ce chapitre par un petit QCM avant de continuer sur notre lance... J'espre que ce chapitre vous a permis d'y voir plus clair sur le fonctionnement global de tout ce mic-mac...

Aprs la lecture : l'dition


Nous avons appris utiliser des requtes SQL avec des ResultSet afin de rcuprer des informations provenant de la base. Nous allons voir comment diter nos tables en insertion, modification et suppression dans nos programmes Java ! Vous allez voir, c'est simplissime ! ! ^^

Modifier des donnes


Je sais que beaucoup d'entre vous se sont dit, lors du chapitre prcdent : "t'es sympa, tu nous dis que les objets ResultSetpeuvent modifier des donnes lors de parcours de rsultats... et tu ne nous montres mme pas a !" J'ai juste prfr sparer le ct lecture du ct lecture et modifications. D'ailleurs, c'est par a que nous allons commencer. Bien sr, il faudra que l'objet Statement retourne un ResultSet permettant cela ! En fait, durant la lecture, vous pouvez utilisez des mthodes qui ressemblent celle que je vous ai dj montre lors du parcours d'un rsultat... Vous vous souvenez, les mthodes comme :
r e s . g e t A s c i i ( ) ; r e s . g e t B y t e s ( ) ; r e s . g e t I n t ( ) ; r e s . g e t S t r i n g ( ) ;

... Sauf qu'ici, vous remplacerez g e t X X X ( ) ; par u p d a t e X X X ( ) ; . Ces mthodes de mise jour des donnes prennent deux paramtres : 1 : le nom de la colonne (String) ; 2 : la valeur mettre la place de la valeur existante (dpend de la mthode utilise) ; Comment a : dpend de la mthode utilise ? C'est simple :
u p d a t e F l o a t ( S t r i n gn o m C o l o n n e ,f l o a tv a l u e ) : prend un float comme valeur ; u p d a t e S t r i n g ( S t r i n gn o m C o l o n n e ,S t r i n gv a l u e ) : prend une chane de caractres en paramtre ;

...

Donc, changer la valeur d'un champ est trs simple mais il faut, en plus des changements de valeurs, valider ces changements pour qu'ils soient effectifs, et ceci se fait grce la mthode u p d a t e R o w ( ) . De la mme faon, vous pouvez annuler des changements avec la mthode c a n c e l R o w U p d a t e s ( ) . Si vous avez annuler des modifications, vous devrez le faire avant la mthode de validation, sinon, l'annulation sera ignore ! Je vous propose de voir un petit exemple de mise jour :
p a c k a g ec o m . s d z . r e s u l t s e t ; i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . D r i v e r M a n a g e r ; i m p o r tj a v a . s q l . R e s u l t S e t ; i m p o r tj a v a . s q l . S t a t e m e n t ; p u b l i cc l a s sM o d i f{ p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ){ t r y{ / / / / T O U TC E C I ,V O U SC O N N A I S S E Z C l a s s . f o r N a m e ( " o r g . p o s t g r e s q l . D r i v e r " ) ; S t r i n gu r l=" j d b c : p o s t g r e s q l : / / l o c a l h o s t : 5 4 3 2 / E c o l e " ; S t r i n gu s e r=" p o s t g r e s " ; S t r i n gp a s s w d=" p o s t g r e s " ; C o n n e c t i o nc o n n=D r i v e r M a n a g e r . g e t C o n n e c t i o n ( u r l ,u s e r ,p a s s w d ) ; / / O na u t o r i s el am i s ej o u rd e sd o n n e se tl am i s ej o u rd el ' a f f i c h a g e S t a t e m e n ts t a t e=c o n n . c r e a t e S t a t e m e n t ( R e s u l t S e t . T Y P E _ S C R O L L _ I N S E N S I T I V E ,R e s u l t S e t . C O N C U R _ U P D A T A B L E ) ; / / O nv ac h e r c h e ru n el i g n ed a n sl ab a s ed ed o n n e s S t r i n gq u e r y=" S E L E C Tp r o f _ i d ,p r o f _ n o m ,p r o f _ p r e n o mF R O Mp r o f e s s e u rW H E R Ep r o f _ n o m=' M A M O U ' " ; R e s u l t S e tr e s=s t a t e . e x e c u t e Q u e r y ( q u e r y ) ; / / / / O ns ep o s i t i o n n es u rl ap r e m i r el i g n ed ed o n n e r e s . f i r s t ( ) ; / / O na f f i c h ec eq u ' o nt r o u v e S y s t e m . o u t . p r i n t l n ( " N O M:"+r e s . g e t S t r i n g ( " p r o f _ n o m " )+"-P R E N O M:"+r e s . g e t S t r i n g ( " p r o f _ p r e n o m " ) ) ; / / O nm e tj o u rl e sc h a m p s

r e s . u p d a t e S t r i n g ( " p r o f _ n o m " ," C O U R T E L " ) ; r e s . u p d a t e S t r i n g ( " p r o f _ p r e n o m " ," A n g e l o " ) ; / / O nv a l i d e r e s . u p d a t e R o w ( ) ; / / E tv o i c il e sm o d i f i c a t i o n s S y s t e m . o u t . p r i n t l n ( " * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * " ) ; S y s t e m . o u t . p r i n t l n ( " A P R E SM O D I F I C A T I O N:" ) ; S y s t e m . o u t . p r i n t l n ( " \ t N O M:"+r e s . g e t S t r i n g ( " p r o f _ n o m " )+"P R E N O M:"+r e s . g e t S t r i n g ( " p r o f _ p r e n o m " )+" \ n " ) ; / / O nr e m e tl e si n f o sd ud p a r t r e s . u p d a t e S t r i n g ( " p r o f _ n o m " ," M A M O U " ) ; r e s . u p d a t e S t r i n g ( " p r o f _ p r e n o m " ," D a n i e l " ) ; / / O nr e v a l i d e r e s . u p d a t e R o w ( ) ; / / E tv o i l ! S y s t e m . o u t . p r i n t l n ( " * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * " ) ; S y s t e m . o u t . p r i n t l n ( " A P R E SR E M O D I F I C A T I O N:" ) ; S y s t e m . o u t . p r i n t l n ( " \ t N O M:"+r e s . g e t S t r i n g ( " p r o f _ n o m " )+"P R E N O M:"+r e s . g e t S t r i n g ( " p r o f _ p r e n o m " )+" \ n " ) ; r e s . c l o s e ( ) ; s t a t e . c l o s e ( ) ; }c a t c h( E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } } }

Et voici ce que j'obtiens :

Donc, le temps d'un instant, les donnes ont t modifies dans la base de donnes, nous avons donc russi notre pari ! :magicien: te-nous d'un doute, une bte requte SQL n'aurait pas pu faire l'affaire ?

Bien sr que si ! :) Mais au moins, vous avez vu comment modifier des lignes via l'objet ResultSet... Nous allons voir comment excuter les autres types de requtes avec Java !

Statement, toujours plus fort


Vous savez depuis quelques temps dj que ce sont les objets Statement qui sont chargs d'excuter les instructions SQL. Par consquent, vous devez avoir devin que les requtes de type sront aussi excutes par ces mmes objets : INSERT UPDATE DELETE CREATE Voici un code d'exemple :
p a c k a g ec o m . s d z . s t a t e m e n t ; i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . D r i v e r M a n a g e r ; i m p o r tj a v a . s q l . P r e p a r e d S t a t e m e n t ; i m p o r tj a v a . s q l . R e s u l t S e t ; i m p o r tj a v a . s q l . S Q L E x c e p t i o n ; i m p o r tj a v a . s q l . S t a t e m e n t ; p u b l i cc l a s sS t a t e{ p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ){ t r y{ C l a s s . f o r N a m e ( " o r g . p o s t g r e s q l . D r i v e r " ) ; S t r i n gu r l=" j d b c : p o s t g r e s q l : / / l o c a l h o s t : 5 4 3 2 / E c o l e " ; S t r i n gu s e r=" p o s t g r e s " ; S t r i n gp a s s w d=" p o s t g r e s " ; C o n n e c t i o nc o n n=D r i v e r M a n a g e r . g e t C o n n e c t i o n ( u r l ,u s e r ,p a s s w d ) ; / / O na u t o r i s el am i s ej o u rd e sd o n n e se tl am i s ej o u rd el ' a f f i c h a g e S t a t e m e n ts t a t e=c o n n . c r e a t e S t a t e m e n t ( R e s u l t S e t . T Y P E _ S C R O L L _ S E N S I T I V E ,R e s u l t S e t . C O N C U R _ U P D A T A B L E ) ; P r e p a r e d S t a t e m e n tp r e p a r e=c o n n . p r e p a r e S t a t e m e n t ( " U P D A T Ep r o f e s s e u rs e tp r o f _ p r e n o m=?W H E R Ep r o f _ n o m=' M A M O U ' " ) ; / / O nv ac h e r c h e ru n el i g n ed a n sl ab a s ed ed o n n e s S t r i n gq u e r y=" S E L E C Tp r o f _ n o m ,p r o f _ p r e n o mF R O Mp r o f e s s e u rW H E R Ep r o f _ n o m=' M A M O U ' " ;

/ / O ne x c u t el ar e q u t e R e s u l t S e tr e s=s t a t e . e x e c u t e Q u e r y ( q u e r y ) ; r e s . f i r s t ( ) ; / / O na f f i c h e S y s t e m . o u t . p r i n t l n ( " \ n \ t D O N N E E SD ' O R I G I N E:" ) ; S y s t e m . o u t . p r i n t l n ( " \ t " ) ; S y s t e m . o u t . p r i n t l n ( " \ t N O M:"+r e s . g e t S t r i n g ( " p r o f _ n o m " )+"P R E N O M:"+r e s . g e t S t r i n g ( " p r o f _ p r e n o m " ) ) ; / / O np a r a m t r en o t r er e q u t ep r p a r e p r e p a r e . s e t S t r i n g ( 1 ," G r a r d " ) ; / / O ne x c u t e p r e p a r e . e x e c u t e U p d a t e ( ) ; r e s=s t a t e . e x e c u t e Q u e r y ( q u e r y ) ; r e s . f i r s t ( ) ; / / O na f f i c h en o u v e a u S y s t e m . o u t . p r i n t l n ( " \ n \ t \ tA P R E SM A J:" ) ; S y s t e m . o u t . p r i n t l n ( " \ t \ t*N O M:"+r e s . g e t S t r i n g ( " p r o f _ n o m " )+ "-P R E N O M:"+r e s . g e t S t r i n g ( " p r o f _ p r e n o m " ) ) ; / / O nr e f a i tu n em i s ej o u r p r e p a r e . s e t S t r i n g ( 1 ," D a n i e l " ) ; p r e p a r e . e x e c u t e U p d a t e ( ) ; r e s=s t a t e . e x e c u t e Q u e r y ( q u e r y ) ; r e s . f i r s t ( ) ; / / o na f f i c h eu n en o u v e l l ef o i s S y s t e m . o u t . p r i n t l n ( " \ n \ t \ tR E M I S EAZ E R O:" ) ; S y s t e m . o u t . p r i n t l n ( " \ t \ t*N O M:"+r e s . g e t S t r i n g ( " p r o f _ n o m " )+ "-P R E N O M:"+r e s . g e t S t r i n g ( " p r o f _ p r e n o m " ) ) ; p r e p a r e . c l o s e ( ) ; r e s . c l o s e ( ) ; s t a t e . c l o s e ( ) ; }c a t c h( C l a s s N o t F o u n d E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; }c a t c h( S Q L E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } } }

Ce qui me donne :

Ici, nous avons utilis un PreparedStatement, histoire de faire compliqu ds le premier coup... ^^ Mais vous auriez pu tout aussi bien utiliser un Statement tout simple et invoquer la mthode e x e c u t e U p d a t e ( S t r i n gq u e r y ) . Vous savez quoi ? Pour les autres types de requtes, il suffit d'invoquer la mme mthode que pour la mise jour... En fait, celle-ci retourne un boolen qui permet de savoir si le traitement a russi ou non. :) Voici quelques exemples :
s t a t e . e x e c u t e U p d a t e ( " I N S E R TI N T Op r o f e s s e u r( p r o f _ n o m ,p r o f _ p r e n o m )V A L U E S ( ' S A L M O N ' ,' D y l a n ' ) " ) ; s t a t e . e x e c u t e U p d a t e ( " D E L E T EF R O Mp r o f e s s e u rW H E R Ep r o f _ n o m=' M A M O U ' " ) ;

C'est trs simple utiliser, vous ne pourrez pas dire le contraire... :- Cependant, je ne sais pas si vous savez ceci, mais certains moteurs SQL, comme PostgreSQL, vous proposent de grer vos requtes SQL (celles qui ont pour effet une modification de la base, pas celle de visualisation de donnes) avec ce qu'on appelle des transactions...

Grer les transactions manuellement


Tu es bien gentil, mais qu'est-ce que c'est que a ? Bon, alors, par o vais-je commencer ?... Lorsque vous insrez, modifiez ou supprimez des donnes dans PostgreSQL, il se passe un vnement automatique : la validation des modifications par le moteur SQL ! C'est aussi simple que a... Un petit schma pour visualiser :

Lorsque vous excutez une requte de type INSERT, CREATE , UPDATE ou DELETE , ces requtes modifient les donnes prsentes dans la base. Une fois excute, le moteur SQL valide directement ces modifications ! Par contre, vous pouvez avoir la main sur ce point :

Comme ceci, c'est vous qui avez le contrle sur vos donnes ! Je ne vois pas l'intrt de faire a ! C'est simple : pour pouvoir contrler l'intgrit de vos donnes ! Imaginez que vous devez faire deux requtes, une modification et une insertion et que vous partez du principe que l'insertion dpend de la mise jour ! Comment feriez-vous si de mauvaises donnes taient mises jour ? L'insertion qui en dcoule serait mauvaise... :( Ceci, bien sr, si le moteur SQL valide automatiquement les requtes faites... Oui, vu sous cet angle... Comment on gre a, alors ? On spcifie au moteur SQL de ne pas valider automatiquement. Ou plutt de valider automatiquement les requtes SQL avec une mthode qui prend un boolen en paramtre, mais qui ne concernera pas l'objet Statement, mais l'objet Connection :

i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . D r i v e r M a n a g e r ; i m p o r tj a v a . s q l . R e s u l t S e t ; i m p o r tj a v a . s q l . S t a t e m e n t ;

p u b l i cc l a s sT r a n s a c t{ p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ){ t r y{ C l a s s . f o r N a m e ( " o r g . p o s t g r e s q l . D r i v e r " ) ; S t r i n gu r l=" j d b c : p o s t g r e s q l : / / l o c a l h o s t : 5 4 3 2 / E c o l e " ; S t r i n gu s e r=" p o s t g r e s " ; S t r i n gp a s s w d=" b a t t e r i e " ; C o n n e c t i o nc o n n=D r i v e r M a n a g e r . g e t C o n n e c t i o n ( u r l ,u s e r ,p a s s w d ) ; c o n n . s e t A u t o C o m m i t ( f a l s e ) ; }c a t c h( E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } } }

Par contre, lorsque vous voulez que vos requtes soient prises en compte, il faut utiliser la mthode c o n n . c o m m i t ( ) ; . En mode s e t A u t o C o m m i t ( f a l s e ) ; , si vous ne validez pas vos requtes, elles ne seront pas prises en compte ! Vous pouvez revenir tout moment en mode validation automatique avec s e t A u t o C o m m i t ( t r u e ) ; Voici un exemple :

i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . D r i v e r M a n a g e r ; i m p o r tj a v a . s q l . R e s u l t S e t ; i m p o r tj a v a . s q l . S t a t e m e n t ;

p u b l i cc l a s sT r a n s a c t{ p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ){ t r y{ C l a s s . f o r N a m e ( " o r g . p o s t g r e s q l . D r i v e r " ) ; S t r i n gu r l=" j d b c : p o s t g r e s q l : / / l o c a l h o s t : 5 4 3 2 / E c o l e " ; S t r i n gu s e r=" p o s t g r e s " ; S t r i n gp a s s w d=" b a t t e r i e " ; C o n n e c t i o nc o n n=D r i v e r M a n a g e r . g e t C o n n e c t i o n ( u r l ,u s e r ,p a s s w d ) ; c o n n . s e t A u t o C o m m i t ( f a l s e ) ; S t a t e m e n ts t a t e=c o n n . c r e a t e S t a t e m e n t ( R e s u l t S e t . T Y P E _ S C R O L L _ S E N S I T I V E ,R e s u l t S e t . C O N C U R _ U P D A T A B L E ) ; S t r i n gq u e r y=" U P D A T Ep r o f e s s e u rS E Tp r o f _ p r e n o m=' C y r i l l e 'W H E R Ep r o f _ n o m=' M A M O U ' " ; R e s u l t S e tr e s u l t=s t a t e . e x e c u t e Q u e r y ( " S E L E C T*F R O Mp r o f e s s e u r W H E R Ep r o f _ n o m=' M A M O U ' " ) ; r e s u l t . f i r s t ( ) ; S y s t e m . o u t . p r i n t l n ( " N O M:"+r e s u l t . g e t S t r i n g ( " p r o f _ n o m " )+"P R E N O M:"+r e s u l t . g e t S t r i n g ( " p r o f _ p r e n o m " ) ) ; s t a t e . e x e c u t e U p d a t e ( q u e r y ) ; r e s u l t=s t a t e . e x e c u t e Q u e r y ( " S E L E C T*F R O Mp r o f e s s e u rW H E R Ep r o f _ n o m=' M A M O U ' " ) ; r e s u l t . f i r s t ( ) ; S y s t e m . o u t . p r i n t l n ( " N O M:"+r e s u l t . g e t S t r i n g ( " p r o f _ n o m " )+"P R E N O M:"+r e s u l t . g e t S t r i n g ( " p r o f _ p r e n o m " ) ) ; r e s u l t . c l o s e ( ) ; s t a t e . c l o s e ( ) ; }c a t c h( E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } } }

Vous pouvez excuter le code autant de fois que vous voulez, vous aurez toujours :

Vous voyez : malgr la requte de mise jour, celle-ci est inoprante ! Oh oui ! Vous pouvez voir les modifications durant le temps d'excution du script, mais vu que vous n'avez pas valid les modifications, celles-ci sont annules la fin... Pour que la mise jour soit effective, il aurait fallu faire un c o n n . c o m m i t ( ) avant la fin du script ! ^^ Bon, je crois qu'on en a assez vu pour ce chapitre... En route pour le QCM ! :pirate: Alors ? Je ne vous avais pas dit que ce chapitre allait tre tout simple ? Chose promise, chose due ! Maintenant, je vous propose de voir comment uniformiser un peu tout a... C'est vrai qu'tablir tout le temps la connexion est un peu fastidieux alors qu'une seule instance de celle-ci suffirait... C'est ce que je vous propose de voir dans le chapitre qui suit. :)

N'avoir qu'une instance de sa connexion


L'excution de commandes SQL n'a plus de secret pour vous, je le sais, c'est moi qui vous ai forms ! :p Non, je blague... Aprs vous avoir fait dcouvrir tout a, je me suis dis : montrer une approche un peu plus objet ne serait pas du luxe ! C'est vrai, se connecter sans arrt notre base de donnes commence tre fastidieux. Je vous propose donc d'y remdier avec ce chapitre. :)

Pourquoi se connecter qu'une seule fois ?


Pourquoi tu veux absolument qu'on aie une seule instance de notre objet Connection ? Parce que a ne sert pas grand-chose de rinitialiser la connexion votre BDD. Rappelez-vous que la connexion sert faire le pont entre votre base et votre application. Pourquoi voulez-vous que votre application se connecte chaque fois votre BDD ? Une fois la connexion effective, pourquoi vouloir la refaire ? Votre application et votre BDD peuvent discuter ! Bon, c'est vrai qu'avec du recul, a parat superflu... Du coup, comment tu fais pour garantir qu'une seule instance de Connection existe dans l'application ? C'est ici que le pattern singleton arrive ! Ce pattern est peut-tre l'un des plus simples comprendre mme s'il va y avoir un point qui va vous faire bondir... ^^ Le principe de base de ce pattern est d'interdire l'instanciation d'une classe ! :waw: On peut savoir comment tu comptes t'y prendre ?

C'est a qui va vous faire bondir : avec un constructeur dclar private ! Nul ne sert de lambiner, voyons comment rendre tout ceci possible...

Le pattern singleton
Alors ce que nous voulons, c'est une seule instance de notre connexion ; voici une classe qui permet a :

p a c k a g ec o m . s d z . c o n n e c t i o n ; i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . D r i v e r M a n a g e r ; i m p o r tj a v a . s q l . S Q L E x c e p t i o n ; p u b l i cc l a s sS d z C o n n e c t i o n { / * * *U R Ld ec o n n e c t i o n * / p r i v a t eS t r i n gu r l=" j d b c : p o s t g r e s q l : / / l o c a l h o s t : 5 4 3 2 / E c o l e " ; / * * *N o md uu s e r * / p r i v a t eS t r i n gu s e r=" p o s t g r e s " ; / * * *M o td ep a s s ed uu s e r * / p r i v a t eS t r i n gp a s s w d=" p o s t g r e s " ; / * * *O b j e tC o n n e c t i o n * / p r i v a t es t a t i cC o n n e c t i o nc o n n e c t ; / * * *C o n s t r u c t e u rp r i v * / p r i v a t eS d z C o n n e c t i o n ( ) { t r y{ c o n n e c t=D r i v e r M a n a g e r . g e t C o n n e c t i o n ( u r l ,u s e r ,p a s s w d ) ; }c a t c h( S Q L E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } } / * * *M t h o d eq u iv an o u sr e t o u r n e rn o t r ei n s t a n c e *e tl ac r e rs ie l l en ' e x i s t ep a s . . . *@ r e t u r n * / p u b l i cs t a t i cC o n n e c t i o ng e t I n s t a n c e ( ) { i f ( c o n n e c t= =n u l l ) { n e wS d z C o n n e c t i o n ( ) ; } r e t u r nc o n n e c t ; } }

Nous avons ici une classe avec un constructeur priv (mme si, ici, ce n'tait pas ncessaire) : du coup, impossible d'avoir une instance de cet objet et impossible d'accder aux attributs puisqu'ils sont dclars private ! Notre objet Connection est instanci dans le constructeur priv et la seule mthode accessible de l'extrieur de la classe est g e t I n s t a n c e ( ) . C'est donc cette mthode qui aura pour rle de crer la connexion lorsque celle-ci n'existe pas, et seulement dans ce cas. Pour en tre bien srs, nous allons faire un petit test... ^^ Voici le code un peu modifi de la mthode g e t I n s t a n c e ( ) ...
p u b l i cs t a t i cC o n n e c t i o ng e t I n s t a n c e ( ) { i f ( c o n n e c t= =n u l l ) { n e wS d z C o n n e c t i o n ( ) ; S y s t e m . o u t . p r i n t l n ( " I N S T A N C I A T I O ND EL AC O N N E X I O NS Q L!" ) ; } e l s e { S y s t e m . o u t . p r i n t l n ( " C O N N E X I O NS Q LE X I S T A N T E!" ) ; } r e t u r nc o n n e c t ; }

Ceci a pour but de voir quand la connexion est rellement cre. Ensuite, il ne nous manque plus qu'un code de test. Oh ! Ben a alors ! J'en ai un sous la main :

p a c k a g ec o m . s d z . c o n n e c t i o n ; i m p o r tj a v a . s q l . D a t a b a s e M e t a D a t a ; i m p o r tj a v a . s q l . P r e p a r e d S t a t e m e n t ; i m p o r tj a v a . s q l . S Q L E x c e p t i o n ; i m p o r tj a v a . s q l . S t a t e m e n t ; p u b l i cc l a s sT e s t{ p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ){ t r y{ / / 1 P r e p a r e d S t a t e m e n tp r e p a r e=S d z C o n n e c t i o n . g e t I n s t a n c e ( ) . p r e p a r e S t a t e m e n t ( " S E L E C T*F R O Mc l a s s eW H E R Ec l s _ n o m=? " ) ; / / 2 S t a t e m e n ts t a t e=S d z C o n n e c t i o n . g e t I n s t a n c e ( ) . c r e a t e S t a t e m e n t ( ) ; / / 3 S d z C o n n e c t i o n . g e t I n s t a n c e ( ) . s e t A u t o C o m m i t ( f a l s e ) ; / / E t4a p p e l sl am t h o d eg e t I n s t a n c e ( ) D a t a b a s e M e t a D a t am e t a=S d z C o n n e c t i o n . g e t I n s t a n c e ( ) . g e t M e t a D a t a ( ) ; }c a t c h( S Q L E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } } }

Il y a 4 appels la mthode en question, que croyez-vous que ce code va afficher ?

Vous avez la preuve que l'instanciation ne se fait qu'une seule fois et donc, que notre connexion la BDD est unique ! Bon, a c'est compris, par contre, pourquoi tu disais que le constructeur n'tait pas ncessaire ? Tout simplement parce que nous aurions pu avoir cela la place et a aurait tout aussi bien fonctionn :

p a c k a g ec o m . s d z . c o n n e c t i o n ; i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . D r i v e r M a n a g e r ; i m p o r tj a v a . s q l . S Q L E x c e p t i o n ; p u b l i cc l a s sS d z C o n n e c t i o n { / * * *U R Ld ec o n n e c t i o n * / p r i v a t es t a t i cS t r i n gu r l=" j d b c : p o s t g r e s q l : / / l o c a l h o s t : 5 4 3 2 / E c o l e " ; / * * *N o md uu s e r * / p r i v a t es t a t i cS t r i n gu s e r=" p o s t g r e s " ; / * * *M o td ep a s s ed uu s e r * / p r i v a t es t a t i cS t r i n gp a s s w d=" p o s t g r e s " ; / * * *O b j e tC o n n e c t i o n * / p r i v a t es t a t i cC o n n e c t i o nc o n n e c t ; / * * *M t h o d eq u iv an o u sr e t o u r n e rn o t r ei n s t a n c e *e tl ac r e rs ie l l en ' e x i s t ep a s . . . *@ r e t u r n * / p u b l i cs t a t i cC o n n e c t i o ng e t I n s t a n c e ( ) { i f ( c o n n e c t= =n u l l ) { t r y{ c o n n e c t=D r i v e r M a n a g e r . g e t C o n n e c t i o n ( u r l ,u s e r ,p a s s w d ) ; }c a t c h( S Q L E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } } r e t u r nc o n n e c t ; } }

Par contre, vous devrez rajouter la dclaration static de vos paramtres de connexion... Vous pouvez relancer le code de test, vous verrez qu'il fonctionne toujours ! J'ai mis un constructeur priv d'abord car vous deviez savoir que cela existait, mais c'tait superflu dans notre cas...

D'accord, mais j'ai une application multi-threads, tu es sr qu'il n'y aura pas de conflit ? Hum ! Vous savez dj rpondre cette question si vous avez lu le chapitre sur les threads du tuto Java ! (http://www.siteduzero.com/tutoriel-3-10516-les-threads.html) Il vous suffit de synchroniser la mthode g e t I n s t a n c e ( ) et le tour est jou... Mais, parce qu'il y a un mais... cette mthode ne rgle le problme qu'avant que la connexion ne soit instancie. Autrement dit, une fois la connexion instancie, la synchronisation ne sert plus rien... :euh: Le problme de multi-threading ne se pose pas vraiment pour une connexion une BDD puisque ce singleton sert surtout de passerelle entre votre BDD et votre application, mais il peut y avoir d'autres objets que des connexions SQL qui ne doivent tre instancis qu'une fois et tous ne sont pas aussi laxistes concernant le multi-threading... Voyons comment parfaire ce pattern avec un autre exemple qu'une connexion SQL...

Le singleton dans tous ces tats


Alors... Nous allons travailler avec un autre exemple et vu que j'tais trs inspir, voici notre super singleton :

p a c k a g ec o m . s d z . c o n n e c t i o n ; p u b l i cc l a s sS d z S i n g l e t o n{ / * * *L es i n g l e t o n * / p r i v a t es t a t i cS d z S i n g l e t o ns i n g l e ; / * * *V a r i a b l ed ' i n s t a n c e * / p r i v a t eS t r i n gn a m e=" " ; / * * *C o n s t r u c t e u rp r i v * / p r i v a t eS d z S i n g l e t o n ( ) { t h i s . n a m e=" M o ns i n g l e t o n " ; S y s t e m . o u t . p r i n t l n ( " \ t \ t C R E A T I O ND EL ' I N S T A N C E!!! " ) ; } / * * *M t h o d ed ' a c c sa us i n g l e t o n *@ r e t u r nS d z S i n g l e t o n * / p u b l i cs t a t i cS d z S i n g l e t o ng e t I n s t a n c e ( ) { i f ( s i n g l e= =n u l l ) s i n g l e=n e wS d z S i n g l e t o n ( ) ; r e t u r ns i n g l e ; } / * * *A c c e s s e u r *@ r e t u r n * / p u b l i cS t r i n gg e t N a m e ( ) { r e t u r nt h i s . n a m e ; } }

Quoi, c'est a ton singleton ? Oui, ce n'est pas que je manquais d'inspiration, c'est juste qu'avec une classe toute simple, on comprend mieux les choses... Et voici notre classe de test :

p a c k a g ec o m . s d z . c o n n e c t i o n ; p u b l i cc l a s sT e s t S i n g l e t o n{ p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ){ f o r ( i n ti=1 ;i<4 ;i + + ) S y s t e m . o u t . p r i n t l n ( " A p p e lN "+i+":"+S d z S i n g l e t o n . g e t I n s t a n c e ( ) . g e t N a m e ( ) ) ; } }

Ce qui nous donne :

La politique du singleton est toujours bonne. Maintenant, je vais vous poser une question : quand croyezvous que la cration d'une instance soit la plus judicieuse ? Qu'est-ce que tu veux dire par l ? C'est simple : ici, nous avons excut notre code et l'instance est cre lorsque qu'on la demande pour la premire fois ! C'est le principal problme que pose le singleton et le multi-threading : la premire instance... Une fois celle-ci cre, il y a moins de problme. Parce que tu vois un autre endroit o crer l'instance, toi ? Oui, au chargement de la classe par la JVM et ceci se fait en instanciant notre singleton sa dclaration dans la classe, soit, comme ceci :

p a c k a g ec o m . s d z . c o n n e c t i o n ; p u b l i cc l a s sS d z S i n g l e t o n{ / * * *L es i n g l e t o n * / p r i v a t es t a t i cS d z S i n g l e t o ns i n g l e=n e wS d z S i n g l e t o n ( ) ; / * * *V a r i a b l ed ' i n s t a n c e * / p r i v a t eS t r i n gn a m e=" " ; / * * *C o n s t r u c t e u rp r i v * / p r i v a t eS d z S i n g l e t o n ( ) { t h i s . n a m e=" M o ns i n g l e t o n " ; S y s t e m . o u t . p r i n t l n ( " \ n \ t \ t C R E A T I O ND EL ' I N S T A N C E!!! " ) ; } / * * *M t h o d ed ' a c c sa us i n g l e t o n *@ r e t u r nS d z S i n g l e t o n * / p u b l i cs t a t i cS d z S i n g l e t o ng e t I n s t a n c e ( ) { r e t u r ns i n g l e ; } / * * *A c c e s s e u r *@ r e t u r n * / p u b l i cS t r i n gg e t N a m e ( ) { r e t u r nt h i s . n a m e ; } }

Avec ce code, c'est la machine virtuelle qui va se charger de charger l'instance du singleton, bien avant que n'importe quel thread vienne taquiner la mthode g e t I n s t a n c e ( ) ... :magicien: Il y a une autre mthode permettant de faire ceci, mais elle ne fonctionne parfaitement que depuis le JDK 1.5... On appelle cette mthode : "le verrouillage double vrification". Cette mthode consiste utiliser le mot cl volatile combin au mot cl synchronized. Pour les ZrOs qui l'ignorent, dclarer une variable volatile permet de s'assurer un accs ordonn des threads une variable (plusieurs threads peuvent accder cette variable), Ceci marque le premier point de verrouillage. Ensuite, la double vrification s'effectuera dans la mthode g e t I n s t a n c e ( ) , on synchronise UNIQUEMENT lorsque le singleton n'est pas cr. Voici ce que a nous donne :

p a c k a g ec o m . s d z . c o n n e c t i o n ; p u b l i cc l a s sS d z S i n g l e t o n{ / * * *L es i n g l e t o n * / p r i v a t ev o l a t i l es t a t i cS d z S i n g l e t o ns i n g l e ; / * * *V a r i a b l ed ' i n s t a n c e * / p r i v a t eS t r i n gn a m e=" " ; / * * *C o n s t r u c t e u rp r i v * / p r i v a t eS d z S i n g l e t o n ( ) { t h i s . n a m e=" M o ns i n g l e t o n " ; S y s t e m . o u t . p r i n t l n ( " \ n \ t \ t C R E A T I O ND EL ' I N S T A N C E!!! " ) ; } / * * *M t h o d ed ' a c c sa us i n g l e t o n *@ r e t u r nS d z S i n g l e t o n * / p u b l i cs t a t i cS d z S i n g l e t o ng e t I n s t a n c e ( ) { i f ( s i n g l e= =n u l l ) { s y n c h r o n i z e d ( S d z S i n g l e t o n . c l a s s ) { i f ( s i n g l e= =n u l l ) s i n g l e=n e wS d z S i n g l e t o n ( ) ; } } r e t u r ns i n g l e ; } / * * *A c c e s s e u r *@ r e t u r n * / p u b l i cS t r i n gg e t N a m e ( ) { r e t u r nt h i s . n a m e ; } }

Voil : vous tes dsormais incollables sur le singleton ! Je pense qu'aprs tout a, un QCM s'impose... Bon : vous devez vous rendre compte que travailler avec JDBC n'a rien de compliqu, en dfinitive ! Je vois dans vos regards que vous avez perdu le ct mystifi de JDBC, maintenant ; vous devriez tre mme d'utiliser cette API dans vos programmes Java.

Tiens, avec ce que nous venons de voir, a me donne une ide de TP... :pirate:

TP : un testeur de requte
Bon, vous avez appris un tas de choses et il est grand temps de faire un peu de pratique ! Dans ce TP, je vais vous demander de raliser un testeur de requte SQL... Vous ne voyez pas o je veux en venir ? Lisez donc la suite... :pirate:

Cahier des charges


Alors... Le but du jeu est de : pouvoir avoir une IHM permettant la saisie d'une requte SQL dans un champ ; lancer l'excution de la requte grce un bouton ; ce bouton devra tre dans une barre d'outils ; dans le cas o la requte renvoie 0 ou plusieurs rsultats, afficher ceux-ci dans un JTable ; le nom des colonnes devra tre visible ; en cas d'erreur, une pop-up (JOptionPane) contenant le message s'affichera ; un petit message affichera le temps d'excution de la requte ainsi que le nombre de lignes retournes en bas de fentre. Vous avez de quoi faire, ici... Bon, si vous ne savez pas comment faire pour le temps d'excution de la requte, je vous donne un indice : S y s t e m . c u r r e n t T i m e M i l l i s ( ) ; retourne un long... Pour les ZrOs n'ayant pas lu la partie vnementielle du tuto Java, je vous autorise faire une version en mode console ; par contre, celle-ci n'aura pas de correction... ^^

Quelques captures d'cran


Bon... Voici ce que j'ai obtenu avec mon code. Inspirez-vous en pour faire votre programme... (medias/uploads.siteduzero.com_files_156001_157000_156377.jpg)

(medias/uploads.siteduzero.com_files_156001_157000_156379.jpg) (medias/uploads.siteduzero.com_files_156001_157000_156378.jpg) Je n'ai plus qu' vous souhaiter bonne chance et bon courage ! Let's go !

Correction

DONG ! Le temps imparti est coul ! Bon : comme toujours, il s'agit d'une correction possible et non pas de LA CORRECTION ! J'espre que vous vous tes bien pris la tte sur ce TP. Bien sr, pas dans le sens o il vous a tortur l'esprit durant des heures jusqu' vous rendre malades, mais plutt dans le sens o celui-ci vous a permis de rflchir et de dcouvrir des choses. :) Bon, assez tergivers, vous devez tre impatient de voir ce que j'ai fait : Classe SdzConnection.java :

p a c k a g ec o m . s d z . c o n n e c t i o n ; i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . D r i v e r M a n a g e r ; i m p o r tj a v a . s q l . S Q L E x c e p t i o n ; i m p o r tj a v a x . s w i n g . J O p t i o n P a n e ; p u b l i cc l a s sS d z C o n n e c t i o n { / * * *U R Ld ec o n n e c t i o n * / p r i v a t es t a t i cS t r i n gu r l=" j d b c : p o s t g r e s q l : / / l o c a l h o s t : 5 4 3 2 / E c o l e " ; / * * *N o md uu s e r * / p r i v a t es t a t i cS t r i n gu s e r=" p o s t g r e s " ; / * * *M o td ep a s s ed uu s e r * / p r i v a t es t a t i cS t r i n gp a s s w d=" p o s t g r e s " ; / * * *O b j e tC o n n e c t i o n * / p r i v a t es t a t i cC o n n e c t i o nc o n n e c t ; / * * *M t h o d eq u iv ar e t o u r n e rn o t r ei n s t a n c e *e tl ac r e rs ie l l en ' e x i s t ep a s . . . *@ r e t u r n * / p u b l i cs t a t i cC o n n e c t i o ng e t I n s t a n c e ( ) { i f ( c o n n e c t= =n u l l ) { t r y{ c o n n e c t=D r i v e r M a n a g e r . g e t C o n n e c t i o n ( u r l ,u s e r ,p a s s w d ) ; }c a t c h( S Q L E x c e p t i o ne ){ J O p t i o n P a n e . s h o w M e s s a g e D i a l o g ( n u l l ,e . g e t M e s s a g e ( ) ," E R R E U RD EC O N N E X I O N!" ,J O p t i o n P a n e . E R R O R _ M E S S A G E ) ; } } r e t u r nc o n n e c t ; } }

Classe Fenetre.java

Classe Fenetre.java

p a c k a g ec o m . s d z . t p ; i m p o r tj a v a . a w t . B o r d e r L a y o u t ; i m p o r tj a v a . a w t . D i m e n s i o n ; i m p o r tj a v a . a w t . e v e n t . A c t i o n E v e n t ; i m p o r tj a v a . a w t . e v e n t . A c t i o n L i s t e n e r ; i m p o r tj a v a . s q l . R e s u l t S e t ; i m p o r tj a v a . s q l . R e s u l t S e t M e t a D a t a ; i m p o r tj a v a . s q l . S Q L E x c e p t i o n ; i m p o r tj a v a . s q l . S t a t e m e n t ; i m p o r tj a v a x . s w i n g . I m a g e I c o n ; i m p o r tj a v a x . s w i n g . J B u t t o n ; i m p o r tj a v a x . s w i n g . J F r a m e ; i m p o r tj a v a x . s w i n g . J L a b e l ; i m p o r tj a v a x . s w i n g . J O p t i o n P a n e ; i m p o r tj a v a x . s w i n g . J P a n e l ; i m p o r tj a v a x . s w i n g . J S c r o l l P a n e ; i m p o r tj a v a x . s w i n g . J S p l i t P a n e ; i m p o r tj a v a x . s w i n g . J T a b l e ; i m p o r tj a v a x . s w i n g . J T e x t A r e a ; i m p o r tj a v a x . s w i n g . J T o o l B a r ; i m p o r tc o m . s d z . c o n n e c t i o n . S d z C o n n e c t i o n ; p u b l i cc l a s sF e n e t r ee x t e n d sJ F r a m e{ / * * *T o o l B a rp o u rl el a n c e m e n td e sr e q u t e s * / p r i v a t eJ T o o l B a rt o o l=n e wJ T o o l B a r ( ) ; / * * *L eb o u t o n * / p r i v a t eJ B u t t o nl o a d=n e wJ B u t t o n ( n e wI m a g e I c o n ( " i m g / l o a d . p n g " ) ) ; / * * *L ed l i m i t e u r * / p r i v a t eJ S p l i t P a n es p l i t ; / * * *L ec o n t e n e u rd er s u l t a t * / p r i v a t eJ P a n e lr e s u l t=n e wJ P a n e l ( ) ; / * * *R e q u t ep a rd f a u tp o u rl ed m a r r a g e * / p r i v a t eS t r i n gr e q u e t e=" S E L E C T *F R O Mc l a s s e " ; / * * *L ec o m p o s a n td a n sl e q u e lt a p e rl ar e q u t e * /

p r i v a t eJ T e x t A r e at e x t=n e wJ T e x t A r e a ( r e q u e t e ) ; / * * *C o n s t r u c t e u r * / p u b l i cF e n e t r e ( ) { s e t S i z e ( 9 0 0 ,6 0 0 ) ; s e t T i t l e ( " T PJ D B C " ) ; s e t L o c a t i o n R e l a t i v e T o ( n u l l ) ; s e t D e f a u l t C l o s e O p e r a t i o n ( E X I T _ O N _ C L O S E ) ; i n i t T o o l b a r ( ) ; i n i t C o n t e n t ( ) ; i n i t T a b l e ( r e q u e t e ) ; } / * * *I n i t i a l i s el at o o l b a r * / p r i v a t ev o i di n i t T o o l b a r ( ) { l o a d . s e t P r e f e r r e d S i z e ( n e wD i m e n s i o n ( 3 0 ,3 5 ) ) ; l o a d . s e t B o r d e r ( n u l l ) ; l o a d . a d d A c t i o n L i s t e n e r ( n e wA c t i o n L i s t e n e r ( ) { p u b l i cv o i da c t i o n P e r f o r m e d ( A c t i o n E v e n te v e n t ) { i n i t T a b l e ( t e x t . g e t T e x t ( ) ) ; } } ) ; t o o l . a d d ( l o a d ) ; g e t C o n t e n t P a n e ( ) . a d d ( t o o l ,B o r d e r L a y o u t . N O R T H ) ; } / * * *I n i t i a l i s el ec o n t e n ud el af e n t r e * / p u b l i cv o i di n i t C o n t e n t ( ) { / / V o u sc o n n a i s s e z a . . . r e s u l t . s e t L a y o u t ( n e wB o r d e r L a y o u t ( ) ) ; s p l i t=n e wJ S p l i t P a n e ( J S p l i t P a n e . V E R T I C A L _ S P L I T ,n e wJ S c r o l l P a n e ( t e x t ) , r e s u l t ) ; s p l i t . s e t D i v i d e r L o c a t i o n ( 1 0 0 ) ; g e t C o n t e n t P a n e ( ) . a d d ( s p l i t ,B o r d e r L a y o u t . C E N T E R ) ; } / * * *I n i t i a l i s el ev i s u e la v e cl ar e q u t es a i s i ed a n sl ' d i t e u r *@ p a r a mq u e r y * / p u b l i cv o i di n i t T a b l e ( S t r i n gq u e r y ) {

t r y{ / / O nc r eu ns t a t e m e n t l o n gs t a r t=S y s t e m . c u r r e n t T i m e M i l l i s ( ) ; S t a t e m e n ts t a t e=S d z C o n n e c t i o n . g e t I n s t a n c e ( ) . c r e a t e S t a t e m e n t ( R e s u l t S e t . T Y P E _ S C R O L L _ I N S E N S I T I V E , R e s u l t S e t . C O N C U R _ R E A D _ O N L Y ) ; / / O ne x c u t el ar e q u t e R e s u l t S e tr e s=s t a t e . e x e c u t e Q u e r y ( q u e r y ) ; / / T e m p sd ' e x c u t i o n / / O nr c u p r el e sm e t aa f i nd er c u p r e rl en o md e sc o l o n n e s R e s u l t S e t M e t a D a t am e t a=r e s . g e t M e t a D a t a ( ) ; / / O ni n i t i a l i s eu nt a b l e a ud ' O b j e c tp o u rl e se n t t e sd ut a b l e a u O b j e c t [ ]c o l u m n=n e wO b j e c t [ m e t a . g e t C o l u m n C o u n t ( ) ] ; f o r ( i n ti=1;i< =m e t a . g e t C o l u m n C o u n t ( ) ;i + + ) { c o l u m n [ i 1 ]=m e t a . g e t C o l u m n N a m e ( i ) ; } / / P e t i t em a n i p u l a t i o np o u ro b t e n i rl en o m b r ed el i g n e s r e s . l a s t ( ) ; i n tr o w C o u n t=r e s . g e t R o w ( ) ; O b j e c t [ ] [ ]d a t a=n e wO b j e c t [ r e s . g e t R o w ( ) ] [ m e t a . g e t C o l u m n C o u n t ( ) ] ; / / O nr e v i e n ta ud p a r t r e s . b e f o r e F i r s t ( ) ; i n tj=1 ; / / O nr e m p l i tl et a b l e a ud ' O b j e c t [ ] [ ] w h i l e ( r e s . n e x t ( ) ) { f o r ( i n ti=1;i< =m e t a . g e t C o l u m n C o u n t ( ) ;i + + ) d a t a [ j 1 ] [ i 1 ]=r e s . g e t O b j e c t ( i ) ; j + + ; } / / o nf e r m el et o u t r e s . c l o s e ( ) ; s t a t e . c l o s e ( ) ; l o n gt o t a l T i m e=S y s t e m . c u r r e n t T i m e M i l l i s ( )-s t a r t ;

/ / O ne n l v el ec o n t e n ud en o t r ec o n t e n e u r r e s u l t . r e m o v e A l l ( ) ; / / O nya j o u t eu nJ T a b l e r e s u l t . a d d ( n e wJ S c r o l l P a n e ( n e wJ T a b l e ( d a t a ,c o l u m n ) ) ,B o r d e r L a y o u t . C E N T E R ) ; r e s u l t . a d d ( n e wJ L a b e l ( " L ar e q u t e t e x c u t e re n"+t o t a l T i m e+"m se tar e t o u r n "+r o w C o u n t+"l i g n e ( s ) " ) ,B o r d e r L a y o u t . S O U T H ) ; / / O nf o r c el am i s ej o u rd el ' a f f i c h a g e r e s u l t . r e v a l i d a t e ( ) ; }c a t c h( S Q L E x c e p t i o ne ){ / / D a n sl ec a sd ' u n ee x c e p t i o n ,o na f f i c h eu n ep o p u pe to ne f f a c el ec o n t e n u r e s u l t . r e m o v e A l l ( ) ; r e s u l t . a d d ( n e wJ S c r o l l P a n e ( n e wJ T a b l e ( ) ) ,B o r d e r L a y o u t . C E N T E R ) ; r e s u l t . r e v a l i d a t e ( ) ; J O p t i o n P a n e . s h o w M e s s a g e D i a l o g ( n u l l ,e . g e t M e s s a g e ( ) ," E R R E U R!" , J O p t i o n P a n e . E R R O R _ M E S S A G E ) ; } } / * * *P o i n td ed p a r td up r o g r a m m e *@ p a r a ma r g s * / p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ) { F e n e t r ef e n=n e wF e n e t r e ( ) ; f e n . s e t V i s i b l e ( t r u e ) ; } }

Bien sr, ce code n'est pas la perfection mme, vous pouvez l'amliorer grandement ! Vous pouvez utiliser un autre composant que moi pour la saisie de la requte, un JTextPane par exemple : pour la coloration syntaxique... ;) Vous pourriez avoir un menu qui vous permette de sauvegarder vos requtes, un tableau interactif autorisant la modification des donnes... Bref, ce n'est pas les amliorations qui manquent. :- Un TP assez riche et qui a d vous demander quelques instants de rflexion... :diable: Mais bon, rien d'insurmontable pour les ZrOs avertis que vous tes. Je vous propose maintenant de voir comment faire en sorte d'utiliser des objets Java correspondant vos donnes dans votre BDD ! J'imagine que vous aspirez faire ceci depuis longtemps... Alors, rendez-vous au prochain chapitre ! :)

Le pattern DAO (1/2)


Bon, vous voulez pouvoir utiliser vos donnes dans des objets, et c'est normal ! ^^ Avec le pattern DAO, vous allez voir comment faire ceci mais en plus, comment rendre a stable !

En fait, je suppose que vous avez d essayer de faire en sorte que les donnes de votre base collent vos objets, avec des mthodes : de rcupration ; de cration ; de mise jour ; de suppression. Nous allons voir tout ceci dans ce chapitre et le suivant ! :)

Avant toute chose


Comme je le disais, vous avez d essayer de faire en sorte que les donnes de la base puissent tre utilises via des objets Java. En tout premier lieu, il faut crer une classe par entit (les tables hors tables de jointures...), ce qui nous donnerait les classes suivantes : Eleve ; Matiere ; Professeur ; Classe. Et, si nous suivons la logique des relations entre nos tables, nous avons des classes lies suivant le diagramme de classes suivant :

Nous voyons les liens entre les objets avec ce diagramme : une classe est compose de plusieurs lves et de plusieurs professeurs, et un professeur peut exercer plusieurs matires ! Les tables de jointures de la base sont symbolises par la composition dans nos objets. Une fois ceci fait, nous devons coder ces objets avec les accesseurs et les mutateurs adquats : getters et setters pour tous les attributs de toutes les classes ; mthode d'ajout et de suppression pour les objets ayant des listes d'objets. On appelle ce genre d'objet des POJO, pour Plain Old Java Object ! Ce qui nous donne ces codes sources :

Classe Eleve.java
p a c k a g ec o m . s d z . b e a n ;

p u b l i cc l a s sE l e v e{ / * * *I D * / p r i v a t ei n ti d=0 ; / * * *N o md el ' l v e * / p r i v a t eS t r i n gn o m=" " ; / * * *P r n o md el ' l v e * / p r i v a t eS t r i n gp r e n o m=" " ;

/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / /C O N S T R U C T E U RD EL ' O B J E T / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / * * *@ p a r a mi d *@ p a r a mn o m *@ p a r a mp r e n o m * / p u b l i cE l e v e ( i n ti d ,S t r i n gn o m ,S t r i n gp r e n o m ){ t h i s . i d=i d ; t h i s . n o m=n o m ; t h i s . p r e n o m=p r e n o m ; } p u b l i cE l e v e ( ) { } ; / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / /A C C E S S E U R SE TM U T A T E U R S / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / * * *@ r e t u r nt h ei d * / p u b l i ci n tg e t I d ( ){ r e t u r ni d ; }

/ * *

*@ p a r a mi dt h ei dt os e t * / p u b l i cv o i ds e t I d ( i n ti d ){ t h i s . i d=i d ; } / * * *@ r e t u r nt h en o m * / p u b l i cS t r i n gg e t N o m ( ){ r e t u r nn o m ; } / * * *@ p a r a mn o mt h en o mt os e t * / p u b l i cv o i ds e t N o m ( S t r i n gn o m ){ t h i s . n o m=n o m ; } / * * *@ r e t u r nt h ep r e n o m * / p u b l i cS t r i n gg e t P r e n o m ( ){ r e t u r np r e n o m ; } / * * *@ p a r a mp r e n o mt h ep r e n o mt os e t * / p u b l i cv o i ds e t P r e n o m ( S t r i n gp r e n o m ){ t h i s . p r e n o m=p r e n o m ; } }

Classe Matiere.java
p a c k a g ec o m . s d z . b e a n ; p u b l i cc l a s sM a t i e r e{ / * * *I D * / p r i v a t ei n ti d=0 ; / * * *N o md up r o f e s s e u r * / p r i v a t eS t r i n gn o m=" " ;

/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / /C O N S T R U C T E U RD EL ' O B J E T / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / * * *@ p a r a mi d *@ p a r a mn o m * / p u b l i cM a t i e r e ( i n ti d ,S t r i n gn o m ){ t h i s . i d=i d ; t h i s . n o m=n o m ; } p u b l i cM a t i e r e ( ) { }

/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / /A C C E S S E U R SE TM U T A T E U R S / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / * * *@ r e t u r nt h ei d * / p u b l i ci n tg e t I d ( ){ r e t u r ni d ; } / * * *@ p a r a mi dt h ei dt os e t * / p u b l i cv o i ds e t I d ( i n ti d ){ t h i s . i d=i d ; } / * * *@ r e t u r nt h en o m * / p u b l i cS t r i n gg e t N o m ( ){ r e t u r nn o m ; } / * * *@ p a r a mn o mt h en o mt os e t * / p u b l i cv o i ds e t N o m ( S t r i n gn o m ){ t h i s . n o m=n o m ; } }

Classe Professeur.java

p a c k a g ec o m . s d z . b e a n ; i m p o r tj a v a . u t i l . H a s h S e t ; i m p o r tj a v a . u t i l . S e t ; p u b l i cc l a s sP r o f e s s e u r{ / * * *I D * / p r i v a t ei n ti d=0 ; / * * *N o md up r o f e s s e u r * / p r i v a t eS t r i n gn o m=" " ; / * * *P r n o md up r o f e s s e u r * / p r i v a t eS t r i n gp r e n o m=" " ; / * * *L i s t ed e sm a t i r e sd i s p e n s e s * / p r i v a t eS e t < M a t i e r e >l i s t M a t i e r e=n e wH a s h S e t < M a t i e r e > ( ) ;

/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / /C O N S T R U C T E U RD EL ' O B J E T / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / * * *@ p a r a mi d *@ p a r a mn o m *@ p a r a mp r e n o m * / p u b l i cP r o f e s s e u r ( i n ti d ,S t r i n gn o m ,S t r i n gp r e n o m ){ t h i s . i d=i d ; t h i s . n o m=n o m ; t h i s . p r e n o m=p r e n o m ; } p u b l i cP r o f e s s e u r ( ) { } / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / /A C C E S S E U R SE TM U T A T E U R S / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / * * *@ r e t u r nt h ei d * / p u b l i ci n tg e t I d ( ){

r e t u r ni d ; } / * * *@ p a r a mi dt h ei dt os e t * / p u b l i cv o i ds e t I d ( i n ti d ){ t h i s . i d=i d ; } / * * *@ r e t u r nt h en o m * / p u b l i cS t r i n gg e t N o m ( ){ r e t u r nn o m ; } / * * *@ p a r a mn o mt h en o mt os e t * / p u b l i cv o i ds e t N o m ( S t r i n gn o m ){ t h i s . n o m=n o m ; } / * * *@ r e t u r nt h ep r e n o m * / p u b l i cS t r i n gg e t P r e n o m ( ){ r e t u r np r e n o m ; } / * * *@ p a r a mp r e n o mt h ep r e n o mt os e t * / p u b l i cv o i ds e t P r e n o m ( S t r i n gp r e n o m ){ t h i s . p r e n o m=p r e n o m ; } / * * *@ r e t u r nt h el i s t M a t i e r e * / p u b l i cS e t < M a t i e r e >g e t L i s t M a t i e r e ( ){ r e t u r nl i s t M a t i e r e ; } / * * *@ p a r a ml i s t M a t i e r et h el i s t M a t i e r et os e t * / p u b l i cv o i ds e t L i s t M a t i e r e ( S e t < M a t i e r e >l i s t M a t i e r e ){ t h i s . l i s t M a t i e r e=l i s t M a t i e r e ; } / * * *A j o u t eu n em a t i r el al i s t ed e sc o u r sd i s p e n s s *@ p a r a mM a t i e r e

* / p u b l i cv o i da d d M a t i e r e ( M a t i e r em a t i e r e ) { t h i s . l i s t M a t i e r e . a d d ( m a t i e r e ) ; } / * * *R e t i r eu n em a t i r ed el al i s t ed e sc o u r sd i s p e n s s *@ p a r a mM a t i e r e * / p u b l i cv o i dr e m o v e M a t i e r e ( M a t i e r em a t i e r e ) { t h i s . l i s t M a t i e r e . r e m o v e ( m a t i e r e ) ; } }

Classe Classe.java
p a c k a g ec o m . s d z . b e a n ; i m p o r tj a v a . u t i l . A r r a y L i s t ; i m p o r tj a v a . u t i l . H a s h S e t ; i m p o r tj a v a . u t i l . L i s t ; i m p o r tj a v a . u t i l . S e t ; p u b l i cc l a s sC l a s s e{

/ * * *I D * / p r i v a t ei n ti d=0 ; / * * *N o md up r o f e s s e u r * / p r i v a t eS t r i n gn o m=" " ; / * * *L i s t ed e sp r o f e s s e u r s * / p r i v a t eS e t < P r o f e s s e u r >l i s t P r o f e s s e u r=n e wH a s h S e t < P r o f e s s e u r > ( ) ; / * * *L i s t ed e s l v e s * / p r i v a t eS e t < E l e v e >l i s t E l e v e=n e wH a s h S e t < E l e v e > ( ) ;

/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / /C O N S T R U C T E U RD EL ' O B J E T / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / * *

*@ p a r a mi d *@ p a r a mn o m * / p u b l i cC l a s s e ( i n ti d ,S t r i n gn o m ){ t h i s . i d=i d ; t h i s . n o m=n o m ; } p u b l i cC l a s s e ( ) { }

/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / /A C C E S S E U R SE TM U T A T E U R S / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / * * *@ r e t u r nt h ei d * / p u b l i ci n tg e t I d ( ){ r e t u r ni d ; } / * * *@ p a r a mi dt h ei dt os e t * / p u b l i cv o i ds e t I d ( i n ti d ){ t h i s . i d=i d ; } / * * *@ r e t u r nt h en o m * / p u b l i cS t r i n gg e t N o m ( ){ r e t u r nn o m ; } / * * *@ p a r a mn o mt h en o mt os e t * / p u b l i cv o i ds e t N o m ( S t r i n gn o m ){ t h i s . n o m=n o m ; } / * * *@ r e t u r nt h el i s t M a t i e r e * / p u b l i cS e t < P r o f e s s e u r >g e t L i s t P r o f e s s e u r ( ){ r e t u r nl i s t P r o f e s s e u r ; } / * * *@ p a r a ml i s t M a t i e r et h el i s t M a t i e r et os e t * /

p u b l i cv o i ds e t L i s t P r o f e s s e u r ( S e t < P r o f e s s e u r >l i s t P r o f e s s e u r ){ t h i s . l i s t P r o f e s s e u r=l i s t P r o f e s s e u r ; }

/ * * *@ r e t u r nt h el i s t M a t i e r e * / p u b l i cv o i da d d P r o f e s s e u r ( P r o f e s s e u rp r o f ){ i f ( ! l i s t P r o f e s s e u r . c o n t a i n s ( p r o f ) ) l i s t P r o f e s s e u r . a d d ( p r o f ) ; } / * * *@ p a r a ml i s t M a t i e r et h el i s t M a t i e r et os e t * / p u b l i cv o i dr e m o v e P r o f e s s e u r ( P r o f e s s e u rp r o f){ t h i s . l i s t P r o f e s s e u r . r e m o v e ( p r o f ) ; }

/ * * *@ r e t u r nt h el i s t M a t i e r e * / p u b l i cS e t < E l e v e >g e t L i s t E l e v e ( ){ r e t u r nl i s t E l e v e ; } / * * *@ p a r a ml i s t M a t i e r et h el i s t M a t i e r et os e t * / p u b l i cv o i ds e t L i s t E l e v e ( S e t < E l e v e >l i s t E l e v e ){ t h i s . l i s t E l e v e=l i s t E l e v e ; } / * * *A j o u t eu n l v el ac l a s s e *@ p a r a me l e v e * / p u b l i cv o i da d d E l e v e ( E l e v ee l e v e ) { i f ( ! t h i s . l i s t E l e v e . c o n t a i n s ( e l e v e ) ) t h i s . l i s t E l e v e . a d d ( e l e v e ) ; } / * * *R e t i r eu n l v ed el ac l a s s e *@ p a r a me l e v e * / p u b l i cv o i dr e m o v e E l e v e ( E l e v ee l e v e ) { t h i s . l i s t E l e v e . r e m o v e ( e l e v e ) ;

} / * * *M t h o d ee q u a l s *@ p a r a mc l s *@ r e t u r n * / p u b l i cb o o l e a ne q u a l s ( C l a s s ec l s ) { r e t u r nt h i s . g e t I d ( )= =c l s . g e t I d ( ) ; } }

Voil, vous avez vos objets tout beaux tout propres ! Nous avons des objets prts l'emploi. Maintenant, comment faire en sorte que ces objets puissent recevoir les donnes de notre base ? Au lieu de faire des essais ttons, nous allons dfinir le pattern DAO et voir comment il fonctionne avant de l'implmenter.

Le pattern DAO : dfinition


Contexte
Vous avez des donnes srialises dans une base de donnes et vous souhaitez y accder et les manipuler avec des objets Java. Cependant, votre entreprise est en pleine restructuration et vous ne savez pas si vos donnes vont : rester o elles sont ; migrer sur une autre base de donnes ; tre stockes dans des fichiers XML ; ... Comment faire en sorte de ne pas avoir modifier toutes les utilisations de nos objets ? Comment faire un systme adaptatif aux futures modifications de supports de donnes ? Comment faire en sorte que les objets que nous allons utiliser restent tels qu'ils sont ? Il pourrait y avoir beaucoup de problmatiques de ce genre, mais le pattern DAO est l pour vous ! :magicien: La dfinition d'un design pattern est toujours un peu pompeuse et mystifie ; par contre, et ceux qui ont lu les chapitres concernant les design patterns du tuto Java le confirmeront, ils apportent plus de souplesse et de robustesse vos programmes !

Le pattern DAO
Ce pattern permet de faire le lien entre la couche d'accs aux donnes et la couche mtier d'une application. Il permet de mieux matriser les changements susceptibles d'tre oprs sur le systme de stockage des donnes, donc, par extension, de prparer une migration d'un systme un autre (BDD vers fichiers XML par exemple...). Ceci se fait en sparant accs aux donnes (BDD) et objets mtiers (POJO). Je me doute que tout ceci doit vous sembler trs flou !

Euh... un peu... :euh: C'est normal, mais ne vous en faites pas, je vais tout vous expliquer... Dj, il y a une histoire de sparation des "couches mtiers et couches d'accs aux donnes". Il s'agit ni plus ni moins de faire en sorte qu'un type d'objet se charge de rcuprer les donnes dans la base et qu'un autre type d'objet (souvent des POJO) soit utilis pour manipuler ces donnes. Schmatiquement, a nous donne :

Si on comprend bien, nous allons avoir deux types d'objets !

Tout fait. Les objets que nous avons crs plus haut sont nos POJO, les objets utiliss par le programme pour manipuler les donnes de la base. Il ne nous reste plus qu' crer les objets qui vont rechercher les donnes dans la base ! Oui, mais nous n'allons pas faire n'importe comment... Les dits objets devront tre capables de faire des recherches, des insertions, des mises jour et des suppressions ! Par consquent, nous pouvons dfinir un super type d'objet afin d'utiliser au mieux le polymorphisme... Nous allons devoir crer une classe abstraite (ou une interface) mettant en oeuvre toutes les mthodes sus-mentionnes ! Comment va-t-on faire pour demander nos objets DAO de rcuprer tel type d'objet ou d'en srialiser tel autre ? Avec des cast ? Soit en castant, soit en faisant une classe gnrique ! Comme ceci :

Ah... mais oui ! Vous aviez oubli que nous pouvions crer des classes gnriques ? :colere2: Bon, je vous pardonne. Maintenant, voyons un peu les codes sources de ces objets :

Classe DAO.java

p a c k a g ec o m . s d z . d a o ; i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tc o m . s d z . c o n n e c t i o n . S d z C o n n e c t i o n ; p u b l i ca b s t r a c tc l a s sD A O < T >{ p r o t e c t e dC o n n e c t i o nc o n n e c t=n u l l ; / * * *C o n s t r u c t e u r *@ p a r a mc o n n * / p u b l i cD A O ( C o n n e c t i o nc o n n ) { t h i s . c o n n e c t=c o n n ; } / * * *M t h o d ed ec r a t i o n *@ p a r a mo b j *@ r e t u r n * / p u b l i ca b s t r a c tb o o l e a nc r e a t e ( To b j ) ; / * * *M t h o d ep o u re f f a c e r *@ p a r a mo b j *@ r e t u r n * / p u b l i ca b s t r a c tb o o l e a nd e l e t e ( To b j ) ; / * * *M t h o d ed em i s ej o u r *@ p a r a mo b j *@ r e t u r n * / p u b l i ca b s t r a c tb o o l e a nu p d a t e ( To b j ) ; / * * *M t h o d ed er e c h e r c h ed e si n f o r m a t i o n s *@ p a r a mi d *@ r e t u r n * / p u b l i ca b s t r a c tTf i n d ( i n ti d ) ; }

Classe EleveDAO.java
p a c k a g ec o m . s d z . d a o . i m p l e m e n t ; i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . R e s u l t S e t ;

i m p o r tj a v a . s q l . S Q L E x c e p t i o n ; i m p o r tc o m . s d z . b e a n . E l e v e ; i m p o r tc o m . s d z . d a o . D A O ; p u b l i cc l a s sE l e v e D A Oe x t e n d sD A O < E l e v e >{ p u b l i cE l e v e D A O ( C o n n e c t i o nc o n n ){ s u p e r ( c o n n ) ; } p u b l i cb o o l e a nc r e a t e ( E l e v eo b j ){ r e t u r nf a l s e ; } p u b l i cb o o l e a nd e l e t e ( E l e v eo b j ){ r e t u r nf a l s e ; } p u b l i cE l e v ef i n d ( i n ti d ){ E l e v ee l e v e=n e wE l e v e ( ) ; t r y{ R e s u l t S e tr e s u l t=t h i s . c o n n e c t R e s u l t S e t . T Y P E _ S C R O L L _ I N S E N S I T I V E , R e s u l t S e t . C O N C U R _ R E A D _ O N L Y ) . e x e c u t e Q u e r y ( " S E L E C T*F R O Me l e v eW H E R Ee l v _ i d="+i d ) ; i f ( r e s u l t . f i r s t ( ) ) e l e v e=n e wE l e v e ( i d ,r e s u l t . g e t S t r i n g ( " e l v _ n o m " ) ,r e s u l t . g e t S t r i n g ( " e l v _ p r e n o m " ) ) ; }c a t c h( S Q L E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } r e t u r ne l e v e ; } p u b l i cb o o l e a nu p d a t e ( E l e v eo b j ){ r e t u r nf a l s e ; } } . c r e a t e S t a t e m e n t (

Classe MatiereDAO.java
p a c k a g ec o m . s d z . d a o . i m p l e m e n t ; i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . R e s u l t S e t ; i m p o r tj a v a . s q l . S Q L E x c e p t i o n ; i m p o r tc o m . s d z . b e a n . E l e v e ; i m p o r tc o m . s d z . b e a n . M a t i e r e ; i m p o r tc o m . s d z . d a o . D A O ; p u b l i cc l a s sM a t i e r e D A Oe x t e n d sD A O < M a t i e r e >{ p u b l i cM a t i e r e D A O ( C o n n e c t i o nc o n n ){ s u p e r ( c o n n ) ; }

p u b l i cb o o l e a nc r e a t e ( M a t i e r eo b j ){ r e t u r nf a l s e ; }

p u b l i cb o o l e a nd e l e t e ( M a t i e r eo b j ){ r e t u r nf a l s e ; }

p u b l i cM a t i e r ef i n d ( i n ti d ){ M a t i e r em a t i e r e=n e wM a t i e r e ( ) ; t r y{ R e s u l t S e tr e s u l t=t h i s . c o n n e c t R e s u l t S e t . T Y P E _ S C R O L L _ I N S E N S I T I V E , R e s u l t S e t . C O N C U R _ R E A D _ O N L Y ) . e x e c u t e Q u e r y ( " S E L E C T*F R O Mm a t i e r eW H E R Em a t _ i d="+i d ) ; i f ( r e s u l t . f i r s t ( ) ) m a t i e r e=n e wM a t i e r e ( i d ,r e s u l t . g e t S t r i n g ( " m a t _ n o m " ) ) ; . c r e a t e S t a t e m e n t (

}c a t c h( S Q L E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } r e t u r nm a t i e r e ; }

p u b l i cb o o l e a nu p d a t e ( M a t i e r eo b j ){ r e t u r nf a l s e ; } }

Classe ProfesseurDAO.java
p a c k a g ec o m . s d z . d a o . i m p l e m e n t ; i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . R e s u l t S e t ; i m p o r tj a v a . s q l . S Q L E x c e p t i o n ; i m p o r tc o m . s d z . b e a n . E l e v e ; i m p o r tc o m . s d z . b e a n . P r o f e s s e u r ; i m p o r tc o m . s d z . d a o . D A O ; p u b l i cc l a s sP r o f e s s e u r D A Oe x t e n d sD A O < P r o f e s s e u r >{ p u b l i cP r o f e s s e u r D A O ( C o n n e c t i o nc o n n ){ s u p e r ( c o n n ) ; } p u b l i cb o o l e a nc r e a t e ( P r o f e s s e u ro b j ){ r e t u r nf a l s e ; }

p u b l i cb o o l e a nd e l e t e ( P r o f e s s e u ro b j ){ r e t u r nf a l s e ; }

p u b l i cP r o f e s s e u rf i n d ( i n ti d ){ P r o f e s s e u rp r o f e s s e u r=n e wP r o f e s s e u r ( ) ; t r y{ R e s u l t S e tr e s u l t=t h i s . c o n n e c t . c r e a t e S t a t e m e n t (

R e s u l t S e t . T Y P E _ S C R O L L _ I N S E N S I T I V E , R e s u l t S e t . C O N C U R _ R E A D _ O N L Y ) . e x e c u t e Q u e r y ( " s e l e c t*f r o mp r o f e s s e u r" + " l e f tj o i nj _ m a t _ p r o fo nj m p _ p r o f _ k=p r o f _ i dA N Dp r o f _ i d=" +i d+ "i n n e rj o i nm a t i e r eo nj m p _ m a t _ k=m a t _ i d " ) ; i f ( r e s u l t . f i r s t ( ) ) { p r o f e s s e u r=n e wP r o f e s s e u r ( i d ,r e s u l t . g e t S t r i n g ( " p r o f _ n o m " ) ,r e s u l t . g e t S t r i n g ( " p r o f _ p r e n o m " ) ) ; r e s u l t . b e f o r e F i r s t ( ) ; M a t i e r e D A Om a t D a o=n e wM a t i e r e D A O ( t h i s . c o n n e c t ) ; w h i l e ( r e s u l t . n e x t ( ) ) p r o f e s s e u r . a d d M a t i e r e ( m a t D a o . f i n d ( r e s u l t . g e t I n t ( " m a t _ i d " ) ) ) ; } }c a t c h( S Q L E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } r e t u r np r o f e s s e u r ; }

p u b l i cb o o l e a nu p d a t e ( P r o f e s s e u ro b j ){ r e t u r nf a l s e ; } }

Classe ClasseDAO.java
p a c k a g ec o m . s d z . d a o . i m p l e m e n t ; i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tj a v a . s q l . R e s u l t S e t ; i m p o r tj a v a . s q l . S Q L E x c e p t i o n ; i m p o r tc o m . s d z . b e a n . C l a s s e ; i m p o r tc o m . s d z . b e a n . E l e v e ; i m p o r tc o m . s d z . d a o . D A O ; p u b l i cc l a s sC l a s s e D A Oe x t e n d sD A O < C l a s s e >{

p u b l i cC l a s s e D A O ( C o n n e c t i o nc o n n ){ s u p e r ( c o n n ) ; } p u b l i cb o o l e a nc r e a t e ( C l a s s eo b j ){ r e t u r nf a l s e ; }

p u b l i cb o o l e a nd e l e t e ( C l a s s eo b j ){ r e t u r nf a l s e ; }

p u b l i cC l a s s ef i n d ( i n ti d ){ C l a s s ec l a s s e=n e wC l a s s e ( ) ; t r y{ R e s u l t S e tr e s u l t=t h i s . c o n n e c t R e s u l t S e t . T Y P E _ S C R O L L _ I N S E N S I T I V E , R e s u l t S e t . C O N C U R _ R E A D _ O N L Y ) . e x e c u t e Q u e r y ( " s e l e c t*f r o mc l a s s eW H E R Ec l s _ i d="+i d ) ; . c r e a t e S t a t e m e n t (

i f ( r e s u l t . f i r s t ( ) ) { c l a s s e=n e wC l a s s e ( i d ,r e s u l t . g e t S t r i n g ( " c l s _ n o m " ) ) ; r e s u l t=t h i s . c o n n e c t Q u e r y ( " s e l e c tp r o f _ i d ,p r o f _ n o m ,p r o f _ p r e n o mf r o mp r o f e s s e u r"+ " I N N E RJ O I Nj _ m a t _ p r o fo np r o f _ i d=j m p _ p r o f _ k"+ " I N N E RJ O I Nj _ c l s _ j m po nj m p _ i d=j c m _ j m p _ kA N Dj c m _ c l s _ k="+i d ) ; P r o f e s s e u r D A Op r o f D a o=n e wP r o f e s s e u r D A O ( t h i s . c o n n e c t ) ; . c r e a t e S t a t e m e n t ( ) . e x e c u t e

w h i l e ( r e s u l t . n e x t ( ) ) c l a s s e . a d d P r o f e s s e u r ( p r o f D a o . f i n d ( r e s u l t . g e t I n t ( " p r o f _ i d " ) ) ) ; E l e v e D A Oe l e v e D a o=n e wE l e v e D A O ( t h i s . c o n n e c t ) ;

r e s u l t=t h i s . c o n n e c t Q u e r y ( " s e l e c te l v _ i d ,e l v _ n o m ,e l v _ p r e n o mf r o me l e v e"+ " I N N E RJ O I Nc l a s s eo ne l v _ c l s _ k=c l s _ i dA N Dc l s _ i d="+i d

. c r e a t e S t a t e m e n t ( ) . e x e c u t e

) ; w h i l e ( r e s u l t . n e x t ( ) ) c l a s s e . a d d E l e v e ( e l e v e D a o . f i n d ( r e s u l t . g e t I n t ( " e l v _ i d " ) ) ) ; } }c a t c h( S Q L E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; } r e t u r nc l a s s e ; }

p u b l i cb o o l e a nu p d a t e ( C l a s s eo b j ){ r e t u r nf a l s e ; } }

Pour ne pas compliquer la tche, je n'ai dtaill que la mthode de recherche des donnes, les autres sont des coquilles vides... Mais vous devriez tre capables de faire a tout seuls, normalement...

Premier test
Bon : nous avons ralis une bonne partie de ce pattern, nous allons pouvoir faire notre premier test. :) Une bonne partie ? Tu veux dire qu'il y a encore des choses faire ?

Oui, nous verrons a dans le prochain chapitre : pour le moment, testons ce que nous avons. Par contre, je tiens prciser que j'utilise toujours le singleton cr quelques chapitres plus haut ! Voici un code de test :
i m p o r tc o m . s d z . b e a n . C l a s s e ; i m p o r tc o m . s d z . b e a n . E l e v e ; i m p o r tc o m . s d z . b e a n . M a t i e r e ; i m p o r tc o m . s d z . b e a n . P r o f e s s e u r ; i m p o r tc o m . s d z . c o n n e c t i o n . S d z C o n n e c t i o n ; i m p o r tc o m . s d z . d a o . D A O ; i m p o r tc o m . s d z . d a o . i m p l e m e n t . C l a s s e D A O ; i m p o r tc o m . s d z . d a o . i m p l e m e n t . E l e v e D A O ; i m p o r tc o m . s d z . d a o . i m p l e m e n t . P r o f e s s e u r D A O ;

p u b l i cc l a s sF i r s t T e s t{ p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ){ / / t e s t o n sd e s l v e s D A O < E l e v e >e l e v e D a o=n e wE l e v e D A O ( S d z C o n n e c t i o n . g e t I n s t a n c e ( ) ) ; f o r ( i n ti=1 ;i<5 ;i + + ) { E l e v ee l e v e=e l e v e D a o . f i n d ( i ) ; S y s t e m . o u t . p r i n t l n ( " E l v eN "+e l e v e . g e t I d ( )+" -"+e l e v e . g e t N o m ( )+""+e l e v e . g e t P r e n o m ( ) ) ; } S y s t e m . o u t . p r i n t l n ( " \ n * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ n " ) ; / / V o y o n sv o i rl e sp r o f e s s e u r s D A O < P r o f e s s e u r >p r o f D a o=n e wP r o f e s s e u r D A O ( S d z C o n n e c t i o n . g e t I n s t a n c e ( ) ) ; f o r ( i n ti=4 ;i<8 ;i + + ) { P r o f e s s e u rp r o f=p r o f D a o . f i n d ( i ) ; S y s t e m . o u t . p r i n t l n ( p r o f . g e t N o m ( )+""+p r o f . g e t P r e n o m ( )+"e n s e i g n e:" ) ; f o r ( M a t i e r em a t:p r o f . g e t L i s t M a t i e r e ( ) ) S y s t e m . o u t . p r i n t l n ( " \ t*"+m a t . g e t N o m ( ) ) ; } S y s t e m . o u t . p r i n t l n ( " \ n * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ n " ) ; / / E tl ,c ' e s tl ac l a s s e D A O < C l a s s e >c l a s s e D a o=n e wC l a s s e D A O ( S d z C o n n e c t i o n . g e t I n s t a n c e ( ) ) ; C l a s s ec l a s s e=c l a s s e D a o . f i n d ( 1 1 ) ; S y s t e m . o u t . p r i n t l n ( " C l a s s ed e"+c l a s s e . g e t N o m ( ) ) ; S y s t e m . o u t . p r i n t l n ( " \ n L i s t ed e s l v e s: " ) ;

f o r ( E l e v ee l e v e:c l a s s e . g e t L i s t E l e v e ( ) ) S y s t e m . o u t . p r i n t l n ( " -"+e l e v e . g e t N o m ( )+""+e l e v e . g e t P r e n o m ( ) ) ; S y s t e m . o u t . p r i n t l n ( " \ n L i s t ed e sp r o f e s s e u r s: " ) ; f o r ( P r o f e s s e u rp r o f:c l a s s e . g e t L i s t P r o f e s s e u r ( ) ) S y s t e m . o u t . p r i n t l n ( " -"+p r o f . g e t N o m ( )+""+p r o f . g e t P r e n o m ( ) ) ; } }

Qui me donne :

Vous avez compris comment tout a fonctionnait ? Ce n'est pas trs dur en fin de compte. Je vous laisse quelques instants pour lire, tester, relire, tester nouveau... Nous utilisons des objets spcifiques afin de rechercher dans la base des donnes qui nous servent instancier des objets Java habituels. :) Avant de poursuivre, nous allons faire un tour du ct du QCM...

Bon, vous voyez un peu comment on va procder. Le truc, c'est que vous savez comment rcuprer les donnes de votre base pour les utiliser dans des POJO, mais nous n'avons pas vu comment permettre l'utilisation de plusieurs systmes de base de donnes, voire mme de l'XML. Ne prenez pas peur, le rsultat sera la hauteur de vos attentes... Mme si ne connaissez rien Java ni XML (pour l'instant...). ;)

Le pattern DAO (2/2)


Dans ce chapitre, nous allons voir comment peaufiner le pattern DAO afin que celui-ci puisse s'adapter d'autres systmes de sauvegarde... Le but du jeu tant d'avoir le moins possible de changements le cas chant !

Le pattern factory
Nous allons aborder ici une notion importante : la fabrication d'objets ! En effet, le pattern DAO implmente aussi ce qu'on appelle le pattern factory. Celui-ci consiste dlguer l'instanciation d'objets une classe. En fait, une fabrique ne fait que a ! ^^ En gnral, lorsque vous voyez ce genre de code dans une classe :
c l a s sA { p u b l i cO b j e c tg e t D a t a ( i n tt y p e ) { O b j e c to b j ; / / i f ( t y p e= =0 ) o b j=n e wB ( ) ; e l s ei f ( t y p e= =1 ) o b j=n e wC ( ) ; e l s e o b j=n e wD ( ) ; / / o b j . d o S o m e t h i n g ( ) ; o b j . d o S o m e t h i n g E l s e ( ) ; } }

vous constatez qu'il y a une cration d'objet et que ceci est conditionn par une variable. En fait, selon celle-ci, l'objet instanci n'est pas le mme. Nous allons donc extraire ce code (celui entre commentaires) pour le mettre dans une classe part :

p a c k a g ec o m . s d z . t r a n s a c t ; p u b l i cc l a s sF a c t o r y{ p u b l i cs t a t i cO b j e c tg e t D a t a ( i n tt y p e ) { i f ( t y p e= =0 ) r e t u r nn e wB ( ) ; e l s ei f ( t y p e= =1 ) r e t u r nn e wC ( ) ; e l s e r e t u r nn e wD ( ) ; } }

Du coup, maintenant, lorsque nous voudrons instancier les objets de la fabrique, nous utiliserons celle-ci. Comme a :
Bb=F a c t o r y . g e t D a t a ( 0 ) ; Cc=F a c t o r y . g e t D a t a ( 1 ) ; / / . . .

Pourquoi faire tout ce ramdam ? Quel est le problme avec nos instances ? C'est simple : en temps normal, nous travaillons avec des objets concrets, non soumis au changement. Cependant, dans le cas qui nous intresse, nos objets peuvent tre amens changer et j'irais mme plus loin : le type d'objet utilis peut changer ! L'avantage d'utiliser une fabrique, c'est que les instances concrtes (utilisation du mot cl new) se fait UN SEUL ENDROIT ! Donc, si nous devons faire des changements, il ne se feront qu' un seul endroit ! Si nous ajoutons un paramtre dans le constructeur, par exemple... D'accord, on commence comprendre l'intrt de cette fabrique. Je savais que vous comprendriez vite. je vous propose maintenant de voir comment ce pattern est implment dans le pattern DAO.

Fabriquer vos DAO


En fait, la factory dans le pattern DAO sert construire nos instances d'objets d'accs aux donnes. Du coup, vu que nous avons un super-type d'objet pour ces objets, nous savons quel type d'objet va retourner notre fabrique.

Voici le code de notre fabrique :

p a c k a g ec o m . s d z . d a o ; i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tc o m . s d z . c o n n e c t i o n . S d z C o n n e c t i o n ; i m p o r tc o m . s d z . d a o . i m p l e m e n t . C l a s s e D A O ; i m p o r tc o m . s d z . d a o . i m p l e m e n t . E l e v e D A O ; i m p o r tc o m . s d z . d a o . i m p l e m e n t . M a t i e r e D A O ; i m p o r tc o m . s d z . d a o . i m p l e m e n t . P r o f e s s e u r D A O ; p u b l i cc l a s sD A O F a c t o r y{ p r o t e c t e ds t a t i cf i n a lC o n n e c t i o nc o n n=S d z C o n n e c t i o n . g e t I n s t a n c e ( ) ; / * * *R e t o u r n eu no b j e tC l a s s ei n t e r a g i s s a n ta v e cl aB D D *@ r e t u r n * / p u b l i cs t a t i cD A Og e t C l a s s e D A O ( ) { r e t u r nn e wC l a s s e D A O ( c o n n ) ; } / * * *R e t o u r n eu no b j e tP r o f e s s e u ri n t e r a g i s s a n ta v e cl aB D D *@ r e t u r n * / p u b l i cs t a t i cD A Og e t P r o f e s s e u r D A O ( ) { r e t u r nn e wP r o f e s s e u r D A O ( c o n n ) ; } / * * *R e t o u r n eu no b j e tE l e v ei n t e r a g i s s a n ta v e cl aB D D *@ r e t u r n * / p u b l i cs t a t i cD A Og e t E l e v e D A O ( ) { r e t u r nn e wE l e v e D A O ( c o n n ) ; } / * * *R e t o u r n eu no b j e tM a t i e r ei n t e r a g i s s a n ta v e cl aB D D *@ r e t u r n * / p u b l i cs t a t i cD A Og e t M a t i e r e D A O ( ) { r e t u r nn e wM a t i e r e D A O ( c o n n ) ; } }

Et voici un code qui devrait vous plaire :


i m p o r tc o m . s d z . b e a n . C l a s s e ; i m p o r tc o m . s d z . b e a n . E l e v e ; i m p o r tc o m . s d z . b e a n . M a t i e r e ; i m p o r tc o m . s d z . b e a n . P r o f e s s e u r ;

i m p o r tc o m . s d z . d a o . D A O ; i m p o r tc o m . s d z . d a o . D A O F a c t o r y ;

p u b l i cc l a s sT e s t D A O{ / * * *@ p a r a ma r g s * / p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ){ S y s t e m . o u t . p r i n t l n ( " " ) ; / / / / O nv ar e c h e r c h e rd e s l v e s / / / / O nr c u p r eu no b j e tf a i s a n tl el i e ne n t r el ab a s ee tn o so b j e t s D A O < E l e v e >e l e v e D a o=D A O F a c t o r y . g e t E l e v e D A O ( ) ;

f o r ( i n ti=1 ;i<5 ;i + + ) { / / O nf a i tn o t r er e c h e r c h e E l e v ee l e v e=e l e v e D a o . f i n d ( i ) ; S y s t e m . o u t . p r i n t l n ( " \ t E L E V EN "+e l e v e . g e t I d ( )+"-N O M:"+ e l e v e . g e t N o m ( )+"-P R E N O M:"+e l e v e . g e t P r e n o m ( ) ) ; } S y s t e m . o u t . p r i n t l n ( " \ n \ t * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * " ) ; / / O nf a i td em m ep o u ru n ec l a s s e D A O < C l a s s e >c l a s s e D a o=D A O F a c t o r y . g e t C l a s s e D A O ( ) ; / / O nc h e r c h el ac l a s s ea y a n tp o u rI D1 0 C l a s s ec l a s s e=c l a s s e D a o . f i n d ( 1 0 ) ; S y s t e m . o u t . p r i n t l n ( " \ t C L A S S ED E"+c l a s s e . g e t N o m ( ) ) ; / / O nr c u p r el al i s t ed e s l v e s S y s t e m . o u t . p r i n t l n ( " \ n \ t C e l l e c ic o n t i e n t"+c l a s s e . g e t L i s t E l e v e ( ) . s i z e ( )+" l v e ( s ) " ) ; f o r ( E l e v ee l e v e:c l a s s e . g e t L i s t E l e v e ( ) ) S y s t e m . o u t . p r i n t l n ( " \ t \ t-"+e l e v e . g e t N o m ( )+""+e l e v e . g e t P r e n o m ( ) ) ;

/ / A i n s iq u el al i s t ed e sp r o f e s s e u r s S y s t e m . o u t . p r i n t l n ( " \ n \ t C e l l e c ia"+c l a s s e . g e t L i s t P r o f e s s e u r ( ) . s i z e ( ) +"p r o f e s s e u r ( s ) " ) ; f o r ( P r o f e s s e u rp r o f:c l a s s e . g e t L i s t P r o f e s s e u r ( ) ) { S y s t e m . o u t . p r i n t l n ( " \ t \ t-M r"+p r o f . g e t N o m ( )+""+p r o f . g e t

P r e n o m ( )+"p r o f e s s e u rd e: " ) ; / / T a n tq u ' f a i r e ,o np r e n da u s s il e sm a t i r e s . . .^ ^ f o r ( M a t i e r em a t:p r o f . g e t L i s t M a t i e r e ( ) ) S y s t e m . o u t . p r i n t l n ( " \ t \ t \ t*"+m a t . g e t N o m ( ) ) ; } S y s t e m . o u t . p r i n t l n ( " \ n \ t * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * " ) ; / / U np e t i te s s a is u rl e sm a t i r e s D A O < M a t i e r e >m a t i e r e D a o=D A O F a c t o r y . g e t M a t i e r e D A O ( ) ; M a t i e r em a t=m a t i e r e D a o . f i n d ( 2 ) ; S y s t e m . o u t . p r i n t l n ( " \ t M A T I E R E"+m a t . g e t I d ( )+":"+m a t . g e t N o m ( ) ) ; } }

Et voil le rsultat que nous donne ce code :

Vous pouvez tre fiers de vous ! Vous venez d'implmenter le pattern DAO utilisant une fabrique. C'tait un peu effrayant, mais, au final ce n'est rien du tout... ^^

On a bien compris le principe du pattern DAO, mme la combinaison DAO - factory. Cependant, on ne voit pas comment grer plusieurs systmes de sauvegarde de donnes ? Il faut modifier les DAO chaque fois ? Non, bien sr... Le fait est que vous pouvez trs bien avoir un type de DAO pour chaque type de gestion de donnes (PostgreSQL, XML, MySQL...). Le vrai problme, c'est de savoir comment rcuprer les DAO puisque nous avons dlgu leurs instanciations une fabrique. Vous allez voir, les choses les plus compliques peuvent tre aussi les plus simples. :)

D'une usine une multinationale


Faisons le topo de ce que nous avons : des objets mtiers ; une implmentation d'accs aux donnes ; une classe permettant d'instancier les objets d'accs aux donnes. Le fait est que notre structure actuelle fonctionne pour notre systme actuel... Ah ! Mais ! Qu'entends-je, qu'oue-je ? Votre patron vient de trancher ! Vous allez utiliser PostgreSQL ET du XML ! C'est bien ce qu'on disait plus haut... Comment grer a ? On ne va pas mettre des if(){...}else{} dans la fabrique, tout de mme ? Ah ! Je vous arrte ! Vous entendez ce que vous dites : Citation : Les ZrOs

On ne va pas mettre des if(){...}else{} dans la fabrique, tout de mme ?


Vous voulez mettre des conditions afin de savoir quel type d'instance retourner : a ressemble grandement une portion de code pouvant tre dcline en fabrique ! o_O Tu veux faire des fabriques de fabriques ? ? Oui ! Notre fabrique actuelle nous permet de construire des objets accdant des donnes se trouvant sur une base de donnes PostgreSQL. Mais la problmatique maintenant est de pouvoir aussi utiliser des donnes provenant de fichiers XML... Voici un petit schma reprsentant la situation actuelle :

Et voil ce quoi on aspire :

Je pense que vous tes tous d'accord pour dire que ces deux usines ont un processus de fabrication trs similaire. Par l, j'entends que nous allons utiliser les mmes mthodes sur les objets sortant de ces deux usines. Voyez a un peu comme une grande marque de pain qui aurait beaucoup de boulangeries dans tous les pays du monde ! Cette firme a un savoir-faire vident, mais aussi des particularits : le pain ne se fait pas pareil dans tous les endroits du globe... Pour vous, c'est comme si vous passiez commande directement au sige social qui, lui, va dlguer l'usine qui permet de rpondre vos attentes ! Schmatiquement, a donne ceci :

Lorsque je vous dis a, vous devez avoir une raction quasi-immdiate : hritage - polymorphisme ! Ce qui va changer le plus, par rapport notre ancienne fabrique, c'est que nous n'utiliserons plus de mthodes statiques, mais des mthodes d'une instance concrte, et pour cause : impossible de crer une classe abstraite ou une interface avec des mthodes statiques destine la redfinition ! Donc, nous allons crer une classe abstraite pour nos futurs fabriques, celle-ci devra avoir les mthodes permettant de rcuprer les diffrents DAO ET une mthode permettant d'instancier la bonne fabrique ! Je vous ai prpar un diagramme de classe, vous verrez mieux comme a :

Je vous ai mme prpar les codes sources : Classe AbstractDAOFactory.java :

p a c k a g ec o m . s d z . d a o ;

p u b l i ca b s t r a c tc l a s sA b s t r a c t D A O F a c t o r y{ p u b l i cs t a t i cf i n a li n tD A O _ F A C T O R Y=0 ; p u b l i cs t a t i cf i n a li n tX M L _ D A O _ F A C T O R Y=1 ; / * * *R e t o u r n eu no b j e tC l a s s ei n t e r a g i s s a n ta v e cl aB D D *@ r e t u r n * / p u b l i ca b s t r a c tD A Og e t C l a s s e D A O ( ) ; / * * *R e t o u r n eu no b j e tP r o f e s s e u ri n t e r a g i s s a n ta v e cl aB D D *@ r e t u r n * / p u b l i ca b s t r a c tD A Og e t P r o f e s s e u r D A O ( ) ; / * * *R e t o u r n eu no b j e tE l e v ei n t e r a g i s s a n ta v e cl aB D D *@ r e t u r n * / p u b l i ca b s t r a c tD A Og e t E l e v e D A O ( ) ; / * * *R e t o u r n eu no b j e tM a t i e r ei n t e r a g i s s a n ta v e cl aB D D *@ r e t u r n * / p u b l i ca b s t r a c tD A Og e t M a t i e r e D A O ( ) ; / * * *M t h o d ep e r m e t t a n td er c u p r e rl e sF a c t o r y *@ p a r a mt y p e *@ r e t u r nA b s t r a c t D A O F a c t o r y * / p u b l i cs t a t i cA b s t r a c t D A O F a c t o r yg e t F a c t o r y ( i n tt y p e ) { s w i t c h ( t y p e ) { c a s eD A O _ F A C T O R Y : r e t u r nn e wD A O F a c t o r y ( ) ; c a s eX M L _ D A O _ F A C T O R Y : r e t u r nn e wX M L D A O F a c t o r y ( ) ; d e f a u l t : r e t u r nn u l l ; } } }

Classe DAOFactory.java

p a c k a g ec o m . s d z . d a o ; i m p o r tj a v a . s q l . C o n n e c t i o n ; i m p o r tc o m . s d z . c o n n e c t i o n . S d z C o n n e c t i o n ; i m p o r tc o m . s d z . d a o . i m p l e m e n t . C l a s s e D A O ; i m p o r tc o m . s d z . d a o . i m p l e m e n t . E l e v e D A O ; i m p o r tc o m . s d z . d a o . i m p l e m e n t . M a t i e r e D A O ; i m p o r tc o m . s d z . d a o . i m p l e m e n t . P r o f e s s e u r D A O ; p u b l i cc l a s sD A O F a c t o r ye x t e n d sA b s t r a c t D A O F a c t o r y { p r o t e c t e ds t a t i cf i n a lC o n n e c t i o nc o n n=S d z C o n n e c t i o n . g e t I n s t a n c e ( ) ; p u b l i cD A Og e t C l a s s e D A O ( ) { r e t u r nn e wC l a s s e D A O ( c o n n ) ; } p u b l i cD A Og e t P r o f e s s e u r D A O ( ) { r e t u r nn e wP r o f e s s e u r D A O ( c o n n ) ; } p u b l i cD A Og e t E l e v e D A O ( ) { r e t u r nn e wE l e v e D A O ( c o n n ) ; } p u b l i cD A Og e t M a t i e r e D A O ( ) { r e t u r nn e wM a t i e r e D A O ( c o n n ) ; } }

Classe XMLDAOFactory.java

p a c k a g ec o m . s d z . d a o ; p u b l i cc l a s sX M L D A O F a c t o r ye x t e n d sA b s t r a c t D A O F a c t o r y{ p u b l i cD A Og e t C l a s s e D A O ( ){ r e t u r nn u l l ; } p u b l i cD A Og e t E l e v e D A O ( ){ r e t u r nn u l l ; } p u b l i cD A Og e t M a t i e r e D A O ( ){ r e t u r nn u l l ; } p u b l i cD A Og e t P r o f e s s e u r D A O ( ){ r e t u r nn u l l ; } }

Vous devez y voir plus clair ; mme si la classe XMLDAOFactory ne fait rien du tout, vous voyez le principe de base et c'est l'important ! Nous avons maintenant une hirarchie de classes capables de travailler ensemble. :magicien: Je reprends le dernier exemple que nous avions ralis, avec un peu de modifications...
i m p o r tc o m . s d z . b e a n . C l a s s e ; i m p o r tc o m . s d z . b e a n . E l e v e ; i m p o r tc o m . s d z . b e a n . M a t i e r e ; i m p o r tc o m . s d z . b e a n . P r o f e s s e u r ; i m p o r tc o m . s d z . d a o . A b s t r a c t D A O F a c t o r y ; i m p o r tc o m . s d z . d a o . D A O ; i m p o r tc o m . s d z . d a o . D A O F a c t o r y ;

p u b l i cc l a s sT e s t D A O{ / * * *@ p a r a ma r g s * / p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ){ S y s t e m . o u t . p r i n t l n ( " " ) ; / / / / O nv ar e c h e r c h e rd e s l v e s / / A b s t r a c t D A O F a c t o r ya d f=A b s t r a c t D A O F a c t o r y . g e t F a c t o r y ( A b s t r a c t D A O F a c t o r y . D A O _ F A C T O R Y ) ; / / O nr c u p r eu no b j e tf a i s a n tl el i e ne n t r el ab a s ee tn o so b j e t s D A O < E l e v e >e l e v e D a o=a d f . g e t E l e v e D A O ( ) ;

f o r ( i n ti=1 ;i<5 ;i + + ) { / / O nf a i tn o t r er e c h e r c h e E l e v ee l e v e=e l e v e D a o . f i n d ( i ) ; S y s t e m . o u t . p r i n t l n ( " \ t E L E V EN "+e l e v e . g e t I d ( )+"-N O M:"+ e l e v e . g e t N o m ( )+"-P R E N O M:"+e l e v e . g e t P r e n o m ( ) ) ; } S y s t e m . o u t . p r i n t l n ( " \ n \ t * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * " ) ; / / O nf a i td em m ep o u ru n ec l a s s e D A O < C l a s s e >c l a s s e D a o=a d f . g e t C l a s s e D A O ( ) ; / / O nc h e r c h el ac l a s s ea y a n tp o u rI D1 0 C l a s s ec l a s s e=c l a s s e D a o . f i n d ( 1 0 ) ; S y s t e m . o u t . p r i n t l n ( " \ t C L A S S ED E"+c l a s s e . g e t N o m ( ) ) ; / / O nr c u p r el al i s t ed e s l v e s S y s t e m . o u t . p r i n t l n ( " \ n \ t C e l l e c ic o n t i e n t"+c l a s s e . g e t L i s t E l e v e ( ) . s i z e ( )+" l v e ( s ) " ) ; f o r ( E l e v ee l e v e:c l a s s e . g e t L i s t E l e v e ( ) ) S y s t e m . o u t . p r i n t l n ( " \ t \ t-"+e l e v e . g e t N o m ( )+""+e l e v e . g e t P r e n o m ( ) ) ;

/ / A i n s iq u el al i s t ed e sp r o f e s s e u r s S y s t e m . o u t . p r i n t l n ( " \ n \ t C e l l e c ia"+c l a s s e . g e t L i s t P r o f e s s e u r ( ) . s i z e ( ) +"p r o f e s s e u r ( s ) " ) ; f o r ( P r o f e s s e u rp r o f:c l a s s e . g e t L i s t P r o f e s s e u r ( ) ) { S y s t e m . o u t . p r i n t l n ( " \ t \ t-M r"+p r o f . g e t N o m ( )+""+p r o f . g e t P r e n o m ( )+"p r o f e s s e u rd e: " ) ; / / T a n tq u ' f a i r e ,o np r e n da u s s il e sm a t i r e s . . .^ ^ f o r ( M a t i e r em a t:p r o f . g e t L i s t M a t i e r e ( ) ) S y s t e m . o u t . p r i n t l n ( " \ t \ t \ t*"+m a t . g e t N o m ( ) ) ; } S y s t e m . o u t . p r i n t l n ( " \ n \ t * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * " ) ; / / U np e t i te s s a is u rl e sm a t i r e s D A O < M a t i e r e >m a t i e r e D a o=a d f . g e t M a t i e r e D A O ( ) ; M a t i e r em a t=m a t i e r e D a o . f i n d ( 2 ) ; S y s t e m . o u t . p r i n t l n ( " \ t M A T I E R E"+m a t . g e t I d ( )+":"+m a t . g e t N o m ( ) ) ; } }

Et le rsultat est le mme qu'avant ! Tout fonctionne merveille ! Ainsi, si vous voulez utiliser l'usine de fabrication XML, vous pouvez faire ceci :
A b s t r a c t D A O F a c t o r ya d f=A b s t r a c t D A O F a c t o r y . g e t F a c t o r y ( A b s t r a c t D A O F a c t o r y . X M L _ D A O _ F A C T O R Y ) ; .

Voil, vous en savez plus sur ce pattern de conception et vous devriez tre mme de coder le reste des mthodes (insertions, mise jour et suppression), il n'y a rien de compliqu : ce sont juste des requtes SQL... ;) Allez, et si nous allions faire un tour vers notre QCM ? Bon, je vous l'accorde, c'est plus difficile qu'il n'y parat, mais ce n'tait pas insurmontable... Vous avez appris utiliser un nouvel outil de conception pour structurer vos programmes... Utilisez-le avec sagesse ! :) Une partie somme toute assez simple et pratique ! Je pense que vous devez apprcier tout ceci et que l'utilisation d'une base de donnes avec Java ne vous posera plus de problmes majeurs. ^^ Ce tuto sur JDBC est maintenant termin. J'espre que ce dernier vous a plu et que vous avez appris tout plein de choses... Nous nous retrouverons bientt pour une autre API Java dcouvrir ! Je ne vous dis pas encore laquelle... :p