Académique Documents
Professionnel Documents
Culture Documents
1
Type 1 : pont JDBC-ODBC Type 2 : utilise une API native
Application Java Application Java
Driver JDBC (en Java) Partie en Java (en Java) Driver
Les méthodes du driver (pas en Java)
Driver ODBC (pas en Java) Partie native
JDBC font appel à des
Les méthodes du driver JDBC fonctions d'une API du
font appel à des fonctions SGBD écrite dans un autre Protocole du SGBD
en langage C d'un driver ODBC langage que Java
SGBD SGBD
SGBD SGBD
R. Grin JDBC page 9 R. Grin JDBC page 10
2
Driver de type 4 et applet untrusted
Code Java
Applet
Le serveur HTTP doit
Driver en Java
être sur la même machine
que le SGBD Travailler avec JDBC
connexion par socket
Serveur HTTP
SGBD
3
Avertissement
Nous étudierons tout d'abord les classes et Dans la suite du cours on utilise des raccourcis
méthodes de base de JDBC tels que « instance de Connection »
Des nouvelles possibilités de JDBC 2 et 3, en Comme Connection est une interface, il faut
particulier celles qui sont liées à SQL3, seront traduire par « instance d’une classe qui
abordées dans les parties « JDBC avancé » et implémente Connection »
« JDBC et objet-relationnel »
CallableStatement : procédure stockée sur le SGBD TimeStamp : date et heure, avec une précision à la
4
Exceptions de JDBC 4 (2) Chaînage des exceptions
Classes filles de SQLNonTransientException :
SQLDataException, Une requête SQL peut provoquer plusieurs
SQLFeatureNotSupportedException, exceptions
SQLIntegrityConstraintViolationException, On peut obtenir la prochaine exception par la
SQLInvalidAuthorizationException, méthode getNextException()
SQLNonTransientConnectionException, Une exception peut avoir une cause ; on l'obtient
SQLSyntaxErrorException par la méthode getCause()
Classes filles de SQLTransientException : Toutes ces exceptions peuvent être parcourues
SQLTimeoutException, par une boucle « for-each » :
SQLTransactionRollbackException, catch(SQLException ex) {
SQLTransientConnectionException for (Throwable e : ex) { … }
R. Grin JDBC page 25 R. Grin JDBC page 26
5
Obtenir une connexion Connexions et threads
Pour obtenir une connexion à un SGBD, on demande Les connexions sont des ressources coûteuses,
cette connexion à la classe gestionnaire de drivers : et surtout longues à obtenir
static final String url =
"jdbc:oracle:thin:@sirocco.unice.fr:1521:INFO"; On peut donc être tenté de les réutiliser dans
Connection conn = plusieurs threads différents
DriverManager.getConnection(url,
Mais, attention, les connexions ne peuvent être
"toto", "mdp");
partagées par plusieurs threads
La classe DriverManager s'adresse à tour de rôle à
À la place, utiliser les pools de connexions fournis
tous les drivers qui se sont enregistrés (méthode
avec les « sources de données » (étudiées dans
connect), jusqu'à ce qu'un driver lui fournisse une
une autre partie du cours)
connexion (ne renvoie pas null)
R. Grin JDBC page 31 R. Grin JDBC page 32
n conn.rollback()
6
Consultation des données (SELECT) Interface ResultSet
executeQuery() renvoie une instance de
Statement stmt = conn.createStatement(); ResultSet
// rset contient les lignes renvoyées ResultSet va permettre de parcourir toutes les
ResultSet rset = lignes renvoyées par le select
stmt.executeQuery("SELECT nomE FROM emp");
Au début, ResultSet est positionné avant la
// On récupère chaque ligne une à une
première ligne et il faut donc commencer par le
while (rset.next())
faire avancer à la première ligne en appelant la
System.out.println (rset.getString(1));
méthode next()
// ou . . . (rset.getString("nomE"));
stmt.close(); La première colonne a le numéro 1
Cette méthode permet de passer à la ligne
suivante ; elle renvoie true si cette ligne
Voir plus loin le transparent sur la suivante existe et false sinon
R.fermeture
Grin des ressources JDBC page 37 R. Grin JDBC page 38
7
Correspondances Correspondances avec getXXX()
entre types Java et SQL On a une grande latitude ; ainsi, presque tous les types
SQL peuvent être retrouvés par getString()
Il reste le problème de la correspondance entre les
Cependant, des méthodes sont recommandées ; voici
types Java et les types SQL des exemples :
Dans un programme JDBC, les méthodes getXXX, n CHAR et VARCHAR : getString, LONGVARCHAR :
setXXX servent à préciser cette correspondance getAsciiStream et getCharacterStream
Par exemple, getString indique que l’on veut n BINARY et VARBINARY : getBytes, LONGVARBINARY :
getBinaryStream
récupérer la donnée SQL dans une String n REAL : getFloat, DOUBLE et FLOAT : getDouble
C'est le rôle du driver particulier à chaque SGBD de n DECIMAL et NUMERIC : getBigDecimal
faire les traductions correspondantes ; une exception n DATE : getDate, TIME : getTime, TIMESTAMP :
peut être lancée si ça n’est pas possible getTimestamp
Valeur NULL
Manipulation des dates
Statement stmt = conn.createStatement();
ResultSet rset = stmt.executeQuery(
Un petit rappel sur les dates en Java :
"SELECT nomE, comm FROM emp");
n mise en forme avec la classe
while (rset.next()) {
java.text.DateFormat nom = rset.getString("nomE");
n calculs sur les dates avec la classe commission = rset.getDouble("comm");
java.util.Calendar if (rset.wasNull())
Voir le cours sur les dates dans le support System.out.println(nom + ": pas de comm");
else
« Compléments divers »
System.out.println(nom + " a " + commission
+ " € de commission");
}
8
Modification des données (INSERT, Instruction SQL paramétrée
UPDATE, DELETE)
La plupart des SGBD (dont Oracle) peuvent
Statement stmt = conn.createStatement(); n'analyser qu'une seule fois une requête
String ville = "NICE"; exécutée un grand nombre de fois durant une
int nbLignesModifiees = stmt.executeUpdate( connexion
"INSERT INTO dept (dept, nomD, lieu) " JDBC permet de profiter de ce type de
+ "VALUES (70, 'DIRECTION'," fonctionnalité par l'utilisation de requêtes
+ "'" + ville + "')"); paramétrées ou de procédures stockées
N'oubliez pas
stmt.close(); l'espace ! Les requêtes paramétrées sont associées aux
instances de l'interface PreparedStatement qui
hérite de l'interface Statement
R. Grin JDBC page 49 R. Grin JDBC page 50
9
Avantages des PreparedStatement Procédures stockées
Leur traitement est plus rapide s’ils sont utilisés
plusieurs fois avec plusieurs paramètres Les procédures stockées permettent non
Ils améliorent aussi la portabilité car les méthodes seulement de précompiler des ordres SQL mais
setXXX gèrent les différences entre SGBD aussi de les regrouper
En effet, les SGBD n’utilisent pas tous les mêmes Comme les accès réseau aux bases de données
formats de date ('JJ/MM/AA' ou 'AAAA-MM-JJ' ralentissent les applications, les procédures
par exemple) ou de chaînes de caractères (pour stockées permettent souvent d’améliorer les
les caractères d’« échappement ») performances
Mais on peut aussi utiliser pour cela la syntaxe Mais elles nuisent aussi souvent à la portabilité
(un peu lourde) « SQL Escape » (voir plus loin) des applications
Ils évitent l'injection de code SQL
R. Grin JDBC page 55 R. Grin JDBC page 56
10
Lancement d'une procédure stockée Utilisation d'une procédure stockée
L'appel de la procédure est précédé du passage à la CallableStatement csmt = conn.prepareCall(
procédure des paramètres « in » et « in/out » par les "{ call augmenter(?, ?, ?) }");
// 2 chiffres après la virgule pour 3ème paramètre
méthodes setXXX() (idem requêtes paramétrées)
csmt.registerOutParameter(3, Types.DECIMAL, 2);
On doit indiquer le type des paramètres « out » et // Augmentation de 2,5 % des salaires du dept 10
« in/out » par la méthode registerOutParameter() csmt.setInt(1, 10);
Ensuite on lance la procédure par une des méthodes csmt.setDouble(2, 2.5);
executeQuery(), executeUpdate() ou execute(), suivant csmt.executeQuery(); // ou execute()
le type des commandes SQL que la procédure contient double cout = csmt.getDouble(3);
On récupère les paramètres « out » et « in/out » par les System.out.println("Cout total augmentation : "
méthodes getXXX() (idem requêtes paramétrées) + cout);
11
Fonction qui renvoie un curseur Créer le type référence de curseur
Il faut Créer un nom de type pour la référence de curseur
1. Créer un type pour la référence de curseur qu’on va renvoyer
qu’on va renvoyer Pour utiliser ensuite le type, il faut le créer dans un
2. Créer la fonction qui renvoie la référence de paquetage :
create or replace package Types AS
curseur
type curseur_type is ref cursor;
end Types;
12
Syntaxe spéciale de JDBC
Les Meta données
(« SQL Escape syntax »)
Comme avec les procédures stockées, JDBC a une JDBC permet de récupérer des informations sur
syntaxe spéciale pour ne pas dépendre de le type de données que l'on vient de récupérer
particularités des différents SGBD : par un SELECT (interface ResultSetMetaData),
n dates : {d '2000-10-5'} mais aussi sur la base de données elle-même
n appels de fonctions : {fn concat("Hot", "Java")} (interface DatabaseMetaData)
n jointures externes : Les données que l'on peut récupérer avec
con.createStatement("SELECT * FROM"
+ " {oj EMP RIGHT OUTER JOIN DEPT" DatabaseMetaData dépendent du SGBD avec
+ " ON EMP.DEPT = DEPT.DEPT}"); lequel on travaille
n caractère d’échappement utilisé par LIKE :
WHERE Id LIKE '_%\\' {escape '\'}
R. Grin JDBC page 73 R. Grin JDBC page 74
ResultSetMetaData DatabaseMetaData
private DatabaseMetaData metaData;
ResultSet rs =
private java.awt.List listTables = new List(10);
stmt.executeQuery("SELECT * FROM emp");
. . .
ResultSetMetaData rsmd = rs.getMetaData();
metaData = conn.getMetaData();
int nbColonnes = rsmd.getColumnCount();
String[] types = { "TABLE", "VIEW" };
for (int i = 1; i <= nbColonnes; i++) {
ResultSet rs =
String typeColonne = rsmd.getColumnTypeName(i);
metaData.getTables(null, null, "%", types);
String nomColonne = rsmd.getColumnName(i);
String nomTables;
System.out.println("Colonne " + i + " de nom "
while (rs.next()) { Joker pour
+ nomColonne + " de type " noms des
nomTable = rs.getString(3);
+ typeColonne); tables et vues
listTables.add(nomTable);
}
}
R. Grin JDBC page 75 R. Grin JDBC page 76
13