Академический Документы
Профессиональный Документы
Культура Документы
JDBC (Java Data Base Connectivity) permet l'accs des bases de donnes avec le langage SQL, depuis un programme en Java Il est fourni par le paquetage java.sql LAPI JDBC est presque totalement indpendante des SGBDs (quelques mthodes ne peuvent tre utilises quavec certains SGBDs mais ne doivent tre utilises quen cas de ncessit imprieuse pour amliorer les performances)
R. Grin JDBC page 2
Contenu de java.sql
Ce paquetage contient un grand nombre d'interfaces et quelques classes Les interfaces constituent linterface de programmation JDBC ne fournit pas les classes qui implantent les interfaces
R. Grin
JDBC
page 4
Drivers
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 JDBC Les drivers dpendent du SGBD auquel ils permettent d'accder Tous les SGBD importants du march ont un (et mme plusieurs) driver JDBC, fourni par l'diteur du SGBD ou par des diteurs de logiciels indpendants
R. Grin JDBC page 5
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 Type 4 : driver crit entirement en Java, qui utilise le protocole rseau du SGBD
R. Grin
JDBC
page 6
Les mthodes du driver JDBC font appel des fonctions d'une API du SGBD crite dans un autre langage que Java
Driver
Protocole du SGBD
SGBD
R. Grin JDBC page 7 R. Grin JDBC
SGBD
page 8
Les mthodes du driver JDBC se connectent par socket au serveur middleware et lui envoient les requtes SQL ; le serveur middleware les traitent en se connectant au SGBD
Les mthodes du driver JDBC utilisent des sockets pour dialoguer avec le SGBD selon son protocole rseau
SGBD
Protocole du SGBD
SGBD
R. Grin JDBC page 9 R. Grin JDBC
page 10
SGBD
R. Grin JDBC page 12
Serveur HTTP
SGBD
JDBC page 13 R. Grin JDBC page 14
R. Grin
Charger en mmoire la classe du (des) driver (driver de type 4 fourni par Oracle pour cet exemple) avant d'utiliser JDBC :
Class.forName("oracle.jdbc.OracleDriver");
R. Grin
JDBC
page 15
R. Grin
JDBC
page 16
interroger la base (executeQuery()) ou modifier la base (executeUpdate()) ou tout autre ordre SQL (execute())
Avertissement
Nous tudierons tout d'abord les classes et mthodes de base de JDBC Des nouvelles possibilits de JDBC 2 et 3, en particulier celles qui sont lies SQL3, seront abordes dans les parties JDBC avanc et JDBC et objet-relationnel Dans la suite du cours on utilise des raccourcis tels que instance de Connection Comme Connection est une interface, il faut traduire par instance dune classe qui implmente Connection
R. Grin
JDBC
page 19
R. Grin
JDBC
page 20
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
R. Grin JDBC page 21
Classes principales
DriverManager : gre les drivers, lance les connexions aux bases Date : date SQL Time : heures, minutes, secondes SQL TimeStamp : date et heure, avec une prcision la microseconde Types : constantes pour dsigner les types SQL (pour les conversions avec les types Java)
R. Grin
JDBC
page 22
Exceptions
SQLException : erreurs SQL SQLWarning : avertissements SQL (classe fille de SQLException) ; le mcanisme de rcupration des avertissements est tudi plus loin DataTruncation : avertit quand une valeur est tronque lors d'un transfert entre Java et le SGBD (classe fille de SQLWarning)
R. Grin
JDBC
page 23
Interface Driver
La mthode connect() de Driver prend en paramtre un URL et renvoie une instance de l'interface Connection Cette instance de Connection permettra de lancer des requtes vers le SGBD connect renvoie null si le driver ne convient pas pour se connecter la base dsigne par l'URL
Gestionnaire de drivers
La classe DriverManager gre les drivers (instances de Driver) disponibles pour les diffrents SGBD utiliss par le programme Java Pour qu'un driver soit utilisable, on doit charger sa classe en mmoire :
Class.forName("oracle.jdbc.OracleDriver");
JDBC 4 et le driver
JDBC 4 utilise un autre mcanisme pour charger le driver : il suffit d'indiquer le nom de la classe du driver dans un fichier META-INF/services/java.sql.Driver distribu avec le driver JDBC Il est alors inutile dappeler la mthode Class.forName
La classe cre alors une instance d'elle mme et enregistre cette instance auprs de la classe DriverManager
R. Grin JDBC page 29
R. Grin
JDBC
page 30
Connexions et threads
Les connexions sont des ressources coteuses, et surtout longues obtenir On peut donc tre tent de les rutiliser dans plusieurs threads diffrents Mais, attention, les connexions ne peuvent tre partages par plusieurs threads la place, utiliser les pools de connexions fournis avec les sources de donnes (tudies dans une autre partie du cours)
R. Grin JDBC page 32
La classe DriverManager s'adresse tour de rle tous les drivers qui se sont enregistrs (mthode connect), jusqu' ce qu'un driver lui fournisse une connexion (ne renvoie pas null)
R. Grin JDBC page 31
Transactions
Par dfaut la connexion est en auto-commit : un commit est automatiquement lanc aprs chaque ordre SQL qui modifie la base Le plus souvent il faut enlever l'auto-commit : conn.setAutoCommit(false) Il faut alors explicitement valider ou annuler la transaction par n conn.commit() n conn.rollback()
R. Grin JDBC page 33 R. Grin
Niveau disolation
Le niveau disolation dune transaction peut tre modifi :
conn.setTransactionIsolation( Connection.TRANSACTION_SERIALIZABLE);
JDBC
page 34
R. Grin
JDBC
page 35
Interface ResultSet
executeQuery() renvoie une instance de ResultSet ResultSet va permettre de parcourir toutes les lignes renvoyes par le select Au dbut, ResultSet est positionn avant la premire ligne et il faut donc commencer par le faire avancer la premire ligne en appelant la mthode next() Cette mthode permet de passer la ligne suivante ; elle renvoie true si cette ligne suivante existe et false sinon
R. Grin JDBC page 38
JDBC
page 37
Interface ResultSet
Quand ResultSet est positionn sur une ligne les mthodes getXXX permettent de rcuprer les valeurs des colonnes de la ligne : n getXXX(int numroColonne) n getXXX(String nomColonne) (nom simple dune
colonne, pas prfix par un nom de table ; dans le cas dune jointure utiliser un alias de colonne)
ResultSet - performances
Quand le rseau est lent et que lon veut rcuprer de nombreuses lignes, il est parfois possible damliorer sensiblement les performances en modifiant le nombre de lignes rcupres chaque fois par le ResultSet (il faut effectuer des tests pour chaque cas) Pour cela, on utilise la mthode setFetchSize de Statement Cest seulement une indication quon donne au driver ; il nest pas oblig den tenir compte
R. Grin JDBC page 40
XXX dsigne le type Java de la valeur que l'on va rcuprer, par exemple String, Int ou Double Par exemple, getInt renvoie un int
R. Grin JDBC page 39
Types JDBC/SQL
Tous les SGBD n'ont pas les mmes types SQL ; mme les types de base peuvent prsenter des diffrences importantes Pour cacher ces diffrences, JDBC dfinit ses propres types SQL dans la classe Types, sous forme de constantes nommes Ils sont utiliss par les programmeurs quand ils doivent prciser un type SQL (setNull, setObject, registerOutParameter) Le driver JDBC fait la traduction de ces types dans les types du SGBD
R. Grin JDBC page 41
Types SQL3
page 42
n n n
CHAR et VARCHAR : getString, LONGVARCHAR : getAsciiStream et getCharacterStream BINARY et VARBINARY : getBytes, LONGVARBINARY : getBinaryStream REAL : getFloat, DOUBLE et FLOAT : getDouble DECIMAL et NUMERIC : getBigDecimal DATE : getDate, TIME : getTime, TIMESTAMP : getTimestamp
JDBC page 44
R. Grin
Exemple
Pour passer de java.util.Date java.sql.Date, utiliser la mthode getTime():
java.util.Date date = new java.util.Date(); java.sql.Date dateSQL = new java.sql.Date(date.getTime()); java.sql.Time time = new Time(date.getTime()); java.sql.Timestamp time = new Timestamp(date.getTime());
R. Grin
JDBC
page 46
Valeur NULL
Statement stmt = conn.createStatement(); ResultSet rset = stmt.executeQuery( "SELECT nomE, comm FROM emp"); while (rset.next()) { nom = rset.getString("nomE"); commission = rset.getDouble("comm"); if (rset.wasNull()) System.out.println(nom + ": pas de comm"); else System.out.println(nom + " a " + commission + " de commission"); }
page 47 R. Grin JDBC page 48
R. Grin
JDBC
R. Grin
JDBC
page 49
Les "?" indiquent les emplacements des paramtres Cette requte pourra tre excutes avec plusieurs couples de valeurs : (2500, DUPOND), (3000, DURAND), etc.
R. Grin
JDBC
page 51
R. Grin
JDBC
page 53
R. Grin
JDBC
page 54
Procdures stockes
Les procdures stockes permettent non seulement de prcompiler des ordres SQL mais aussi de les regrouper Comme les accs rseau aux bases de donnes ralentissent les applications, les procdures stockes permettent souvent damliorer les performances Mais elles nuisent aussi souvent la portabilit des applications
R. Grin JDBC page 56
Exemple
CallableStatement cstmt = conn.prepareCall("{? = call augmenter(?,?)}");
R. Grin
JDBC
page 60
10
csmt.setInt(1, 10); csmt.setDouble(2, 2.5); csmt.executeQuery(); // ou execute() double cout = csmt.getDouble(3); System.out.println("Cout total augmentation : " + cout);
R. Grin JDBC page 62
execute renvoie true si le 1er rsultat est un ResultSet getMoreResults renvoie true si le rsultat suivant est un ResultSet getUpdateCount() : renvoie le nombre de lignes modifies, ou -1 s'il n'y a plus de rsultat (ou si le rsultat est un ResultSet)
On peut excuter tous les ordres dans une boucle dont la condition de fin est
!getMoreResults() && getUpdateCount() == -1
R. Grin JDBC page 64
Schma de code
boolean retval = cstmt.execute(); do { if (retval == false) { // pas un ResultSet int count = cstmt.getUpdateCount(); if (count == -1) break; // cest fini ! else { // traite lordre SQL . . . } } else { // ResultSet ResultSet rs = cstmt.getResultSet(); . . . // traite le ResultSet } retval = cstmt.getMoreResults(); while (true);
R. Grin JDBC page 65
11
Il faut Crer un type pour la rfrence de curseur quon va renvoyer Crer la fonction qui renvoie la rfrence de curseur
R. Grin
JDBC
page 67
R. Grin
JDBC
page 68
Crer la fonction
create or replace function listdept(num integer) return Types.curseur_type is empcursor Types.curseur_type; begin open empcurseur for select dept, nomE from emp where dept = num; return empcurseur; end;
R. Grin JDBC page 69
12
dates : {d '2000-10-5'} appels de fonctions : {fn concat("Hot", "Java")} jointures externes : con.createStatement("SELECT * FROM" + " {oj EMP RIGHT OUTER JOIN DEPT" + " ON EMP.DEPT = DEPT.DEPT}"); caractre dchappement utilis par LIKE : WHERE Id LIKE '_%\\' {escape '\'}
JDBC page 73
R. Grin
R. Grin
JDBC
page 74
ResultSetMetaData
ResultSet rs = stmt.executeQuery("SELECT * FROM emp"); ResultSetMetaData rsmd = rs.getMetaData(); int nbColonnes = rsmd.getColumnCount(); for (int i = 1; i <= nbColonnes; i++) { String typeColonne = rsmd.getColumnTypeName(i); String nomColonne = rsmd.getColumnName(i); System.out.println("Colonne " + i + " de nom " + nomColonne + " de type " + typeColonne); }
R. Grin JDBC page 75
DatabaseMetaData
private DatabaseMetaData metaData; private java.awt.List listTables = new List(10); . . . metaData = conn.getMetaData(); String[] types = { "TABLE", "VIEW" }; ResultSet rs = metaData.getTables(null, null, "%", types); String nomTables; Joker pour while (rs.next()) { noms des nomTable = rs.getString(3); tables et vues listTables.add(nomTable); }
R. Grin JDBC page 76
R. Grin
JDBC
page 77
13