| 8.0 Utilisation
des Prepared Statements.
Parfois, il est plus
utile et plus efficace d'utiliser l'objet PreparedStatement pour envoyer
une instruction SQL à la base de données. Ce type spécial
d'instruction est dérivé de la classe plus générale,
Statement, que vous connaissez déjà.
8.1 Quand utiliser
un objet PreparedStatement.
Si vous voulez exécuter
un objet Statement plusieurs fois, le temps d'exécution sera normalement
réduit si vous utilisez à la place un objet PreparedStatement.
La fonctionnalité
principale d'un objet PreparedStatement, contrairement à l'objet
Statement, est de lui fournir une instruction SQL dès sa création.
L'avantage de ceci dans plusieurs cas, est que l'instruction SQL sera
directement envoyée au SGBD, où elle y sera compilée.
Ayant pour résultat que l'objet PreparedStatement ne contient plus
seulement une instruction SQL, mais bien une instruction SQL précompilée.
Cela signifie que quand le PreparedStatement est exécuté,
le SGBD a juste à lancer l'instruction SQL du PreparedStatement
sans avoir à le compiler avant.
Un objet PreparedStatement
peut être aussi utilisé dans une instruction SQL sans paramètre,
mais vous allez plus probablement les utiliser pour des instructions SQL
avec paramètre. L'avantage de ceci, quand vous utilisez une instruction
SQL requérant des paramètres, est que vous pouvez utiliser
la même instruction en fournissant différentes valeurs à
chaque fois que vous l'exécutez. Nous verrons un exemple dans la
prochaine section.
8.2 Créer
un objet PreparedStatement.
Tout comme l'objet
Statement, vous devez créer l'objet PreparedStatement avec une
méthode Connexion. Utilisant notre précédante connexion
ouverte conn, vous aurez à écrire un code ressemblant à
celui ci-dessous pour créer un objet PreparedStatement recevant
deux paramètres.
PreparedStatement updateVentes = conn.preparedStatement(
"UPDATE COFFES SET VENTES = ? WHERE N LIKE ?");
La variable updateVentes contient maintenant une instruction SQL, "UPDATE
CAFE SET VENTES = ? WHERE NOM_CAFE LIKE ?", qui a été
envoyée à SGBD puis précompilée.
8.3 Paramètres
vers un PreparedStatement.
Vous devrez fournir des valeurs pour être utilisées à
la place des points d'interrogation, si il y en a, avant que vous puissiez
exécuter un objet PreparedStatement. Pour faire ça, il faudra
utiliser l'une des méthodes setXXX définies dans la classe
PreparedStatement. Si la valeur que vous voulez substituer au point d'interrogation
est un int Java, vous devrez appeler la méthode setInt. Si la valeur
est un String Java, vous devrez appeler la méthode setString, et
ainsi de suite. En général, il y a un setXXX pour chaque
type Java.
En utilisant l'objet PreparedStatement de l'exemple précédant,
la ligne de code qui suit devrait remplacer le point d'interrogation en
un int Java, la valeur 75 :
updateVentes.setInt(1,75);
Comme vous pouvez le voir dans l'exemple, le premier argument donné
à la méthode setXXX est la position du point d'interrogation,
et le deuxième argument, la valeur par laquelle on veut le remplacer.
L'exemple suivant substitue le deuxième paramètre avec le
String "Colombian".
updateVentes.setString(2, "Colombian");
Après que ces
valeurs aient été déposées dans les deux paramètres
d'entrées, l'instruction SQL contenue dans updateVentes sera équivalente
à l'instruction SQL dans l'objet String updateString que nous avons
utilisé dans un des exemples précédents. Les deux
fragments de codes suivants font la même chose :
Fragment de Code 1
:
String
updateString = "UPDATE CAFE SET VENTES = 75 " +
"WHERE NOM_CAFE LIKE 'Colombian'";
stmt.executeUpdate(updateString);
Fragment de Code 2
:
PreparedStatement
updateVentes = conn.preparedStatement(
"UPDATE CAFE SET VENTES = ? WHERE NOM_CAFE LIKE ?");
updateVentes.setInt(1,75);
updateVentes.setString(2, "Colombian");
updateVentes.executeUpdate();
Nous avons utilisé
la méthode executeUpdate pour exécuter les objets Statement
stmt et PreparedStatement updateVentes. Remarquez qu'aucun argument n'est
fourni à executeUpdate quand ils sont utilisés pour exécuter
updateVentes. Et ceci est juste, car updateVentes contient déjà
l'instruction SQL devant être exécutée.
Prêtez attention
à ces exemples, vous verrez pourquoi vous devriez utiliser un objet
PreparedStatement avec paramètres, plus qu'une simple instruction,
et ce, même si elle nécessite moins d'étapes. Si vous
mettiez une ou deux fois à jour la colonne VENTES, cela ne vaudrait
pas le coup d'utiliser une instruction SQL avec paramètres. Mais
si vous la mettez souvent à jour, il serait plus simple d'utiliser
un objet PreparedStatement, spécialement en situation ou vous avez
à utiliser une boucle for ou une boucle while pour définir
un paramètre à une succession de données. Nous verrons
un exemple plus tard dans cette section.
Une fois qu'on a assigné
une valeur à un paramètre, il retiendra la valeur jusqu'à
ce qu'elle soit réinitialisée avec une autre valeur, ou
bien jusqu'à ce que la méthode clearParameters soit appelée.
Utilisant l'objet PrepareStatement updateVentes. Le code suivant illustre
la réutilisation d'un prepared statement après avoir réinitialisé
la valeur de l'un des paramètres et en conservant la valeur de
l'autre paramètre :
updateVentes.setInt(1,
100);
updateVentes.setString(2, "French_Roast");
updateVentes.executeUpdate();
//Change la valeur de la colonne VENTES à la ligne French Roast
pour la valeur //100
updateVentes.setString(2, "Espresso");
updateVentes.executeUpdate();
//Change la valeur de la colonne VENTES à la ligne Espresso
pour la valeur //100(le premier paramètre est resté
à 100, et le second paramètre est //réinitialisé
par "Espresso"
8.4 Utilisation
d'une boucle pour assigner des valeurs.
Vous pouvez souvent
rendre le code plus facile en utilisant une bouche for ou while pour assigner
des valeurs aux paramètres d'entrées.
Le fragment de code
qui suit présente l'utilisation d'une boucle for pour assigner
des valeurs aux paramètres dans un objet PreparedStatement updateVentes.
Le tableau VentesDeLaSemaine contient les montants des ventes hebdomadaires.
Ces montants de ventes correspondent aux noms des cafés listés
dans le tableau cafe, donc le premier montant dans VentesDeLaSemaine(175)
s'applique au premier café dans cafe (" Colombian "),
le second montant dans VentesDeLaSemaine (150) s'applique au second café
dans cafe (" French_Roast "), et ainsi de suite. Ce fragment
de code présente la mise à jour de la colonne VENTES pour
tout les cafés de la table CAFE :
PreparedStatement
updateVentes;
String updateString = "update CAFE" +
"set VENTES = ? WHERE NOM_CAFE LIKE ?";
updateVentes = conn.prepareStatement(updateString);
int []VentesDeLaSemaine = {175 , 150, 60, 155, 90};
String [] cafes ={"Colombian","French_Roast","Espresso",
"Colombian_Decaf", "French_Roast_Decaf"};
int len = cafes.length;
for(int i = 0 ; i < len ; i ++){
updateVentes.setInt(1, VentesDeLaSemaine[i]);
updateVentes.setString(2, cafes[i]);
updateVentes.executeUpdate();
}
Quand le propriétaire
désire faire une mise à jour sur les montants des ventes
de la semaine suivante, il peut utiliser ce code comme modèle.
Il ne lui reste plus qu'à entrer de nouveaux montants de vente
dans l'ordre adéquat dans le tableau VentesDeLaSemaine. Le nom
du café dans le tableau cafe reste constant, donc il n'a pas besoin
d'y apporter de modifications. (Dans une vraie application, les valeurs
seraient probablement entrées par l'utilisateur plutôt que
d'être initialisées dans le tableau).
8.5 Valeurs retournées
par la méthode executeUpdate.
La méthode
executeQuery retourne un objet ResultSet contenant les résultats
de la requête envoyée au SGBD, la valeur retournée
pour executeUpdate est un int qui indique combien de lignes de la table
ont été mises à jour. Le code qui suit montre la
valeur retournée par executeUpdate en l'assignant à la variable
n :
updateVentes.setInt(1,50);
updateVentes.setString(2, "Espresso");
int n = updateVentes.executeUpdate();
//n = 1 car une ligne procède à un changement.
La table CAFE a été
mise à jour en remplaçant la valeur contenue dans la colonne
VENTES de la ligne Espresso par 50. La mise à jour affecte une
seule ligne dans la table, donc n est égal à 1.
Quand la méthode
executeUpdate est utilisée pour exécuter une instruction
DDL, comme créer une table, elle retourne la valeur 0. Dans le
fragment de code suivant, qui exécute une instruction DDL pour
créer la table CAFE, n recevra la valeur 0 :
int
n = executeUpdate(createTableCafe); // n = 0
Notez que quand la
valeur retournée de executeUpdate est 0, cela peut vouloir dire
deux choses :
- L'instruction
exécutée est une mise à jour et que 0 ligne sont
affectées.
- L'instruction est une instruction DDL
Précédent
Suivant
|