JDBC Java DataBase Connectivity
Ahcène Bounceur
Introduction
• JDBC (Java DataBase Connectivity ) :
– API standard de connexion avec les bases de données relationnelles
• Servlet, Applet ou application Java traditionnelle
– accèdent de la même façon à une base de donnée
Les Drivers
• JDBC : quatre types de drivers
– Type 1 : Bridge
• JDBC-ODBC bridge (Open Data Base Connector)
– Type 2 : Native
• native-API partly Java technology-enabled
– Type 3 : Middleware
• net-protocol fully Java technology-enabled
– Type 4 : Pure
• native-protocol fully Java technology-enabled
Les Drivers (TYPE 1)
JDBC-ODBC bridge
(Open Data Base Connector) Microsoft
Intérêt : pouvoir utiliser directement les fonctionnalités pour lesquels ODBC a été conçu driver le plus utilisé lors de développement Windows
Limite :
impossible de faire appel à ce type de driver en dehors des environnements ODBC
Premier driver créé …
Les Drivers (TYPE 2)
native-API partly Java technology-enabled
Intérêt : permettent d'utiliser directement l'API spécifique du SGBD
Limite :
ne peuvent être utilisés que dans les environnements disposant d'une API propriétaire
Les drivers natifs … (réplique ODBC au sein de l'API Java)
Les Drivers (TYPE 3) net-protocol fully Java technology-enabled
Intérêt : ne laisse pas l'application cliente faire les appels à la base de données : le driver se charge de contacter le serveur, qui traduit la requête et l'envoi au SGBD directement
Applications totalement portables, la sécurisation se fait directement sur le serveur, les connexions
sont gérées selon la demande et donc optimisées. Modifications et reconfigurations se font directement sur le serveur sans devoir modifier les applications clientes…
Limite :
tous les fournisseurs de serveur d'application ne fournissent pas forcément ce type de drivers sur leur système, ou ne reconnaissent pas tous les SGBDR
Les drivers Pont Réseau … (Méthode la plus sûre) Centraliser les accès en utilisant un serveur d'application intermédiaire pour faire transiter les
requêtes vers la base de données
Les Drivers (TYPE 4)
native-protocol fully Java technology-enabled
Intérêt : drivers natifs écrits en Java
Limite : contraintes réseau et sécurité de Java
Les drivers Java …
• portages en Java des API propriétaires (généralement écrites en C)
• utilisent l'interface java.net pour accéder à la base
Si une applet n'est pas reconnue comme étant de confiance (trusted applet), elle ne pourra se
connecter qu'à une base qui se trouve sur son serveur d'origine
il faut un pilote pour chaque base…
Les Drivers
JDBC
Type I “Bridge”
Type II “Native”
Type III “Middleware”
Type IV “Pure”
ODBC ODBC Driver
CLI (.lib)
Middleware Server
Établissement d’une connexion Chargement du driver
Deux possibilités :
1) définition de la propriété système jdbc.drivers au lancement de la JVM :
java -Djdbc.drivers = MonDriver MonApplication
2) chargement dynamique du driver :
Class.forName("MonDriver").newInstance()
Établissement d’une connexion Ouverture de la connexion
• Chaque base de donnée est représentée par une URL de la forme :
jdbc:pilote://host/bd
try {
String url = "jdbc:monPilote://monHote/maBdD";
String user = "monUser";
String pwd = "monPass";
Connection dbConnexion;
dbConnexion = DriverManager.getConnection(url, user, pwd);
}
catch (SQLException ex) {
// gestion des erreurs
}
Exécution d’instructions SQL Requêtes SQL simples
• Objet connexion : méthode createStatement() :
=> récupérer un objet Statement
+ appliquer ses méthodes :
– executeQuery(String sql)
• exécute une requête SQL produisant un résultat (SELECT)
– executeUpdate(String sql)
• exécute une requête SQL ne produisant aucun résultat (INSERT, UPDATE ou DELETE)
Exemple
import java.sql.*;
import java.lang.*;
try {
Statement req = dbConnexion.createStatement(); String sql1 = "SELECT * FROM table WHERE key = " + value1 + " ORDER by column"; ResultSet res1 = req.executeQuery(sql1);
String sql2 = "SELECT * FROM table WHERE key = "
+ value2 + " ORDER by column";
ResultSet res2 = req.executeQuery(sql2);
}
catch (SQLException ex) {
// gestion des erreurs
}
Exécution d'instructions SQL Requêtes SQL paramétrées
• Les requêtes générées par la méthode précédente sont interprétées entièrement à chaque invocation
Pas toujours très efficace
• Dans certains cas, on préférera l'utilisation de requêtes paramétrées (pré-compilées) et donc plus rapides
Exécution d'instructions SQL Requêtes SQL paramétrées
• Objet PreparedStatement
– méthode createPreparedStatement(String sql) appliquée à l'objet connexion.
• L'argument : requête à utiliser avec le caractère "?" à la place de chaque paramètre
• L'affectation de ces paramètres se fait ensuite avec les accesseurs en écriture de l'objet PreparedStatement : – setString(int parameterIndex, String parameterValue)
affecte le paramètre d'index parameterIndex avec la valeur de type String parameterValue
– setInt(int parameterIndex, Int parameterValue)
affecte le paramètre d'index parameterIndex avec la valeur de type int parameterValue
– etc...
Exécution d'instructions SQL Requêtes SQL paramétrées
• Exécution de la requête -> similaire au cas précédent
• mais les méthodes
executeQuery() et executeUpdate()
de l'objet PreparedStatement ne prennent pas d'arguments
Exemple
try {
String sql = "SELECT * FROM table WHERE key = ? ORDER by column";
PreparedStatement req = dbConnexion.createPreparedStatement(sql);
req.setInt(1, value1);
ResultSet res1 = Req .executeQuery();
req.setInt(1, value2);
ResultSet res2 = Req .executeQuery();
}
catch (SQLException ex) {
// gestion des erreurs
}
Exécution d'instructions SQL Lecture des résultats
• Les requêtes de sélection retournent un résultat sous forme d'un objet ResultSet
• On peut interroger séquentiellement grâce à la méthode next()
• qui renvoie le booléen true tant qu'il reste encore des enregistrements
• On récupère le contenu de chaque champ grâce aux accesseurs en lecture : …/…
Exécution d'instructions SQL Lecture des résultats
• getString(int fieldIndex)
– retourne une valeur de type String pour le champ d'index fieldIndex
• getInt(int fieldIndex)
– retourne une valeur de type int pour le champ d'index fieldIndex
– etc...
• getString(String fieldName)
– retourne une valeur de type String pour le champ nommé fieldName
• getInt(String fieldName)
– retourne une valeur de type int pour le champ nommé fieldName
– etc..
Exemple
try {
while (rs.next()) {
int key = rs.getInt("key");
String value = rs.getString(2);
System.out.println("Clé : " +
key + ", valeur : " + value");
}
}
catch (SQLException ex) {
// gestion des erreurs
}
Exécution d'instructions SQL Lecture des métadonnées
Métadonnées : données sur les données
• Finalité : découvrir les noms et types des
champs
Exécution d'instructions SQL Lecture des métadonnées
• Méthode getMetaData() appliquée : – soit à un objet ResultSet après la requête – soit à un objet PreparedStatement avant celle-ci
retourne un objet ResultSetMetaData • On peut appliquer ses méthodes :
– getColumnCount()
• retourne le nombre de champs du résultat sous la forme d'un entier
– getColumnName(int columnIndex)
• retourne le nom du champ désigné par l'index columnIndex sous la forme d'une chaine
– getColumnType(int columnIndex)
• retourne le type du champ désigné par l'index columnIndex, sous la forme d'une constante de la classe java.sql.Types
Exécution d'instructions SQL Fermeture de la connexion
• Les objets ResultSet, Statement (ou PreparedStatement), Connection mobilisent des ressources, tant du coté de l'application Java que du SGBD.
• En effet, la plupart de ces derniers n'acceptent qu'un nombre limité de connexions simultanées.
• Chacun de ces objets dispose d'une méthode close() qu'il convient d'appeler dans l'ordre inverse de leur création : ResultSet, puis Statement, puis Connection.
Exécution d'instructions SQL Traitement des erreurs
try {
…
}
catch (SQLException ex) {
// gestion des erreurs
}
En résumé
Chargement du driver
Connexion Requêtes
SQL Lecture des
Résultats