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