FAQ JDBCConsultez toutes les FAQ
Nombre d'auteurs : 8, nombre de questions : 162, dernière mise à jour : 3 juin 2015 Ajouter une question
Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums de http://www.developpez.com et de l'expérience personnelle des auteurs.
Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes. Les auteurs font leur maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous trouvez une erreur, ou que vous souhaitez nous aider en devenant rédacteur, lisez ceci.
- Comment créer un Statement ?
- Comment exécuter un Statement ?
- Que renvoie l'exécution d'un Statement ?
- Peut-on créer une requête spécifique à un SGBDR ?
- Je n'ai pas d'exception, mais la méthode executeXXX ne fait pas ce que je veux ?
- Comment gérer le timeout de l'exécution d'une instruction ?
- Comment récupérer un ResultSet lors de l'utilisation de la méthode execute ?
- Comment limiter le nombre de lignes des ResultSet renvoyées par l'instruction ?
- Comment récupérer plusieurs ResultSet depuis le Statement ?
- Comment récupérer les clefs autogénérées par l'exécution du Statement ?
- Qu'est-ce que la syntaxe d'échappement ?
- Doit-on fermer un Statement ?
L'interface Statement représente une instruction SQL. L'obtention d'une instance de cette interface se fait à partir de la Connection :
Code java : | Sélectionner tout |
1 2 3 4 5 6 7 | try{ Connection connection = ... Statement statement = connection.createStatement(); } catch(Exception e){ //cf. Comment gérer les erreurs ? } |
Code java : | Sélectionner tout |
1 2 3 | Statement statement = connection.createStatement( ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); |
L'interface Statement propose une dizaine de méthodes permettant l'exécution d'expressions SQL. On peut les regrouper par catégories :
- les méthodes execute : méthodes génériques pour n'importe quelle expression SQL ;
- les méthodes executeQuery : méthodes appropriées à l'exécution d'un SELECT ;
- les méthodes executeUpdate : méthodes appropriées à l'exécution d'une instruction menant à la modification de la BD (INSERT, UPDATE, DELETE, CREATE, etc.) ;
- les méthodes executeBatch : voir la partie réservée aux transactions.
Voici quelques exemples :
Code java : | Sélectionner tout |
1 2 3 4 | Statement statement = connection.createStatement(); boolean result = statement.execute("SELECT * FROM MATABLE"); ResultSet resultSet = statement.executeQuery("SELECT ATTRIBUT1, ATTRIBUT2 FROM MATABLE"); int col = statement.executeUpdate("INSERT INTO MATABLE VALUES(15,'bonjour',7.0)"); |
Le retour d'une méthode execute XXX dépend du type de celle-ci :
- execute : un boolean valant true si l'instruction renvoie un ResultSet, false sinon ;
- executeQuery : unResultSet contenant les résultats (ne retourne jamais null) ;
- executeUpdate : unint indiquant le nombre de tuples (lignes) modifiés pour un INSERT, UPDATE et DELETE, ou alors 0 pour les instructions ne retournant rien (CREATE par exemple) ;
- executeBatch : int[]: un tableau d'entiers indiquant le nombre de tuples modifiés pour chaque commande contenue dans le batch. Ce tableau est ordonné selon l'ordre des ajouts au batch.
En règle générale la réponse est oui. En pratique cela dépendra de l'implémentation du Driver. Cela implique plusieurs choses :
- possibilité d'utiliser des types spécifiques au SGBD ;
- possibilité d'utiliser des mots réservés au SGBD : Comment obtenir la liste des mots clefs SQL non standard d'un SGBDR ? ;
- possibilité d'utiliser les extensions procédurales : par exemple PL/SQL pour Oracle, T/SQL pour Sybase, etc. ;
- possibilité d'appeler des fonctions spécifiques : procédures stockées par exemple. Dans ce dernier cas, il est tout de même conseillé d'utiliser la syntaxe d'échappement.
Dans ce cas de figure, vérifiez :
- que vous n'avez pas de warning ;
- que votre requête SQL est correcte, en la lançant directement avec le SGBD ;
- que vous utilisez la bonne méthode execute : par exemple, un execute ou un executeUpdate pour « INSERT INTO... ».
L'interface Statement fournit pour cela les méthodes setQueryTimeout(int) et getQueryTimeout(). Par exemple :
Code java : | Sélectionner tout |
1 2 3 4 | Statement statement = ... System.out.println("timeout par défaut = "+statement.getQueryTimeout()); statement.setQueryTimeout(2); //le temps exprimé en secondes |
La méthode execute renvoie un boolean indiquant la présence ou non d'un ResultSet. Pour le récupérer, il suffit de faire comme ceci :
Code java : | Sélectionner tout |
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 | String url = "url"; String login = "log"; String password = "pass"; Connection connection = null; Statement statement = null; ResultSet resultSet = null; try{ connection = DriverManager.getConnection(url,login,password); statement = connection.createStatement(); boolean rs = statement.execute("SELECT * FROM MaTable"); if(rs){ resultSet = statement.getResultSet(); }else{ System.out.println("Il n'y a pas de ResultSet, peut-être une mise à jour : "); int nbTuples = statement.getUpdateCount(); System.out.println("Nombre de tuples mis à jour = "+nbTuples); } } catch(SQLException sqle){ //cf. Comment gérer les erreurs ? } finally{ //cf. Comment bien fermer une connexion ? //cf. Doit-on fermer un Statement ? //cf. Doit-on fermer un ResultSet ? } |
Il faut utiliser la méthode setMaxRows(int max) de Statement. Par exemple :
Code java : | Sélectionner tout |
1 2 3 | Statement statement = ...; System.out.println("max rows : "+statement.getMaxRows()); statement.setMaxRows(200); |
Une valeur de 0 signifie qu'il n'y a pas de maximum.
Une SQLException est levée s'il y a une erreur durant une exécution ou si max est négatif.
La méthode getMoreResults() permet de vérifier la présence d'autres ResultSet. Par exemple :
Code java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | Statement statement = ...; if (!statement.execute()) { System.out.println("La requête ne renvoie pas de ResultSet"); } else { ResultSet premierResultSet = statement.getResultSet(); if (statement.getMoreResults(Statement.KEEP_CURRENT_RESULT)) { ResultSet secondResultSet = statement.getResultSet(); // maintenant les deux ResultSet sont ouverts et prêts à être utilisés premierResultSet.next(); secondResultSet.next(); // ... }else{ System.out.println("Il n'y a pas de second ResultSet"); } } |
- Statement.CLOSE_CURRENT_RESULT : le ResultSet courant doit être fermé lors de l'appel à la méthode getMoreResults ;
- Statement.CLOSE_ALL_RESULTS : tous les ResultSet précédemment ouverts doivent être fermés lors de l'appel à la méthode getMoreResults ;
- Statement.KEEP_CURRENT_RESULT : Le ResultSet courant ne doit pas être fermé lors de l'appel à la méthode getMoreResults.
L'argument par défaut est Statement.CLOSE_ALL_RESULTS.
Pour récupérer les clefs autogénérées par l'exécution d'une requête, il faut utiliser la méthode execute(String sql, int autoGeneratedKeys)(ou executeUpdate). L'entier autoGeneratedKeys doit prendre la valeur Statement.RETURN_GENERATED_KEYS.
Code java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | Statement statement = ... String commandeSQL = " ..."; statement.executeUpdate(commandeSQL,Statement.RETURN_GENERATED_KEYS); //Les clefs autogénérées sont retournées sous forme de ResultSet ResultSet clefs = statement.getGeneratedKeys(); if(clefs.next()){ System.out.printn("La première clef autogénérée vaut "); System.out.printn(clefs.getObject(1)); } |
La syntaxe d'échappement est définie par un bloc de code à l'intérieur de l'instruction SQL. Ce morceau de code est contenu entre des guillemets. Cette syntaxe permet d'indiquer au Driver que le code n'est pas du SQL et doit être traité de manière spécifique.
Code java : | Sélectionner tout |
String sql = "{motClefs ... parametres}"
la gestion des caractères spéciaux, dans LIKE, de manière indépendante du SGBD :
Code java : | Sélectionner tout |
1 2 3 | String sql = "SELECT * FROM Annuaire WHERE nom LIKE '%{escape '''}%'"; //sélection dans un annuaire des personnes ayant une apostrophe dans leur nom ResultSet resultat = statement.executeQuery(sql); |
Code java : | Sélectionner tout |
1 2 3 4 5 | String sql = "SELECT {fn curdate()}, {fn user()}"; ResultSet resultat = statement.executeQuery(sql); resultSet.next(); System.out.println("On est le : "+result.getObject(1)); System.out.println("L'utilisateur est : "+result.getObject(2)); |
l'appel de procédures stockées :
Code java : | Sélectionner tout |
1 2 3 4 5 | String sql = "{call maProcedure(?, ?)}"; //appel d'une procédure à deux arguments //Cf. le chapitre sur les procédures stockées CallableStatement call = connection.prepareCall(sql); |
Code java : | Sélectionner tout |
1 2 3 4 5 6 | {d 'yyyy-mm-dd'} //format pour DATE {t 'hh:mm:ss'} //format pour TIME {ts 'yyyy-mm-dd hh:mm:ss.f . . .'} //format pour TIMESTAMP |
Tout comme pour une Connection, même si le Garbage Collector, libérera les ressources allouées au Statement, il est conseillé de le fermer explicitement.
Code java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | Connection connection = null; Statement statement = null; try{ //initialisation de la connexion et du statement } catch(SQLException sqle){} catch(AutreException ae){} finally{ if(statement !=null){try{statement.close();}catch(Exception e){e.printStackTrace();}} if(connection !=null){try{connection.close();}catch(Exception e){e.printStackTrace();}} } |
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.