JDBC
Java DataBase Connectivity
JDBC
Mme CHALOUAH Anissa
Page | 1
1.JDBC (Java DataBase Connectivity)
1.1.
Probl me
Acc der une base de donn es depuis une application Java.
Application
JAVA
BD
1.2. D finition
JDBC est une API (biblioth que dinterfaces et de classes) java standard qui permet un acc s
homog ne des bases de donn es depuis un programme Java au travers du langage SQL.
Cest de plus une tentative de standardiser lacc s aux bases de donn es car lAPI est
ind pendante du SGBD choisi, pourvu que le pilote JDBC existe pour ce SGBD, et quil
impl mente les classes et interfaces de lAPI JDBC.
1.3.
Avantages et inconv nients du JDBC
Avantages
" Comme JDBC repose sur SQL, cette biblioth que b n ficie de toutes ses fonctionnalit s
prouv es : cr ation et mise jour de tables, s lections avec jointure, transactions, appels des
proc dures stock es.
" La dur e dapprentissage de JDBC est r duite pour les personnes utilisant d j un SGBDR avec
SQL.
" Pour permettre dexploiter leur produit en Java, les diteurs de SGBDR du march (Oracle,
Sybase...) nont qu d velopper un driver JDBC, ensemble de classes qui impl mentent les
interfaces du paquetage java.sql.
" Une application peut se connecter plusieurs SGBDR en m me temps.
" Si votre programme utilise la version standard de SQL, il suffit de changer le driver appropri
en cas de changement de SGBDR.
Mme CHALOUAH Anissa
Page | 2
Inconv nients
" Les instructions SQL tant construites sous forme de cha nes de caract res, leur exactitude ne
peut tre v rifi e ni par le compilateur Java ni par JDBC, mais uniquement par le SGBDR au
moment de leur traitement.
" JDBC noblige pas un diteur de SGBDR impl menter tout SQL dans son driver, ce qui peut
g ner la portabilit dune application Java en cas de changement de SGBDR.
" Bas e sur SQL, JDBC est limit lutilisation de bases de donn es relationnelles : aucune
utilisation de base de donn es objet (SGBDO) nest pr vue, fait tonnant pour un langage objet
comme Java.
" JDBC peut difficilement voluer ind pendamment de SQL.
1.4.
Architecture de la technologie JDBC
1.5.
Pilotes JDBC
L'API JDBC se trouve dans java.sql et les pilotes doivent impl menter l'interface java.sql.Driver.
Il existe quatre types de pilotes jdbc :
" Type 1 : Pont jdbc-odbc (livr en standard, id al comme premier driver sous Windows)
" Type 2 : API native + un peu de java.
" Type 3 : Comme type 2 mais avec un protocole r seau tout en java.
" Type 4 : Protocole natif 100% java.
Les diteurs de SGBDR proposent leurs propres pilotes JDBC.
Mme CHALOUAH Anissa
Page | 3
Figure : Types de pilotes JDBC
2.JDBC et les architectures clients-
serveurs multi-tiers
2.1.
Architecture client-serveur 2/tiers
Dans une architecture client-serveur 2/tiers, un programme client acc de directement une
base de donn es sur une machine distante (le serveur) pour changer des informations via des
commandes SQL JDBC automatiquement traduites dans le langage de requ te propre au SGBD.
Le principal avantage de ce type darchitecture est quen cas de changement de SGBD, il ny a
qu mettre jour ou changer le driver JDBC du cot client. Cependant, pour une grande
diffusion du client, cette architecture devient probl matique, car une telle modification n cessite
la mise jour de chaque client.
Protocole propri taire
C
B
D
J
Application
JAVA
Client
BD
Serveur de BD
Mme CHALOUAH Anissa
Page | 4
2.2.
Architecture 3/tiers
Dans une architecture 3/tiers, un programme client nacc de pas directement la base de
donn es, mais un serveur dapplication qui fait lui-m me les acc s celle-ci. Il y a plusieurs
avantages cette architecture. Tout dabord, il est possible de g rer plus efficacement les
connexions au niveau du serveur dapplication et doptimiser les traitements. De plus,
contrairement larchitecture 2/tiers, un changement de SGBD ne n cessite pas une mise jour
des drivers sur tous les clients, mais seulement sur le serveur dapplication.
Application Java
Navigateur
Applet
Serveur
dapplication
JDBC
Protocole propri taire
BD
Serveur de BD
3.Fonctionnement du JDBC
3.1.
Classes et interfaces de JDBC
a- Interfaces principales
- Driver : renvoie une instance de Connection
-
-
-
-
Connection : connexion une base
Statement : ordre SQL
PreparedStatement : ordre SQL param tr
CallableStatement : proc dure stock e.
- ResultSet : lignes r cup r es par un ordre SELECT
- ResultSetMetaData : description des lignes r cup r es par un SELECT
-
DatabaseMetaData : informations sur la base de donn es
b- Classes principales
- DriverManager : g re les drivers, lance les connexions aux bases
-
-
-
-
Date : date SQL
Time : heures, minutes, secondes SQL
TimeStamp : date et heure avec une pr cision la microseconde
Types : constantes pour d signer les types SQL (pour les conversions avec les types
Java)
Mme CHALOUAH Anissa
Page | 5
Publicité
3.2. Mise en Suvre de JDBC
Figure : Mise en Ruvre JDBC
Avant toute chose, noubliez pas dimporter le package java.sql
import java.sql.*;
1) Chargement du driver JDBC : Disposer du driver sp cifique ou utiliser ODBC sinon, car
le pilote ODBC est dans l'API java.
2) Etablir la connexion au SGBD : Conna tre l'URL de la base et y s'assurer d'avoir un
compte d'acc s username/password.
3) Cr er une requ te (ou instruction SQL)
4) Ex cuter la requ te : Mise feu de la transaction et retour des r sultats
5) Traiter les donn es retourn es
6) Fermer la connexion : Prendre soin de fermer les curseurs de dialogue li s la
connexion
a. Etape 1 : Chargement du Driver
Pour se connecter une base de donn es il est essentiel de charger dans un premier
temps le pilote de la base de donn es laquelle on d sire se connecter gr ce un appel
au DriverManager (gestionnaire de pilotes) :
Class.forName("driver_name ");
Exemples
Chargement du pilote JDBC-ODBC :
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Mme CHALOUAH Anissa
Page | 6
Chargement du pilote pour une base Oracle :
Class.forName("oracle.jdbc.driver.OracleDriver");
Chargement du pilote pour une base PostgreSQL :
Class.forName("org.postgresql.Driver");
Quand une classe Driver est charg e, elle doit cr er une instance delle m me et
senregistrer aupr s du DriverManager
Certains compilateurs refusent cette notation et demande plut t :
Class.forName("driver_name").newInstance();
La m thode static forName() de la classe Class peut lever l'exception
java.lang.ClassNotFoundException.
Exemple
try {
Class.forName("com.mysql.jdbc.Driver");
}
catch (ClassNotFoundException e) {
System.err.println("Driver loading error : " + e);
}
b. Etape 2 : Connexion la base
Etablir une connexion en utilisant la classe java.sql.DriverManager. Son r le est
de cr er des connexions en utilisant le driver pr alablement charg . Cette classe dispose
d'une m thode statique getConnection() prenant en param tre l'URL de connexion,
le nom d'utilisateur et le mot de passe.
URL de la forme :
jdbc:<sous-protocole>:<nom-BD>;param=valeur, ...
L URL sp cifie :
o
o
o
l'utilisation de JDBC (protocole)
le driver ou le type du SGBDR (sous-protocole)
le nom de la base locale ou distante avec des param tres de configuration
ventuels : nom utilisateur, mot de passe, &
Exemple dURL
jdbc:odbc:ma_base
jdbc:pg95:mabase?username=toto:password=titi
Ouverture de la connexion :
Connection con = DriverManager.getConnection(url, "myLogin", "myPassword");
La m thode getConnection() peut
lever une exception de
la classe
java.sql.SQLException.
Mme CHALOUAH Anissa
Page | 7
Exemple
String url = "jdbc:mysql://localhost/tp";
try {
Connection con =
DriverManager.getConnection(url, "root", "secret");
}
catch (SQLException e) {
System.err.println("Error opening SQL connection: " +
e.getMessage()); }
c. Etape 3 : Etablir une requ te SQL
Il y a 3 types de requ tes :
Statement pour les ordres SQL simple. Ces tats sont construits par la m thode
createStatement appliqu e la connexion.
PreparedStatement pour les ordres SQL param tr s. Ces tats sont construits
par la m thode prepareStatement appliqu e la connexion.
CallableStatement pour les proc dures ou fonctions catalogu es (PL/SQL, C,
Java, ..). Ces tats sont construits par la m thode prepareCall appliqu e la
connexion.
Figure : Connexion et requ tes
Sil ne doit plus tre utilis dans la suite du code Java, chaque objet de type Statement,
PreparedStatement ou CallableStatement devra tre ferm laide de la
m thode close.
Exemple avec Statement
try {
Statement stmt = conn.createStatement();
}
catch (SQLException e) {
System.err.println("Error creating SQL statement: " +
e.getMessage());
}
Remarque
Il n'est pas n cessaire de d finir un objet Statement pour chaque ordre SQL : il est
possible d'en d finir un et de le r utiliser
Mme CHALOUAH Anissa
Page | 8
d. Etape 4 : Ex cution d'une requ te de type Statement
Il y a 3 types d'ex cutions :
executeQuery : pour les requ tes (SELECT) accessibles par la m thode
Statement.executeQuery(). Cette m thode retourne un r sultat de type
java.sql.ResultSet contenant les lignes s lectionn es.
executeUpdate : pour les requ tes INSERT, UPDATE, DELETE, CREATE TABLE
et DROP TABLE accessibles par la m thode Statement.executeUpdate().
Cette m thode retourne un r sultat de type int correspondant au nombre de
lignes affect es par la requ te.
execute : pour quelques cas rares (proc dures stock es)
Exemple avec executeQuery
String query = "SELECT CIN, name,email FROM users;";
try {
ResultSet resultSet = stmt.executeQuery(query);
}
catch (SQLException e) {
System.err.println("Error executing query: " +
e.getMessage());
}
Exemple avec executeUpdate
String query = "UPDATE users SET
email='[email protected]' WHERE nom='SMITH';";
Publicité
try {
int result = stmt.executeUpdate(query);
}
catch (SQLException e) {
System.err.println("Error executing query: " +
e.getMessage());
}
int count =
stmt.executeUpdate(
"DELETE FROM ENTREPRISES WHERE CODEPOST LIKE '77%'");
System.out.println("Il y a eu " + count + " lignes supprim es.");
e. Etape 5 : Traitement des r sultats
L'objet ResultSet permet d'avoir un acc s aux donn es r sultantes de notre requ te
en mode ligne par ligne. La m thode ResultSet.next() permet de passer d'une ligne
la suivante. Cette m thode renvoie false dans le cas o il n'y a pas de ligne suivante. Il
est n cessaire d'appeler au moins une fois cette m thode, le curseur est plac au d part
avant la premi re ligne (si elle existe).
Mme CHALOUAH Anissa
Page | 9
La
classe ResultSet dispose aussi d'un
certain nombres d'accesseurs
(ResultSet.getXXX()) qui permettent de r cup rer le r sultat contenu dans une
colonne s lectionn e.
On peut utiliser soit le num ro de la colonne d sir e, soit son nom avec l'accesseur. La
num rotation des colonnes commence 1.
XXX correspond au type de la colonne. Le tableau suivant pr cise les relations entre type
SQL, type JDBC et m thode appeler sur l'objet ResultSet.
Types
char
varchar
integer
double,
float
Date
Blob
Type SQL
Type JDBC
M thode d'acc s
String
String
Integer
Double
Float
Date
Blob
getString()
getString()
getInt()
getDouble()
getDouble()
getDate()
getBlob()
La m thode getString() permet d'obtenir la valeur d'un champ de n'importe quel
type.
Exemple
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
try {
while (rs.next()) {
System.out.println(rs.getInt("CIN")+" " +
rs.getString("NOM") +" " + rs.getString("EMAIL"));
}
}
catch (SQLException e) {
System.err.println("Error browsing query results: " +
e.getMessage());
}
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
// Pour acc der chacun des tuples du r sultat de la requ te :
&
while (rs.next()) {
int cin=rs.getInt(1) ;
String nom = rs.getString(2);
String prenom = rs.getString(3);
java.sql.Date date_nais = rs.getDate(4);
...
}
Mme CHALOUAH Anissa
Page | 10
f. Etape 6 : Fermeture des diff rents espaces
Pour terminer proprement un traitement, il faut fermer les diff rents espaces ouverts
sinon le garbage collector sen occupera mais moins efficace
Chaque objet poss de une m thode close() :
resultset.close();
statement.close();
connection.close();
Exemple de programme :
Le programme ci-dessous utilise une base nomm e Refugedb . Cette base de donn es contient
une table nomm e ANIMAL; voici un script de cr ation :
CREATE TABLE ANIMAL (
id INTEGER PRIMARY KEY,
categorie VARCHAR NOT NULL,
nom VARCHAR, race VARCHAR,
sexe CHAR,
date_nais DATE,
id_proprio INTEGER,
present BIT
)
INSERT INTO ANIMAL
VALUES (1,'CRM', 'kiki','berger','M','2000-2-21',21,false)
INSERT INTO ANIMAL
VALUES (2,'CRM','rex','caniche','M','1996-12-2',11,true)
...
Lorsque l'on acc de une base de donn es, une gestion des exceptions s'av re n cessaire car de
multiples probl mes peuvent survenir : le pilote ne peut tre charg (introuvable ?), connexion
refus e, requ te SQL mal form e... Voici l'exemple complet.
1 import java.sql.*;
2
3 public class TestAnimal {
4 public void test() {
5 final String driver = "org.hsqldb.jdbcDriver";
6 final String url = "jdbc:hsqldb:/home/kpu/Refuge/Refugedb";
7 final String user = "sa";
8 final String password ="";
9
10 Statement st = null;
11 Connection con = null;
12 ResultSet rs = null;
13 String sql = "";
14 try {
15 Class.forName(driver).newInstance();
16 con = DriverManager.getConnection(url, user, password);
17 st = con.createStatement();
18 sql = "SELECT * FROM ANIMAL";
Mme CHALOUAH Anissa
Page | 11
19 rs = st.executeQuery(sql);
Publicité
20 System.out.println("ID\tTYPE\tNOM\t\tRACE\t");
21 while (rs.next()) {
22 System.out.print(rs.getInt(1)+"\t");
23 // ATTENTION, les indices commencent 1.
24 System.out.print(rs.getString(2)+"\t");
25 System.out.print(rs.getString("nom")+"\t\t");
26 System.out.println(rs.getString("race")+"\t");
27 }//while
28 }
29 catch (ClassNotFoundException e) {
30 System.err.println("Classe non trouv e : " + driver );
31 }
32 catch (SQLException e) {
33 System.err.println("SQL erreur : "+
sql + " " + e.getMessage());
34 }
35 catch (Exception e) {
36 System.err.println("Erreur : "+ e);
37 }
38
39 finally {
40 try { if (con != null) { con.close(); } }
41 catch (Exception e) { System.err.println(e); }
42 }
43 }
44 static public void main(String[] arg) {
45 TestAnimal app = new TestAnimal();
46 app.test(); }}
Figure : Sch ma r capitulatif de la mise en Suvre JDBC
Mme CHALOUAH Anissa
Page | 12
3.3.
Acc s aux m ta-donn es
JDBC permet de r cup rer des informations :
sur le type de donn es que l'on vient de r cup rer par un SELECT (interface
ResultSetMetaData)
mais aussi sur la base elle-m me (interface DatabaseMetaData)
a. Interface ResultSetMetaData
La m thode getMetaData() permet dobtenir des informations sur les types de
donn es du ResultSet
Elle renvoie des instances de ResultSetMetaData
on peut conna tre entre autres :
le nombre de colonne : getColumnCount()
o
le nom dune colonne : getColumnName(int col)
o
le nom de la table : getTableName(int col)
o
o
le type de donn e SQL de la colonne : int getColumnType(int)
o si un NULL SQL peut tre stock dans une colonne : isNullable()
Exemple
ResultSet rs = st.executeQuery("SELECT * FROM users");
ResultSetMetaData rsmd = rs.getMetaData();
int nbColonnes = rsmd.getColumnCount();
for (int i = 1; i <= nbColonnes; i++) {
String typeColonne = rsmd.getColumnType(i);
String nomColonne= rsmd.getColumnName(i);
System.out.println("Colonne " + i+ " de nom " + nomColonne
+ " de type " + typeColonne);
}
b. Interface DatabaseMetaData
Elle permet de donner des informations sur la base de donn es
M thode getMetaData() de lobjet Connection
D pend du SGBD avec lequel on travaille
Elle renvoie des instances de DatabaseMetaData
on peut conna tre entre autres :
o
o
les tables de la base : getTables()
le nom de lutilisateur : getUserName()
Exemple
private DatabaseMetaData metaData;
private java.awt.List listTables= new List(10);
&
String[] types = { "TABLE", "VIEW" };
String nomTables;
&
metaData = conn.getMetaData();
ResultSet rs =
metaData.getTables(null, null, "%", types);
Mme CHALOUAH Anissa
Page | 13
while (rs.next()) {
nomTable = rs.getString(3);
listTables.add(nomTable);
}
3.4.
Requ tes pr compil s (PreparedStatement)
L'interface PreparedStatement d finit les m thodes pour un objet qui va encapsuler
une requ te pr compil e. Ce type de requ te est particuli rement adapt pour une
ex cution r p t e d'une m me requ te avec des param tres diff rents.
Cette interface h rite de l'interface Statement.
Lors de l'utilisation d'un objet de type PreparedStatement, la requ te est envoy e au
moteur de la base de donn es pour que celui ci pr pare son ex cution.
Un objet qui impl mente l'interface PreparedStatement est obtenu en utilisant la
m thode prepareStatement() d'un objet de type Connection. Cette m thode
attend en param tre une cha ne de caract res contenant la requ te SQL. Dans cette
chaine, chaque param tre est repr sent par un caract re ?
Exemple
PreparedStatement ps =
conn.prepareStatement("SELECT * FROM users "+
"WHERE nom = ? ");
Un ensemble de m thode setXXX(int, valeur) (ou XXX repr sente un type primitif
ou certains objets tel que String, Date, Object, ...) permet de fournir les valeurs de chaque
param tre d fini dans la requ te.
o
Le premier param tre pr cise le num ro du param tre dont la m thode va
fournir la valeur.
o Le second param tre pr cise cette valeur.
Exemple
PreparedStatement pstmt = conn.prepareStatement( "UPDATE emp SET sal
= ? " + "WHERE grade = ?");
for (int i=0; i<10; i++) {
pstmt.setDouble(1,employe .getSalaire());
pstmt.setString(2, employe .getNom());
int count = pstmt.executeUpdate();
}
Exemple
import java.sql.*;
public class TestJDBC2 {
private static void arret(String message) {
System.err.println(message);
System.exit(99);}
Mme CHALOUAH Anissa
Page | 14
Publicité
public static void main(java.lang.String[] args) {
Connection con = null;
ResultSet resultats = null;
String requete = "";
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
} catch (ClassNotFoundException e) {
arret("Impossible de charger le pilote jdbc:odbc");
}
System.out.println("connexion a la base de donn es");
try {
String DBurl = "jdbc:odbc:testDB";
con = DriverManager.getConnection(DBurl);
PreparedStatement recherchePersonne =
con.prepareStatement("SELECT * FROM personnes WHERE nom_personne =
?");
recherchePersonne.setString(1, "Ali");
resultats = recherchePersonne.executeQuery();
affiche("parcours des donn es retourn es");
boolean encore = resultats.next();
while (encore) {
System.out.print(resultats.getInt(1) + " :
"+resultats.getString(2)+" "+
resultats.getString(3)+"("+resultats.getDate(4)+")");
System.out.println();
encore = resultats.next();
}
resultats.close();
} catch (SQLException e) {
arret(e.getMessage());
}
System.out.println("fin du programme");
System.exit(0);
}
}
3.5.
Proc dure stock e (CallableStatement)
Rappel
Les proc dures stock es permettent de fournir la m me fonctionnalit plusieurs
utilisateurs
Les proc dures sont stock es dans la base c t serveur
JDBC offre une interface d di e
CallableStatement
d rive de linterface PreparedStatement
g re le retour de valeur avec ResultSet
Mme CHALOUAH Anissa
Page | 15
Comment
cr ation dun objet CallableStatement
en utlisant Connection.prepareCall(&)
La requ te doit tre format e
encadr e par des accolades {&}
utilisation du pr fixe call
Trois modes pour l'appel
la proc dure renvoie une valeur
{ ? = call nomProc dure(?,?,&)}
la proc dure ne renvoie aucune valeur
{ call nomProc dure(?,?,&)}
si on ne lui passe aucun param tre
{ call nomProc dure }
Passage de param tres possible comme pour PreparedStatement
Exemple
Sans valeur de retour
CallableStatement testCall;
testCall = conn.prepareCall("{ call setSalary(?,?) }");
testCall.setString(1, " EUR");
testCall.setLong(2, 2000);
testCall.execute();
Un PreparedStatement peut retourner des donn es gr ce un ResultSet
Les proc dures stock es tendent le mod le
o appel de la proc dure pr c d du passage des param tres in et out gr ce aux
o
m thodes setXXX()
type des param tres out et in/out gr ce la m thode
registerOutParameter()
o ex cution de la requ te gr ce executeQuery(), executeUpdate() ou
execute()
r cup ration des param tres out et in/out gr ce aux m thodes getXXX()
o
Exemple
On consid re la proc dure stock e
create or replace procedure augmentation
(unDept in integer,
pourcentage in number,
cout out number) is
begin
update emp
set sal = sal * (1 + pourcentage / 100)
where dept = unDept;
select sum(sal) * pourcentage / 100 into cout
Mme CHALOUAH Anissa
Page | 16
from emp
where dept = unDept;
end;
CallableStatement csmt = conn.prepareCall(
"{ call augmentation(?, ?, ?) }");
// 2 chiffres apr s la virgule pour 3 me param tre
csmt.registerOutParameter(3, Types.DECIMAL, 2);
// Augmentation de 2,5 % des salaires du dept 10
csmt.setInt(1, 10);
csmt.setDouble(2, 2.5);
csmt.executeQuery();
double cout = csmt.getDouble(3);
System.out.println("Cout total augmentation : "
+ cout);
Elles peuvent retourner n'importe quel type de donn es y compris des ResultSet
utiliser executeQuery() au lieu de execute()
r cup ration d'un ResultSet normal
o utilisable comme d'habitude
o permet de sauvegarder la requ te SQL au niveau de la base
CallableStatement csmt;
csmt = myConn.prepareCall("{ call getDetails(?) }");
ResultSet rs;
csmt.setLong(1, 1000000);
rs = csmt.executeQuery();
Mme CHALOUAH Anissa
Page | 17