Académique Documents
Professionnel Documents
Culture Documents
1/58
JDBC
(2e partie)
Bibliographies: Pour cette deuxime partie de ce cours, une revue littraire a t ralise partir des transparents se trouvant la plus part dans les deux documents :
http://deptinfo.unice.fr/~grin/messupports/trjdbcA.pdf http://www-sop.inria.fr/semir/personnel/Patrick.Itey/cours/java-bd.html
Le reste est venu des liens et livres suivants : Site web de SUN sur les JDBC: http://java.sun.com/products/jdbc Les livres : Database Programming with JDBC and Java de George Reese, OReilly. 2nd dition. Core Java 2 de C. S. Horstmann, G. Cornell ; volume 2.
Mohamed N. Lokbani
v1.01
2/58
Pourquoi JDBC
Pendant des annes, les programmeurs cods des outils daccs des bases de donnes en utilisant des outils fournis par les distributeurs (vendeurs, qui sont parfois les concepteurs) de ces bases. Ces outils prenaient la forme de APIs codes en C/C++, ayant des spcifications propres elles. Les distributeurs de bdd fournissaient parfois des prprocesseurs o le programmeur devait inclure ses requtes la base de donnes dans la logique du concepteur de ces prprocesseurs.
Mohamed N. Lokbani
v1.01
3/58
Le but recherch Permettre aux programmeurs dcrire un code indpendant de la base de donnes et du moyen de connectivit utilis. Vu les difficults rencontres avec dautres langages cause des API trop spcifiques la base de donnes. Pourquoi pas Java? robuste et scuris, facile comprendre, automatiquement tlchargeable par le rseau, permettant diverses oprations via le net etc.
Mohamed N. Lokbani
v1.01
4/58
Java oui, mais est-ce possible ? Quavons nous besoin rellement ? - Faire des requtes SQL. SQL tant le langage permettant de dialoguer avec un SGBDR. - Prendre cette requte et la transfrer indpendamment du systme et du SGBDR? telle quelle
Mohamed N. Lokbani
v1.01
5/58
Serveur Oracle
Serveur Sybase
Serveur DB2
Mohamed N. Lokbani
v1.01
6/58
Le driver et son rle Chaque base de donnes utilise un pilote (driver) qui lui est propre et qui permet de convertir les requtes dans le langage natif du SGBDR. Les drivers dpendent du SGBD auquel ils permettent d'accder Tous les SGBD importants du march ont un (et mme plusieurs) driver, fourni par l'diteur du SGBD ou par des diteurs de logiciels indpendants.
Mohamed N. Lokbani
v1.01
7/58
Et la Java la dedans JDBC (Java Database Connectivity), est un ensemble de classes Java qui permet de se connecter une base de donnes distante sur le rseau, et dinterroger cette base afin den extraire des donnes. JDBC est fourni par le paquetage java.sql Ce paquetage permet de formuler et grer les requtes aux bases de donnes relationnelles Ce paquetage contient un grand nombre d'interfaces et quelques classes.
Mohamed N. Lokbani
v1.01
8/58
8 interfaces dfinissent les objets ncessaires : la connexion une base loigne et aux cration et excution de requtes SQL Les interfaces imposent l'API pour travailler avec JDBC. JDBC ne fournit pas les classes qui implantent les interfaces Pour travailler avec un SGBD ; il faut disposer de classes qui implantent les interfaces de JDBC. Un ensemble de telles classes est dsign sous le nom de driver (la classe qui implante l'interface Driver de JDBC y joue un rle important).
Mohamed N. Lokbani v1.01 JDBC -2e partie-
9/58
Les avantages de JDBC - JDBC offre une intgration trs troite du client et des modules chargs de laccs la base. Cela permet de limiter le trafic rseau. - JDBC est compltement indpendant de tout SGBD: la mme application peut tre utilise pour accder une base ORACLE, SYBASE, MySQL, etc. Consquences : pas besoin dapprendre une nouvelle API quand on change de systme, et rutilisation totale du code. - Enfin, JDBC est relativement simple, beaucoup plus simple, par exemple, que linterface C+SQL propose par les SGBD relationnels.
Mohamed N. Lokbani v1.01 JDBC -2e partie-
10/58
Types de drivers
Type 1 : pont JDBC-ODBC Type 2 : driver qui fait appel des fonctions natives non Java (le plus souvent en langage C) de l'API du SGBD que l'on veut utiliser Type 3 : driver qui permet l'utilisation d'un serveur middleware (application intermdiaire) d'accs plusieurs types de sources de donnes Type 4 : driver crit entirement en Java, qui utilise le protocole rseau du SGBD.
Mohamed N. Lokbani
v1.01
11/58
Type 1 Le driver accde un SGBDR en passant par les drivers ODBC (standard Microsoft) via un pont JDBC-ODBC : les appels JDBC sont traduits en appels ODBC presque tous les SGBDR sont accessibles (monde Windows) Application Java Driver JDBC (Java) Driver ODBC (Non Java)
SGBD
Mohamed N. Lokbani
v1.01
12/58
ncessite lemploi dune librairie native (code C) ne peut tre utilis par des applets (scurit) est fourni par SUN avec le JDK sun.jdbc.odbc.JdbcOdbcDriver Open DataBase Connectivity (ODBC) permet daccder la plupart des SGBD dans le monde Windows, dfinit un format de communication standard entre les clients Windows et les serveurs de bases de donnes,
Mohamed N. Lokbani
v1.01
13/58
est devenu un standard de fait du monde Windows, tous les constructeurs de SGBD fournissent un driver ODBC. Avantages : possibilit dcrire des applications accdant des donnes rparties entre plusieurs sources htrognes on dveloppe lapplication sans se soucier de la source de donnes la base de donnes utilise ct serveur peut tre interchange sans aucune modification du dveloppement fait dans la partie cliente.
Mohamed N. Lokbani v1.01 JDBC -2e partie-
14/58
Inconvnient : Ne convient pas au applet (scurit). interdiction de charger du code natif dans la mmoire vive de la plateforme. TYPE 2 Driver dAPI natif : fait appel des fonctions natives (non Java) de l API du SGBDR gre des appels C/C++ directement avec la base
Mohamed N. Lokbani v1.01
Application Java Partie en Java Partie native Protocole du SGBD Driver SGBD
JDBC -2e partie-
15/58
fourni par les diteurs de SGBD et gnralement payant ne convient pas aux applets (scurit) Type 3 Pilote tout Java ou 100% Java interagit avec une API rseau gnrique (Sockets) et communique avec une application intermdiaire (middleware) sur le serveur, le middleware accde par un moyen quelconque (par exple JDBC si crit en Java) aux diffrents SGBDR
Mohamed N. Lokbani
v1.01
16/58
portable car entirement crit en Java pour applets et applications Application Java Driver en Java Protocole du serveur Middleware Serveur middleware
SGBD
Mohamed N. Lokbani
v1.01
17/58
Type 4 Driver 100% Java mais utilisant le protocole rseau du SGBDR interagit avec la base de donnes via des sockets gnralement fourni par lditeur aucun problme dexcution pour une applet si le SGBDR est install au mme endroit que le serveur Web scurit pour lutilisation des sockets : une applet ne peut ouvrir une connexion que sur la machine o elle est hberge
Mohamed N. Lokbani
v1.01
18/58
SGBD
Mohamed N. Lokbani
v1.01
19/58
Types de drivers et applet untrusted Une application Java peut travailler avec tous les types de drivers Pour une applet (untrusted) : Une applet ne peut pas charger distance du code natif (non Java) ; elle ne peut donc pas utiliser les drivers de type 1 et 2 Pour des raisons de scurit, une applet untrusted ne peut changer des donnes par sockets qu'avec la machine d'o elle provient, ce qui implique des contraintes avec les drivers de type 3 et 4
Mohamed N. Lokbani
v1.01
20/58
Applet
Serveur HTTP
Serveur middleware
SGBD
Mohamed N. Lokbani
v1.01
21/58
Applet
Serveur HTTP
SGBD
Mohamed N. Lokbani
v1.01
22/58
Utilisez les servlets Constitue une autre solution pour accder une base de donnes travers le Web Les servlets sont le pendant des applets ct serveur : programmes Java travaillant directement avec le serveur Web pas de contraintes de scurit comme les applets peuvent gnrer des pages HTML contenant les donnes rcupres grce JDBC (par exple)
Mohamed N. Lokbani
v1.01
23/58
La pratique des JDBC 0. Importer le package java.sql et configuration des paths 1. Enregistrer le driver JDBC 2. tablir la connexion la base de donnes 3. Crer une zone de description de requte 4. Excuter la requte 5. Traiter les donnes retournes 6. Fermer les diffrents espaces
Mohamed N. Lokbani v1.01 JDBC -2e partie-
24/58
Les classes et interfaces de JDBC Liste des interfaces principales Driver : renvoie une instance de Connection Connection : connexion une base Statement : ordre SQL PreparedStatement : ordre SQL paramtr CallableStatement : procdure stocke sur le SGBD ResultSet : lignes rcupres par un ordre SELECT ResultSetMetaData : description des lignes rcupres par un SELECT DatabaseMetaData : informations sur la base de donnes
Mohamed N. Lokbani
v1.01
25/58
Liste des classes principales DriverManager : gre les drivers, lance les connexions aux bases Date : date SQL Time : heures, minutes, secondes SQL TimeStamp : comme Time avec une prcision la microseconde Types : constantes pour dsigner les types SQL (pour les conversions avec les types Java)
Mohamed N. Lokbani
v1.01
26/58
Liste des exceptions SQLException : erreurs SQL est leve ds quune connexion ou un ordre SQL ne se passe pas correctement la mthode getMessage() donne le message en clair de lerreur SQLWarning : avertissements SQL DataTruncation : avertit quand une valeur est tronque lors d'un transfert entre Java et le SGBD
Mohamed N. Lokbani
v1.01
27/58
0. Importer le package java.sql et configuration des paths Mysql/Oracle puis ODBC, pas de DB2! MySql paquetage www.mysql.org suivre les indications dinstallation, la configuration des chemins, et le tlchargement du driver mm.mysql.jdb-xxx Oracle voir la dmo#11, pour la partie sqlplus et dmo#12 pour la partie JDBC.
Mohamed N. Lokbani v1.01 JDBC -2e partie-
28/58
import java.sql.*;
Mohamed N. Lokbani
v1.01
29/58
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; /** * Example 3.2. Livre Oreilly : * Database programming with JDBC and Java ; page 37-38 */ public class SimpleConnection { static public void main(String args[]) { Connection connection = null; // Vrification des paramtres se trouvant // sur la ligne de commande if( args.length != 4 ) { System.out.println( "Syntax: java SimpleConnection " + "DRIVER URL UID PASSWORD"); return; }
Mohamed N. Lokbani v1.01 JDBC -2e partie-
30/58
try { // chargement du driver Class.forName(args[0]).newInstance(); } catch( Exception e ) { // prb. charg. du driver // class inexistante? e.printStackTrace(); return; } try { connection = DriverManager.getConnection( args[1], args[2], args[3]); System.out.println("Connection successful!"); // blablabla les requtes faire!!!! } catch( SQLException e ) { e.printStackTrace(); }
Mohamed N. Lokbani
v1.01
31/58
Mohamed N. Lokbani
v1.01
32/58
1. Enregistrer le driver JDBC Mthode forName() de la classe Class : Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Class.forName("oracle.jdbc.driver.OracleDriver"); Class.forName("org.gjt.mm.mysql.Driver"); quand une classe Driver est charge, elle doit crer une instance delle mme et senregistrer auprs du DriverManager certains compilateurs refusent cette notation et demandent plutt : Class.forName("driver_name").newInstance();
Mohamed N. Lokbani
v1.01
33/58
2. tablir la connexion la base de donnes Une fois le driver enregistr, une connexion peut-tre tablie. Afin dtablir une connexion, il est ncessaire davoir un url pour la base de donnes. Cet url est construit suivant la mthodologie suivante : Un URL pour une base de donnes est de la forme : jdbc:sous-protocole:base de donne Par exemple, pour Oracle : jdbc:oracle:thin:@oracle:1521:a05 oracle: thin est le sous -protocole (driver "thin" ; Oracle fournit
Mohamed N. Lokbani v1.01 JDBC -2e partie-
34/58
aussi un autre type de driver) @ oracle:1521:a05 dsigne la base de donnes a05 situe sur la machine oracle (le serveur coute sur le port 1521) La forme exacte des parties sous-protocole et base de donnes dpend des SGBD MySql jdbc:mysql://[hostname][:port]/dbname[?param1=value1] ODBC jdbc:mysql:dbname
Mohamed N. Lokbani v1.01 JDBC -2e partie-
35/58
Obtenir une connexion Pour obtenir une connexion un SGBD, on demande cette connexion la classe gestionnaire de drivers : Mthode getConnection() de DriverManager 3 arguments : lURL de la base de donnes le nom de lutilisateur de la base son mot de passe
Connection conn = DriverManager.getConnection(url,user,password) ;
Mohamed N. Lokbani
v1.01
36/58
le DriverManager essaye tous les drivers qui se sont enregistrs (chargement en mmoire avec Class.forName()) jusqu ce quil trouve un driver qui peut se connecter la base static final String url = "jdbc:oracle:thin:@oracle:1521:a05"; Connection conn = DriverManager.getConnection(url, "toto", "mdp"); Gestion des transactions (ensemble de requtes SQL) Par dfaut la connexion est en "auto-commit" : un commit est automatiquement lanc aprs chaque ordre SQL qui modifie la base
Mohamed N. Lokbani v1.01 JDBC -2e partie-
37/58
On peut enlever l'auto-commit par : conn.setAutoCommit(false) conn.commit() valide la transaction. conn.rollback() annule la transaction.
Mohamed N. Lokbani
v1.01
38/58
3. Crer une zone de description de requte Lobjet Statement possde les mthodes ncessaires pour raliser les requtes sur la base associe la connexion dont il dpend 3 types de Statement : Statement : requtes statiques simples PreparedStatement : requtes dynamiques prcompiles (avec paramtres dentre/sortie) CallableStatement : procdures stockes
Mohamed N. Lokbani
v1.01
39/58
A partir de linstance de lobjet Connection, on rcupre le Statement associ : Statement req1 = conn.createStatement() ; PreparedStatement req2 = conn.prepareStatement(str) ; CallableStatement req3 = conn.prepareCall(str) ;
Mohamed N. Lokbani
v1.01
40/58
4. Excuter la requte 3 types dexcution : executeQuery() : pour les requtes (SELECT) qui retournent un ResultSet (tuples rsultants) executeUpdate() : pour les requtes (INSERT, UPDATE, DELETE, CREATE TABLE, DROP TABLE) qui retournent un entier (nombre de tuples traits) execute() : procdures stockes (cas rares)
Mohamed N. Lokbani
v1.01
41/58
executeQuery() et executeUpdate() de la classe Statement prennent comme argument une chane (String) indiquant la requte SQL excuter :
Statement stmt = conn.createStatement (); ResultSet rset = user_catalog"); stmt.executeQuery ("select * from
le code SQL nest pas interprt par Java. cest le pilote associ la connexion (et au final par le moteur de la base de donnes) qui interprte la requte SQL si une requte ne peut sexcuter ou quune erreur de syntaxe SQL a t dtecte, lexception SQLException est leve
Mohamed N. Lokbani v1.01 JDBC -2e partie-
42/58
le driver JDBC effectue dabord un accs la base pour dcouvrir les types des colonnes impliques dans la requte puis un 2me pour lexcuter. 5. Traiter les donnes retournes Lobjet ResultSet (retourn par lexcution de executeQuery() ) permet daccder aux champs des tuples slectionns seules les donnes demandes sont transfres en mmoire par le driver JDBC il faut donc les lire "manuellement" et les stocker dans des variables pour un usage ultrieur
Mohamed N. Lokbani
v1.01
43/58
JDBC 1.x : Il se parcourt itrativement ligne par ligne par la mthode next() retourne false si dernier tuple lu, true sinon chaque appel fait avancer le curseur sur le tuple suivant initialement, le curseur est positionn avant le premier tuple excuter next() au moins une fois pour avoir le premier while(rs.next()) {// Traitement de chaque tuple} impossible de revenir au tuple prcdent ou de parcourir lensemble dans un ordre alatoire
Mohamed N. Lokbani
v1.01
44/58
Avec le JDBC 2.0 : on peut parcourir le ResultSet davant en arrire : next() vs. previous() en dplacement absolu : aller la n-ime ligne absolute(int row), first(), last(), ... en dplacement relatif : aller la n-ime ligne partir de la position courante du curseur, : relative(int row), afterLast(), beforeFirst(), ...
Mohamed N. Lokbani
v1.01
45/58
Les colonnes sont rfrences par leur numro (commencent 1) ou par leur nom Laccs aux valeurs des colonnes se fait par les mthodes de la forme getXXX() lecture du type de donnes XXX dans chaque colonne du tuple courant int val = rs.getInt(3) ; // accs la 3e colonne. String prod = rs.getString("PRODUIT") ;
Mohamed N. Lokbani
v1.01
46/58
Statement st = conn.createStatement() ; ResultSet rs = st.executeQuery( "Select a, b, c, FROM Table1") ; while(rs.next()) { int i = rs.getInt("a"); String s = rs.getString("b"); byte[] b = rs.getBytes("c"); }
Mohamed N. Lokbani
v1.01
47/58
/* * Cet exemple montre comment obtenir la liste des usagers * disposant dun compte dans la base. (de la doc. de Oracle) */ import java.sql.*;
class Employee { public static void main (String args []) throws SQLException { // Chrgement du driver JDBC-Oracle DriverManager.registerDriver( new oracle.jdbc.driver.OracleDriver());
Mohamed N. Lokbani
v1.01
48/58
// Connexion la base de donnes // syntaxe <host>:<port>:<sid>. Connection conn = DriverManager.getConnection ( "jdbc:oracle:thin:@oracle:1521:a05 ", "momo", "toto"); // Crer un descripteur de requtes Statement stmt = conn.createStatement (); // Slectionner les noms de la table ResultSet rset = stmt.executeQuery ( "select username from dba_users"); // Itrer afin dobtenir la liste de tous // les noms ! while (rset.next ()) System.out.println (rset.getString (1));
} }
Mohamed N. Lokbani
v1.01
49/58
Accs au mta-donnes La mthode getMetaData() permet dobtenir des informations sur les types de donnes du ResultSet elle renvoie des ResultSetMetaData on peut connatre entre autres : le nombre de colonne : getColumnCount() le nom dune colonne : getColumnName(int col) le nom de la table : getTableName(int col) si un NULL SQL peut tre stock dans une colonne : isNullable()
Mohamed N. Lokbani
v1.01
50/58
ResultSet rs = stmt.executeQuery("SELECT * FROM emp") ; ResultSetMetaData rsmd = rs.getMetaData() ; int nbColonnes = rsmd.getColumnCount() ; for (int i = 1 ; i<=nbColonnes ; i++) { // partir de 1 et non pas 0 String nomCol = rsmd.getColumnName(i) ; }
Mohamed N. Lokbani
v1.01
51/58
DatabaseMetaData Pour rcuprer des informations sur la base de donnes elle-mme, utiliser la mthode getMetaData() de l objet Connection dpend du SGBD avec lequel on travaille elle renvoie des DatabaseMetaData on peut connatre entre autres : les tables de la base : getTables() le nom de lutilisateur : getUserName()
Mohamed N. Lokbani
v1.01
52/58
Type de donnes traites La classe ResultSet fournit des mthodes pour rcuprer dans le code Java les valeurs des colonnes des lignes renvoyes par le SELECT: getXXX(int numroColonne) getXXX(String nomColonne) XXX dsigne le type Java de la valeur que l'on va rcuprer, par exemple String, Int ou Double Tous les SGBD n'ont pas les mmes types SQL ; mme pour les types de base on peut avoir des diffrences importantes
Mohamed N. Lokbani
v1.01
53/58
JDBC dfinit ses propres types SQL dans la classe Types sous forme de constantes nommes Dans un programme JDBC, les mthodes getXXX, setXXX et les types de la classe Types servent prciser le type des donnes que l'on insre dans la base ou que l'on rcupre C'est le rle du driver particulier chaque SGBD de traduire les donnes Java dans le bon type du SGBD
Mohamed N. Lokbani
v1.01
54/58
Type JDBC
CHAR, VARCHAR , LONGVARCHAR NUMERIC, DECIMAL BINARY, VARBINARY, LONGVARBINARY BIT INTEGER BIGINT REAL DOUBLE, FLOAT DATE TIME
Type Java
String java.math.BigDecimal byte[] boolean int long float double java.sql.Date java.sql.Time
Presque tous les types SQL peuvent tre retrouvs par getString() Cependant, voici les mthodes recommandes :
Mohamed N. Lokbani
v1.01
55/58
CHAR et VARCHAR : getString, LONGVARCHAR : getAsciiString et getCharacterString BINARY et VARBINARY : getBytes, LONGVARBINARY : getBinaryStream BIT : getBoolean, TINYINT : getByte, SMALLINT : getShort, INTEGER : getInt, BIGINT: getLong REAL : getFloat, DOUBLE et FLOAT : getDouble DECIMAL et NUMERIC : getBigDecimal etc.
Mohamed N. Lokbani v1.01 JDBC -2e partie-
56/58
cas des valeurs nulles Pour reprer les valeurs NULL de la base : utilise la mthode wasNull() de ResultSet renvoie true si lon vient de lire un NULL, false sinon les mthodes getXXX() de ResultSet convertissent une valeur NULL SQL en une valeur acceptable par le type dobjet demand : les mthodes retournant un objet (getString(), getDate(),... ) retournent un "null " Java les mthodes numriques (getByte() , getInt() , etc) retournent "0" getBoolean() retourne " false "
Mohamed N. Lokbani
v1.01
57/58
Statement stmt1 = conn.createStatement(); ResultSet rset = stmt1.executeQuery("SELECT nome, comm FROM emp"); Float commission; while (rset.next()) { nom = rset.getString(1); commission = rset.getFloat(2); if (rset.wasNull()) System.out.println(nom + " n'a pas de commission"); else System.out.println(nom + " a " + commission + "F de commission"); }
Mohamed N. Lokbani
v1.01
58/58
6. Fermeture des diffrents espaces la fin du programme, il faut fermer toutes les connexions ouvertes au dbut du programme, sinon le garbage collector sen occupera mais moins efficace. Chaque objet possde une mthode close() : resultset.close() ; statement.close() ; connection.close() ;
Mohamed N. Lokbani
v1.01