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.


SommaireLes instructions - StatementLes procédures stockées et fonctions - CallableStatement (7)
précédent sommaire suivant
 

L'interface CallableStatement, qui étend PreparedStatement, permet de faire appel aux procédures stockées et aux fonctions de manière standard pour tous les SGBD. Pour que cet appel soit indépendant du SGBD ciblé, CallableStatement utilise la syntaxe d'échappement (cf. Qu'est-ce que la syntaxe d'échappement ? ).

La principale différence avec les PreparedStatement se situe au niveau des paramètres. Ceux-ci sont toujours définis par des points d'interrogation, mais en plus des paramètres d'entrée (IN), CallableStatement peut avoir des paramètres de sortie (OUT). Ces paramètres définissent le résultat de la procédure. On peut aussi combiner ces deux types (INOUT).

Mis à jour le 11 avril 2013 Ioan

Une instance de CallableStatement s'obtient grâce aux méthodesprepareCall de Connection. Le premier argument de ces méthodes est une chaîne de caractères définissant l'instruction SQL. Cette chaîne de caractères utilise la syntaxe d'échappement et peut avoir deux formes.

Pour les procédures stockées :

Code java : Sélectionner tout
1
2
3
4
5
String sql = "{call nomDeLaProcedure[(?, ?, ...)]}"; 
//[(?, ?, ...)] sont les éventuels arguments de la procédure 
  
//ces arguments peuvent être de type IN, OUT ou INOUT 
CallableStatement statement = connection.prepareCall(sql);
Pour les fonctions (procédures stockées renvoyant un résultat) :

Code java : Sélectionner tout
1
2
3
4
5
String sql = "{? = call nomDeLaProcedure[(?, ?, ...)]}"; 
//le premier ? est le résultat de la procédure 
  
//[(?, ?, ...)] sont les éventuels arguments de la procédure 
CallableStatement statement = connection.prepareCall(sql);
Les autres arguments de la méthode prepareCall servent à déterminer les types de ResultSet obtenus à partir de la procédure. Par exemple :

Code java : Sélectionner tout
1
2
3
4
String sql = "{? = call max(?, ?)}"; 
CallableStatement statement = connection.prepareCall(sql, 
          ResultSet.TYPE_FORWARD_ONLY, 
          ResultSet.CONCUR_READ_ONLY);

Mis à jour le 11 avril 2013 Ioan

Comme pour les PreparedSatement, le passage des paramètres d'entrée des CallableStatement se fait grâce à l'ensemble des méthodes setXXX. Il est important de connaître les correspondances entre les types SQL et les types java (cf. Tableau de relations ). En plus de l'index, on peut cibler un paramètre grâce à son nom.

Voici un exemple, pour une procédure stockée chargée de retrouver les abonnés d'un annuaire ayant un certain nom. Cette procédure renvoie plusieurs ResultSet.

Le code Java chargé de la créer et de l'appeler :

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
27
28
29
30
31
32
33
34
35
36
37
38
//CHARGEMENT DU DRIVER 
Class.forName("com.mysql.jdbc.Driver"); 
//CONNECTION AU SGBD 
String url = "jdbc:mysql://localhost/test"; 
String user = "user"; 
String password = "root"; 
connection = DriverManager.getConnection(url,user,password); 
//CREATION DE LA PROCEDURE 
Statement statement = connection.createStatement(); 
statement.executeUpdate("DROP PROCEDURE IF EXISTS rechercherNom"); 
statement.executeUpdate( 
    "CREATE PROCEDURE rechercherNom(IN leNom VARCHAR(50))\n" 
    + "BEGIN\n"  
    + " SELECT * FROM Annuaire WHERE nom = leNom;\n" 
+ " SELECT COUNT(*) FROM Annuaire WHERE nom = leNom;\n"    
    + "END\n"); 
//APPEL DE LA PROCEDURE 
String sql = "{call rechercherNom(?)}"; 
CallableStatement call = connection.prepareCall(sql); 
//passage de la chaîne "ioio" comme valeur du premier paramètre 
call.setString(1,"ioio"); 
if(call.execute()){ 
    //récupération des ResultSet 
    ResultSet resultat1 = call.getResultSet(); 
    call.getMoreResults(Statement.KEEP_CURRENT_RESULT); 
    ResultSet resultat2 = call.getResultSet(); 
    //traitement des informations 
    while(resultat1.next()){ 
        for(int i=0;i<resultat1.getMetaData().getColumnCount();i++){ 
            System.out.print(resultat1.getObject(i+1)+", "); 
        } 
        System.out.println(""); 
    } 
    resultat2.next(); 
    System.out.println("Nombre de lignes = "+resultat2.getObject(1)); 
    resultat1.close(); 
    resultat2.close(); 
}
Comme pour les PreparedStatement, les paramètres IN peuvent être identifiés par leur index dans l'instruction SQL ou par leur nom. Pour cet exemple, les instructions ci-dessous sont équivalentes :

Code java : Sélectionner tout
1
2
3
4
call.setString("leNom","ioio"); 
call.setObject(1,"ioio"); 
call.setObject(1,"ioio", Types.VARCHAR); 
call.setObject("leNom","ioio",Types.VARCHAR);

Mis à jour le 11 avril 2013 Ioan

Pour récupérer les résultats (OUT) d'un CallableStatement, il faut utiliser les méthodes getXXX correspondant au type retourné. Les paramètres OUT doivent être enregistrés comme tels. Voici un exemple récupérant le nombre d'abonnés d'un annuaire.

Le corps de la procédure :

Code sql : Sélectionner tout
1
2
3
4
CREATE PROCEDURE nombreAbonnes(OUT nb INTEGER) 
   BEGIN 
      SELECT COUNT(*)  INTO nb FROM Annuaire; 
   END
Le code Java : comme pour les paramètres d'entrée, un paramètre peut être ciblé par son nom ou par son index.

Code java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
String sql = "{call nombreAbonnes(?)}"; 
CallableStatement statement = connection.prepareCall(sql); 
//enregistrement du paramètre de sortie en fonction de son type et de son nom 
statement.registerOutParameter("nb", java.sql.Types.INTEGER); 
//enregistrement du paramètre de sortie en fonction de son type et de son index 
  
//statement.registerOutParameter(1, java.sql.Types.INTEGER); 
statement.execute(); 
//récupération du résultat en fonction de l'index 
int resultat = statement.getInt(1); 
//récupération du résultat en fonction du nom du paramètre 
  
//int resultat = statement.getInt("nb"); 
System.out.println("Nombre d'abonnés = "+resultat);

Mis à jour le 11 avril 2013 Ioan

Pour spécifier un paramètre INOUT, il suffit de combiner registerOutParameter et setXXX. Voici un exemple qui montre la marche à suivre.

Voici le code Java :

Code java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Connection connection = ... ; 
//CREATION DE LA PROCEDURE 
Statement statement = connection.createStatement(); 
statement.executeUpdate("DROP PROCEDURE IF EXISTS hello"); 
statement.executeUpdate( 
    "CREATE PROCEDURE hello(INOUT param VARCHAR(30))\n" 
    + "BEGIN\n"  
    + " SELECT CONCAT('Hello', param, 'avec JDBC !!!') INTO param;\n" 
    + "END\n"); 
//APPEL DE LA PROCEDURE 
String sql = "{call hello(?)}"; 
CallableStatement call = connection.prepareCall(sql); 
//passage de la valeur du paramètre 
call.setString(1, " world "); 
//enregistrement du paramètre en tant que paramètre OUT 
call.registerOutParameter(1, Types.VARCHAR); 
//exécution et récupération du résultat 
call.execute(); 
System.out.println(call.getString(1));
Et voici à quoi devrait ressembler le résultat :

Code java : Sélectionner tout
"Hello world avec JDBC !!!"
Fameux non ? ;-)

Mis à jour le 11 avril 2013 Ioan

L'appel d'une fonction grâce aux CallableStatement utilise la syntaxe suivante :

Code java : Sélectionner tout
String sql = "{? = call nomDeLaProcedure[(?, ?, ...)]}";
Le premier paramètre doit être enregistré comme paramètre de sortie :

Code java : Sélectionner tout
1
2
3
4
5
6
String sql = "?= call Hello(?)"; 
CallableStatement statement = connection.prepareCall(sql); 
statement.registerOutParameter(1,Types.VARCHAR); 
statement.setString(2,"world"); 
statement.execute(); 
System.out.println(statement.getString(1));

Mis à jour le 11 avril 2013 Ioan

Cette question a son intérêt, car bien souvent un CallableStatement va renvoyer une valeur par défaut s'il rencontre un type SQL NULL. Ce sera par exemple la chaine vide pour VARCHAR ou 0 pour INTEGER ou NUMERIC. CallableStatement propose donc la méthode wasNull qui renvoie un boolean indiquant si le dernier paramètre de type OUT était NULL. Cette méthode doit être utilisée seulement après l'appel de la méthode get correspondant au paramètre de sortie. Par exemple :

Code java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
String sql = "{getUnNombre(?)}"; 
CallableStatement statement = connection.prepareCall(sql); 
statement.registerOutParameter(1,Types.INTEGER); 
statement.execute(); 
int resultat = statement.getInt(1); 
if(statement.wasNull()){ 
   System.out.pritnln("Le résultat est de type SQL NULL"); 
}else{ 
   System.out.println("Le résultat vaut "+resultat); 
}

Mis à jour le 11 avril 2013 Ioan

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 ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les 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 © 2017 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.

 
Responsables bénévoles de la rubrique Java : Mickael Baron - Robin56 -