Professional Documents
Culture Documents
Cours Jee JDBC Dao 2020
Cours Jee JDBC Dao 2020
Professeur:
Pr HIBA ASRI
Filière:
Génie Informatique , 4 ème année
1
BASE DE DONNÉES
2
SGBD
Language SQL
3
MYSQL INSTALLATION
4
JDBC
5
JDBC
• API de la plateforme JEE : classes permettant l'accès depuis vos applications Java à des données
rangées sous forme de tables
JDBC permet:
• la connexion avec le SGBD ;
• l'envoi de requêtes SQL au SGBD depuis une application Java ;
• le traitement des données et éventuelles erreurs retournées par le SGBD lors des différentes étapes
du dialogue (connexion, requête, exécution, etc.).
6
JDBC
• Problème:
• Plusieurs SGBD == Plusieurs manière de traiter les données.
Solution :
• JDBC : s'adapter à n'importe quel SGBD .
• Ajouter un driver spécifique au SGBD
• https://dev.mysql.com/downloads/connector/j/
7
JDBC DRIVER
Etapes à suivre:
8
COMMUNIQUER AVEC LA BD
} catch ( ClassNotFoundException e ) {
/* Gérer les éventuelles erreurs ici. */
}
9
COMMUNIQUER AVEC LA BD
2. Se connecter à la BD
Identification de l’URL:
jdbc:mysql://nomhote:port/nombdd
jdbc:mysql://localhost:3306/BDGinfo 10
COMMUNIQUER AVEC LA BD
try {
Etablissement de la connexion: connexion = DriverManager.getConnection( url, user, mdp );
11
COMMUNIQUER AVEC LA BD
Erreurs
• SQLException: No suitable driver : driver JDBC n'a pas été chargé ou que l'URL n'a été reconnue par
aucun des drivers chargés par votre application ;
• SQLException: Connection refused ou Connection timed out ou encore CommunicationsException:
Communications link failure : la base de données n'est pas joignable.
12
COMMUNIQUER AVEC LA BD
Le nom d'hôte ou l'adresse IP dans l'URL est incorrect(e) ? Testez la connectivité en effectuant un simpleping.
Le serveur MySQL n'accepte pas de connexions TCP/IP ? Vérifiez que MySQL a été lancé sans l'option--skip-
networking.
Il n'y a plus aucune connexion disponible sur le serveur Redémarrez MySQL, et corrigez le code de votre application
MySQL ? pour qu'il libère les connexions efficacement.
Quelque chose entre l'application Java et le serveur MySQL Configurez votre pare-feu et/ou proxy pour qu'il(s)
bloque la connexion, comme un pare-feu ou un proxy ? autorise(nt) le port écouté par votre serveur MySQL.
Le nom d'hôte dans l'URL n'est pas reconnu par votre Utilisez l'adresse IP dans l'URL au lieu du nom d'hôte, ou
serveur DNS local ? actualisez si possible votre DNS.
13
COMMUNIQUER AVEC LA BD
14
COMMUNIQUER AVEC LA BD
15
COMMUNIQUER AVEC LA BD
16
COMMUNIQUER AVEC LA BD
…………….
} 17
COMMUNIQUER AVEC LA BD
…………….
} 18
COMMUNIQUER AVEC LA BD
Exemple:
19
COMMUNIQUER AVEC LA BD
7. LIBÉRER LES RESSOURCES
Exemple:
http://localhost:8080/GInfo/testjdbc?nom=Nom'&motdepasse=mdp&email=nom@gmail.co
m
21
INJECTIONS SQL
Solution
22
REQUÊTES PRÉPARÉES
Définition
Nouvel objet: peparedStatement
Intérêts:
2. une requête SQL paramétrée: Contient des jokers comblés lors de son exécution ;
3. une requête SQL protégée contre les injections SQL (erreurs sur les types des paramètres)
23
REQUÊTES PRÉPARÉES
Note: Tous les drivers JDBC ne procèdent pas de cette manière, certains n'effectuent pas l'envoi de la
requête vers le serveur SQL pour pré-compilation lors de sa création via un PreparedStatement. Ces
différences de comportement d'un driver à l'autre existent parce que cette fonctionnalité n'est pas
définie noir sur blanc dans les spécifications de l'API JDBC.
24
REQUÊTES PRÉPARÉES
Exemple:
Lorsque vous passez une telle requête à un objet PreparedStatement, celui-ci va la faire pré-compiler
et se chargera ensuite de remplacer le paramètre manquant par la valeur que vous souhaitez lui
donner au moment de l'exécution.
25
REQUÊTES PRÉPARÉES
• Eviter tout risque de failles de ce type : disponible dans tous les Driver JDBC
26
REQUÊTES PRÉPARÉES
Préparer sa requête:
Avec Statement:
Statement statement = connexion.createStatement();
Avec PreparedStatement
PreparedStatement preparedStatement = connexion.prepareStatement( "SELECT id, email,
mot_de_passe, nom FROM User ;" );
27
REQUÊTES PRÉPARÉES
Exécuter sa requête:
Avec Statement:
statement.executeQuery( "SELECT id, email, mot_de_passe, nom FROM User ;" );
Avec PreparedStatement
preparedStatement.executeQuery();
28
REQUÊTES PRÉPARÉES
statement = connexion.createStatement();
String paramEmail = request.getParameter( "email" ); String paramMotDePasse = request.getParameter( "motdepasse" );
String paramNom = request.getParameter( "nom" );
preparedStatement.setString( 1, paramEmail );
preparedStatement.setString( 2, paramMotDePasse );
preparedStatement.setString( 3, paramNom );
int statut = preparedStatement.executeUpdate();
30
LIMITES
31
SOLUTION
32
DAO (DATA ACCESS OBJECT)
33
SOLUTION: PATTERN DAO
35
PRINCIPE
36
PRINCIPE
Résultat:
Couche modèle = Couche métier +
Couche Couche de données
Modèle
Couche Métier:
• utilise les interfaces décrivant les objets de
la couche de données.
• Méthodes à appeler ne changent pas
Couche de données:
• Implémentation des CRUD (Mode de
stockage)
37
ARCHITECTURE JEE
RMI SGBD
CORBA, SOAP
Objet Java
Serveur d’application JEE
REST (HTTP,JSON)
Smart Phone Couche DAO (Data Access Object)
Mapping Object Relationnel (JPA, Hibernate)
SOAP (HTTP, XML
Application .net
Couche Métier
SOAP (HTTP, XML
Application php
Couche Service Couche Web
JMS HTTP
Client JMS • Servlet
MiddleWare: Client
• RMI • JSP
SMS • Frameworks (HTML,CSS,
• CORBA
JavaScript,…)
Client SMS • SOAP (struts, Spring
• JMS MVC, JSF)
• ….
38
MISE EN PLACE
39
MISE EN PLACE
package com.sdzee.beans;
Etapes 1:
import java.sql.Timestamp;
Etapes 2:
41
Etapes 2 (Suite): MISE EN PLACE
Solution: Créer une exception personnalisée qui va encapsuler les exceptions liées à SQL ou JDBC.
Etapes 3:
url = jdbc:mysql://localhost:3306/GestionUSer
driver = com.mysql.jdbc.Driver
nomutilisateur = user
motdepasse = user
43
MISE EN PLACE
Etapes 4:
• Instanciation des différents DAO de votre application (Ex: Une table un seul DAO)
• Lire les informations de configuration depuis le fichier properties ;
• Charger le driver JDBC du SGBD utilisé ;
• Fournir une connexion à la base de données.
44
public class DAOFactory {
MISE
private static final String FICHIER_PROPERTIES
EN PLACE
= "/com/sdzee/dao/dao.properties";
private static final String PROPERTY_URL = "url";
private static final String PROPERTY_DRIVER = "driver";
private static final String PROPERTY_NOM_UTILISATEUR = "nomutilisateur";
private static final String PROPERTY_MOT_DE_PASSE = "motdepasse";
}
MISE EN PLACE
try {
properties.load( fichierProperties );
url = properties.getProperty( PROPERTY_URL );
driver = properties.getProperty( • Charger les propriétés du fichier Properties.
PROPERTY_DRIVER );
• Intercepter l'exception éventuellement envoyée en cas
nomUtilisateur = properties.getProperty( d'erreur lors du chargement des propriétés (format du
PROPERTY_NOM_UTILISATEUR ); fichier properties incorrect)
motDePasse = properties.getProperty(
• l'encapsuler dans une
PROPERTY_MOT_DE_PASSE ); exception DAOConfigurationException.
} catch ( IOException e ) {
throw new DAOConfigurationException( "Impossible
de charger le fichier properties " + FICHIER_PROPERTIES, e );
}
47
…….
MISE EN PLACE
try {
Class.forName( driver ); • Appel à Class.forName(drive)
} catch ( ClassNotFoundException e ) {
• Encapsuler l’exception dans une
throw new DAOConfigurationException( "Le driver exception DAOConfigurationException.
est introuvable dans le classpath.", e );
}
48
MISE EN PLACE
Méthode getConnection
49
MISE EN PLACE
50
MISE EN PLACE
Etapes 5:
Création de l’interface du DAO utilisateur
• Actions effectuées sur les données, c'est-à-dire sur le bean Utilisateur.
Bonne Pratiques:
• Table nommée: User
• Interface: UserDAO
• Implémentation: UserDaoImpl
51
MISE EN PLACE
package com.sdzee.dao;
import com.sdzee.beans.Utilisateur;
} 52
MISE EN PLACE
Etapes 6:
Création de l’implémentation du DAO utilisateur
53
MISE EN PLACE
Etapes 7:
Solution:
• le DAO doit avoir accès à une instance de la DAOFactory
55
MISE EN PLACE
56
MISE EN PLACE
Etapes 8:
TAF:
• Initialiser une requête préparée avec des paramètres ;
• Récupérer une ligne d'une table et enregistrer son contenu dans un bean ;
• Fermer les ressources ouvertes (Connection, PreparedStatement, ResultSet).
57
MISE EN PLACE
Etapes 8:
3 méthodes:
1. Méthode 1: récupère une liste de paramètres et les ajoute à une requête préparée donnée ;
2. Méthode 2: récupère un ResultSet et enregistre ses données dans un bean ;
3. Méthode 3: ferme toutes les ressources ouvertes.
Etapes 8:
Méthode 1: Requête préparée:
59
MISE EN PLACE
Etapes 8:
Méthode 2: Mapping entre un resultsSet et un bean User
60
Etapes 8: Méthode 3: Fermeture des ressources
MISE EN PLACE
public static void closeRessource( ResultSet resultSet ) {
if ( resultSet != null ) {
try {
resultSet.close();
} catch ( SQLException e ) {
System.out.println( "Échec de la fermeture du public static void closeRessource( Connection
ResultSet : " + e.getMessage() ); connexion ) {
} if ( connexion != null ) {
} try {
} connexion.close();
public static void closeRessource( Statement statement ) } catch ( SQLException e ) {
{ System.out.println( "Échec de la fermeture de la
if ( statement != null ) { connexion : " + e.getMessage() );
try { }
statement.close(); }
} catch ( SQLException e ) { }
System.out.println( "Échec de la fermeture du
Statement : " + e.getMessage() );
}
}
61
}
MISE EN PLACE
Etapes 8:
Méthode 3: Fermeture des ressources
public static void closeRessource( Statement statement, Connection connexion ) {
closeRessource( statement );
closeRessource( connexion );
}
public static void closeRessource( ResultSet resultSet, Statement statement, Connection connexion ) {
closeRessource( resultSet );
closeRessource( statement );
closeRessource( connexion );
}
62
try {
MISE EN PLACE
connexion = daoFactory.getConnection();
preparedStatement = initialisationRequetePreparee(
Etapes 8: connexion, SQL_SELECT_PAR_EMAIL, false, email ); //1
Méthode trouver()
resultSet = preparedStatement.executeQuery();
private static final String SQL_SELECT_PAR_EMAIL =
if ( resultSet.next() ) {
"SELECT id, email, nom, mot_de_passe, date_inscription
FROM User WHERE email = ?"; utilisateur = map( resultSet ); //2
DAOException { } finally {
Etapes 8:
Méthode creer()
64
MISE EN PLACE
valeursAutoGenerees = }
preparedStatement.getGeneratedKeys(); finally {
Inscription utilisateur
1. Chargement de la DaoFactory
• Instanciation de cet objet une seule fois au démarrage de l’application
• Utiliser l'interface ServletContextListener.
• Méthode contextInitialized() appelée dès le démarrage de l'application, avant le
chargement des servlets et filtres du projet.
66
INTÉGRATION DAO DANS UNE APP JEE
Création du listener
public class InitialisationDaoFactory implements
/* Enregistrement dans un attribut ayant pour portée toute
ServletContextListener {
l'application */
private static final String ATT_DAO_FACTORY = "daofactory";
servletContext.setAttribute( ATT_DAO_FACTORY,
private DAOFactory daoFactory;
this.daoFactory );
}
@Override
public void contextInitialized( ServletContextEvent event
@Override
){
public void contextDestroyed( ServletContextEvent event
/* Récupération du ServletContext lors du chargement
){
de l'application */
/* Rien à réaliser lors de la fermeture de l'application... */
ServletContext servletContext = event.getServletContext();
}
/* Instanciation de notre DAOFactory */
}
this.daoFactory = DAOFactory.getInstance(); 67
INTÉGRATION DAO DANS UNE APP JEE
Configuration du listener
<listener>
<listener-class>com.projet.config.InitialisationDaoFactory</listener-class>
</listener>
68
INTÉGRATION DAO DANS UNE APP JEE
public class Inscription extends HttpServlet {
public static final String CONF_DAO_FACTORY = "daofactory";
public static final String ATT_USER = "utilisateur";
public static final String ATT_FORM = "form";
public static final String VUE = "/WEB-INF/inscription.jsp";
Configuration du HttpServletRequest
public void doPost( listener request, HttpServletResponse response ) throws
ServletException, IOException {
/* Préparation de l'objet formulaire */
InscriptionForm form = new InscriptionForm( utilisateurDao );
70
INTÉGRATION DAO DANS UNE APP JEE
Méthode inscrireUtilisateur
public Utilisateur inscrireUtilisateur(
HttpServletRequest request ) {
if ( erreurs.isEmpty() ) {
String email = getValeurChamp( request, CHAMP_EMAIL
utilisateurDao.creer( utilisateur );
resultat = "Succès de l'inscription.";
);
} else {
String motDePasse = getValeurChamp( request,
resultat = "Échec de l'inscription.";
CHAMP_PASS );
}
String confirmation = getValeurChamp( request,
} catch ( DAOException e ) {
CHAMP_CONF );
resultat = "Échec de l'inscription : une erreur imprévue
String nom = getValeurChamp( request, CHAMP_NOM );
est survenue, merci de réessayer dans quelques instants.";
e.printStackTrace();
Utilisateur utilisateur = new Utilisateur();
}
try {
traiterEmail( email, utilisateur );
return utilisateur;
traiterMotsDePasse( motDePasse, confirmation,
}
utilisateur );
traiterNom( nom, utilisateur ); 71
RÉCAPITULONS (BONNE PRATIQUES)
Le pattern DAO permet d'isoler l'accès aux données et leur stockage du reste de l'application.
Mettre en place des exceptions spécifiques au DAO permet de masquer le type du stockage sous-
jascent.
Mettre en place des utilitaires pour la préparation des requêtes et la libération des ressources
permet de limiter la duplication et d'alléger grandement le code.
Notre DAO libérant proprement les ressources qu'il met en jeu, une seule et unique instance de
notre DAO peut être partagée par toutes les requêtes entrantes.
72
RÉCAPITULONS (BONNE PRATIQUES)
Récupérer une telle instance de DAO de manière unique depuis une servlet, et non pas à
chaque requête entrante, peut se faire simplement en utilisant sa méthode init().
Une servlet transmet simplement l'instance du DAO à l'objet métier, qui sera responsable de
la gestion des données.
L’objet métier ne connaît pas le système de stockage final utilisé : il ne fait qu'appeler les
méthodes définies dans l'interface de notre DAO.
73