Il va falloir vous accrocher un tout petit peu...
De tels objets sont créés exactement de la même façon que des
Statement classiques, sauf qu'au lieu d'avoir :
Code : Java1 | Statement stm = conn.createStatement();
|
nous avons :
Code : Java1 | PreparedStatement stm = conn.prepareStatement("SELECT * FROM classe");
|
Jusqu'ici, rien de particulier ! Cependant, une différence est déjà effective à ce stade
: la requête SQL est pré-compilée !
Ceci a pour effet que celle-ci s'exécutera plus vite dans le moteur SQL de la BDD, c'est sûr puisqu'il n'aura pas à la compiler...

En fait, en règle générale, on utilise ce genre d'objet pour des requêtes ayant beaucoup de paramètres ou des requêtes pouvant être exécutées plusieurs fois...
C'est tout ce qu'il y a comme différence ?
Non, bien sûr. Je vous ai dit dans le titre que
nous allons préparer des requêtes !.
Il y a une différence de taille entre l'objet
PreparedStatement et l'objet
Statement : dans le premier, on peut utiliser des paramètres à trous !
Quoi ?
Je me doutais que vous auriez du mal à comprendre... En fait, vous pouvez insérer un caractère spécial dans vos requêtes et remplacer ce caractère grâce à des méthodes de l'objet
PreparedStatement en spécifiant sa place et sa valeur (son type étant défini par la méthode utilisée...).
Voici un exemple :
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 | package com.sdz.prepare;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
public class Prepare {
public static void main(String[] args) {
try {
Class.forName("org.postgresql.Driver");
String url = "jdbc:postgresql://localhost:5432/Ecole";
String user = "postgres";
String passwd = "postgres";
Connection conn = DriverManager.getConnection(url, user, passwd);
Statement state = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
//On crée notre requête
String query = "SELECT prof_nom, prof_prenom FROM professeur";
//Premier trou pour le nom du professeur
query += " WHERE prof_nom = ?";
//Deuxième trou pour un id de professeur
query += " OR prof_id = ?";
//On crée notre objet avec la requête en paramètre
PreparedStatement prepare = conn.prepareStatement(query);
//On remplace le trou numéro 1 => le nom du professeur
prepare.setString(1, "MAMOUD");
//On remplace le trou numéro 2 => l'id du professeur
prepare.setInt(2, 2);
//On affiche
System.out.println(prepare.toString());
//On remodifie le trou numéro 1
prepare.setString(1, "TOTO");
//On ré-affiche
System.out.println(prepare.toString());
//On remodifie le trou numéro 2
prepare.setInt(2, 159753);
//On ré-affiche
System.out.println(prepare.toString());
prepare.close();
state.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
|
Ce qui nous donne :
Je sais, ça fait toujours ça la première fois...

Je ne vous cache pas que ceci peut s'avérer très utile.
En effet ! Mais qu'y a-t-il comme méthode d'affectation de valeur ?
C'est simple : vous vous souvenez de la petite liste de méthodes de l'objet
ResultSet pour récupérer des données ? À peu de choses près, la même mais avec
setXXX à la place de
getXXX.
Tout comme son homologue sans trou, cet objet peut prendre les mêmes types de paramètres pour la lecture et pour la modification des données lues :
Code : Java1
2
3
4
5 | PreparedStatement prepare = conn.prepareStatement(
query,
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY
);
|
Vous avez aussi une méthode retournant un objet
ResultSetMetaData mais encore une méthode permettant de nettoyer les changements de valeur des trous :
prepare.clearParameters();
.
Si vous ajoutez cette méthode à 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 détail...