Interface Statement

Un objet de type Statement s'obtient en appelant la méthode createStatement() de l'interface Connection.

On peut créer autant d'objets de ce type par connexion, et tous ces objets peuvent être utilisés de façon concurrente.

On peut de plus passer trois paramètres de configuration lors de la création d'une instance de Statement.

Toutes ces valeurs entières sont des entiers publics et statiques de la classe ResultSet. Nous verrons leur signification exacte dans le paragraphe sur les ResultSet.

Il est important de fermer un Statement lorsqu'il n'est plus utilisé, par appel à sa méthode close().

Il existe trois méthodes pour exécuter un Statement. Chacune de ces méthodes doit être utilisée dans son propre contexte.

Ces trois méthodes prennent une chaîne de caractères en paramètres. Cette chaîne est la commande SQL qui va être exécutée sur le serveur.

Tous les objets de type Statement doivent être fermés par un appel à la méthode close() une fois qu'ils ne sont plus utilisés. La fermeture d'un Statement entraîne automatiquement la fermeture de tous les objets ResultSet qui ont été ouverts sur ce Statement.

Notons que même si la fermture d'une connexion (par appel à sa méthode close()) ferme automatiquement tous les Statement ouverts dessus, il est recommandé de le faire à la main. De même que pour la fermeture des ResultSet.

Une fois qu'un objet Statement ou ResultSet a été fermé, il est illégal d'invoquer une de ses méthodes. L'appel d'une telle méthode peut jeter systématiquement une exception de type SQLException.

L'interface PreparedStatement étend l'interface Statement, donc tout ce qui précède et qui concerne l'interface Statement reste valide pour l'interface PreparedStatement.

L'interface PreparedStatement ajoute la possibilité de paramétrer des requêtes SQL. Les instances de PreparedStatement s'utilisent quand une même requête doit être exécutée plusieurs fois, avec des paramètres différents. La chaîne de caractères SQL contient donc des marqueurs, qui seront remplacés par des valeurs à chaque exécution.

On préfèrera systématiquement l'utilisation de PreparedStatement aux Statement classiques, en particulier pour les requêtes de mise à jour. Ces requêtes comportent le plus souvent des paramètres, qu'il faut ajouter à la chaîne de caractères SQL à exécuter. Utiliser des PreparedStatement permet de passer par les méthodes de paramétrage du pilote de base, ce qui nous décharge de la délicate gestion des erreurs, et évitera les attaques par injection de code SQL.

L'exécution d'un PreparedStatement se déroule de la même manière que pour un Statement, à l'aide des trois méthodes executeQuery(), executeUpdate() et execute().

L'interface PreparedStatement propose deux méthodes :

La méthode getMetaData() retourne un objet de type ResultSetMetaData qui propose un jeu d'une vingtaine de méthodes pour déterminer le types de colonnes du résultat de la requête. Voyons ceci sur un exemple.

On remarquera qu'ici aussi les paramètres sont numérotés à partir de 1.

La méthode getParameterMetaData() retourne un objet de type ParameterMetaData, qui lui-même propose quelques méthodes pour obtenir des informations sur les paramètres d'un PreparedStatement. Voyons un exemple d'utilisation.

Notons que le mode d'un paramètre, qui peut prendre l'une des valeurs IN, OUT ou INOUT est utilisé pour les CallableStatements.

Lors de l'insertion de lignes dans une table, il arrive que certaines valeurs soient générées automatiquement par la base de données. C'est notamment le cas des colonnes auto-incrémentales que l'on peut utiliser pour générer des clés primaires dans les tables MySQL.

JDBC nous donne un moyen d'obtenir la valeur de la clé générée aussitôt la requête d'insertion effectuée. Heureusement, car sans ce moyen, il pourrait être assez compliqué de récupérer la donnée que l'on vient d'insérer. Voyons ceci sur un exemple.

On notera que pour fonctionner correctement, cette méthode ne doit être appelée que si la transaction est en mode non auto-commit.

Il est également possible de grouper des requête SQL dans un Statement et de les exécuter en une seule fois. On appelle ce genre d'exécution l'exécution en batch. En général cela signifie que l'on s'attend à ce que l'exécution totale soit assez longue, et que pendant ce temps, le système peut faire autre chose.

L'exécution de commandes SQL en batch n'est possible que pour des requêtes de modification de la base, celles que l'on exécute avec la méthode executeUpdate(String). Toute requête SQL qui peut être exécutée de la sorte, peut également être passée en paramètre de la méthode addBatch(String). L'appel de cette méthode ne fait que stocker la requête SQL, sans l'exécuter. C'est l'appel à la méthode executeBatch() qui déclenche l'exécution.

L'exécution en batch peut représenter des gains substantiels en performances. Le coût d'une aller et retour avec la base de données est en lui-même coûteux, et l'on tentera le plus possible de minimiser ces allers et retours.

Il est aussi possible de lancer des exécutions de mise à jour en batch lorsque l'on travaille avec des PreparedStatement. Le mécanisme est toutefois légèrement différent, puisqu'un PreparedStatement est construit sur une unique requête SQL paramétrée.

PreparedStatement propose une méthode addBatch() qui ne prend aucun paramètre. Au moment où cette méthode est appelée, JDBC construit une requête SQL avec la requête du PreparedStatement, et le jeu de paramètres qu'il a à sa disposition. Si l'un des paramètres n'a pas été fixé, une erreur est générée. On peut ainsi ajouter autant de requêtes que l'on veut.

L'exécution des requêtes se fait de la même manière et sous les mêmes contraintes que pour un Statement classique.