Réaliser en Java un programme client d’une Base de Données JDBC Réaliser en Java un programme client d’une Base de Données
Un accès universel aux sources de données IHM Magasin de données Moteur Noyau de l’application Programmes de couche intermédiaire (middle-tier software) Programme dorsal (serveur) Programme Client Un accès universel aux sources de données Pour pouvoir faire communiquer un logiciel client avec un logiciel source de données, il faut insérer entre les deux un logiciel intermédiaire appelé logiciel de connexion ou logiciel de niveau intermédiaire qui est chargé de traduire les requêtes émises par le client en commandes directement exécutables par le moteur de la source de données. Avant les années 90, chaque logiciel source de données offrait sa propre API. Il fallait donc réécrire le logiciel client à chaque fois que l'on changeait de source de données, cela limitait donc les capacités d'évolution d'une application et liait fortement les entreprises aux vendeurs de SGBD. Au début des années 90, un consortium industriel comprenant entre autres IBM et Microsoft, proposa une méthode d'accès universel aux données permettant aux applications clientes d'accéder aux données de la même façon quelque soit la source des données. Pour cela on insère entre le logiciel client et le logiciel dorsal un logiciel intermédiaire appelé Pilote (driver) qui traduit les requêtes SQL produites par le client en commandes compréhensibles par le SGBD. Il faut un driver ODBC différent pour chaque type de source de données. La plupart des éditeurs de SGBD : Oracle, Informix, IBM fournissent des pilotes ODBC qui permettent, en principe de migrer facilement d'un SGBD à un autre. Les pilotes ODBC sont écrits en C ou en C++. ODBC est présent sur la plupart des plate-formes Win, Mac OS, Linux Problème d'ODBC : il est lent
API JDBC (Java Data Base Connectivity) et pilotes JDBC Type 1 : Source de données compatible ODBC (ACCESS, EXCEL,…) Programme Java Pont JDBC-ODBC Pilote ODBC API JDBC (Java Data Base Connectivity) et pilotes JDBC JDBC est une API intégrée dans Java 2. Les classes JDBC contiennent des méthodes qui vont dialoguer avec un pilote JDBC qui convertira les appels JDBC généralistes en appels spécifiques à un SGBD. C'est l'éditeur du SGBD qui fournit en principe le pilote JDBC. Mais il existe aussi des pilotes JDBC réalisés par des entreprises tiers, qui peuvent avoir de meilleures performances que les pilotes fournis par l'éditeur du SGBD. Il existe 4 types de pilotes JDBC , dont les plus utilisés sont dits de type 1 et de type 4. Dans le type 1, on utilise un pont JDBC-ODBC, fournit avec Java2, qui convertit les appels JDBC en appels ODBC qui sont transmis aux routines ODBC du système d'exploitation qui renvoient ces appels au pilote ODBC de la source de données ciblée par le programme java. Cette solution est lente car il faut passer par de nombreuses couches logicielles intermédiaires. Mais c'est la seule façon d'accéder par exemple à une BD ACCESS ou à un classeur EXCEL. API ODBC
La meilleure solution de connexion Type 4 Programme Java Pilote JDBC La meilleure solution de connexion Une solution beaucoup plus efficace est d'avoir un pilote JDBC de type 4 : écrit 100% en Java il convertit les appels JDBC en code directement compréhensible par la source de données. Il existe des pilotes JDBC de type 4 pour les principaux SGBD. Certains sont mêmes fournis avec Java 2 (le pilote de mySQL) Source de données (MySQL, Oracle, PostGres…)
Pour le projet GLPOO… Comptoir (base ACCESS) BIG-GROCER Pont JDBC-ODBC Pilote ODBC Pour le projet GLPOO… API ODBC
Déclarer la source de données Comptoir au gestionnaire ODBC de Windows (1)
Déclarer la source de données Comptoir au gestionnaire ODBC de Windows (2)
Déclarer la source de données Comptoir au gestionnaire ODBC de Windows (3)
Déclarer la source de données Comptoir au gestionnaire ODBC de Windows (4)
La base de données Comptoir
Un programme client qui se connecte à la base COMPTOIR import java.sql.*; public class EssaiJDBC_ODBC { public static void main (String [ ] args) { Connection conn = null; try { Class.forName ("sun.jdbc.odbc.JdbcOdbcDriver"); conn = DriverManager.getConnection ("jdbc:odbc:Comptoir","",""); System.out.println ("Connexion etablie avec COMPTOIR"); } catch (Exception e) {System.err.println ("Pas de connexion à COMPTOIR");} finally { if (conn != null) { conn.close ( ); System.out.println ("Connexion terminee"); catch (Exception e) { } Un programme client qui se connecte à la base COMPTOIR Un programme client qui se connecte à la base COMPTOIR La première chose à faire est de charger le pilote JDBC-ODBC. Cela se fait par l’instruction Class.forName….dont la signification ne pourra être entièrement comprise qu’après que nous ayons vu les javabeans. Puis on demande au gestionnaire de pilotes de créer une connexion à la source de données Comptoir. On utilise pour cela la méthode getConnection( ) de la classe DriverManager. Cette méthode prend comme premier argument l'URL de la source de données qui peut être l'url d'une base distante ou locale. Chaque driver JDBC a sa propre syntaxe pour décrire cette URL. La fermeture de la connexion se fait dans la clause finally. Cette fermeture peut elle-même lever une exception, qui n’est pas traitée (choix dangereux)
Variante : connexion à une base mySQL try { String url = "jdbc:mysql://localhost/grocer"; Class.forName ("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection (url, "toto", "toto"); System.out.println ("Connexion etablie avec GROCER"); }
Exécution d’une requête SQL import java.sql.*; public class EssaiSELECT { public static void main (String [ ] args) { Connection conn = null; try { Class.forName ("sun.jdbc.odbc.JdbcOdbcDriver"); conn = DriverManager.getConnection ("jdbc:odbc:Comptoir","",""); System.out.println ("Connexion etablie avec COMPTOIR"); Statement s = conn.createStatement ( ); s.executeQuery ("SELECT Nom, [N° Employé], [Date de naissance] FROM Employés"); ResultSet rs = s.getResultSet ( ); while (rs.next ( )){ String nomVal = rs.getString ("Nom"); int numéro = rs.getInt("N° Employé"); Date date = rs.getDate("Date de naissance"); System.out.println ("N° Employé : " + numéro + " Nom : " + nomVal + " Date de naissance : " + date);} rs.close ( ); s.close ( ); } catch (Exception e) {System.err.println ("Pb avec SELECT");} finally { if (conn != null) { try { conn.close ( ); System.out.println ("Connexion terminee");} catch (Exception e) {System.err.println ("Pb de fermeture de connexion");}}}}} Exécution d’une requête SQL Exécution d’une requête SQL Une fois la connexion établie avec la base de données, on demande à la connexion de créer une instruction SQL par la méthode createStatement Une instruction SQL qui renvoie un résultat s’appelle une requête (query). On demande à l’objet s d’exécuter une requête SQL qui est écrite sous forme d’une chaîne de caractères. Le résultat de la requête est renvoyé dans une instance de la classe ResultSet. Rs.next() renvoie un enregistrement (une ligne d’une table), on peut alors accéder aux valeurs des différents champs de l’enregistrement en indiquant une méthode adaptée au type de ces champs et en passant le nom du champ à la méthode. Il existe dans la classe ResultSet une méthode pour chaque type de données standard SQL : getByte, getBoolean,getTime, getDate. On peut récupérer toutes les valeurs avec un getString, qu'il faut alors convertir sous Java dans le bon format. Ne pas oublier de fermer l’ensemble des résultats et l’instruction SQL.
Résultat du SELECT Résultat du SELECT
Exécution d’une instruction SQL Statement s = conn.createStatement ( ); s.executeUpdate ("INSERT INTO Messagers VALUES (4,'La Poste', '01 46 21 32 64')"); s.executeQuery ("SELECT * FROM Messagers"); ResultSet rs = s.getResultSet ( ); while (rs.next ( )){ int numéro = rs.getInt("N° messager"); String nom = rs.getString("Nom du messager"); String tel = rs.getString("Téléphone"); System.out.println ("N° messager : " + numéro + " Société : " + nom + " Téléphone : " + tel); } rs.close ( ); s.close ( ); Exécution d’une instruction SQL Une modification de la base n’est pas une requête, c’est une instruction qui ne renvoie pas de résultat. On utilise la méthode executeUpdate . Il existe une classe d’exception spécifique SQLException qui permet d’avoir des informations sur le type d’erreurs de syntaxe SQL (très utile pour déboguer les instructions SQL compliquées)
Affichage graphique d’une table (1) Nous allons montrer comment afficher les données issues d'un SELECT dans une JTable
Affichage graphique d’une table (2) import java.sql.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class EssaiTableGraphique extends JFrame{ String [ ] [ ] données; public static void main (String [ ] args) { EssaiTableGraphique etg = new EssaiTableGraphique(100); etg.setSize(400,400); etg.show( ); } public EssaiTableGraphique(int nbLignes) { Connection conn = null; try { Class.forName ("sun.jdbc.odbc.JdbcOdbcDriver"); conn = DriverManager.getConnection ("jdbc:odbc:Comptoir","",""); System.out.println ("Connexion etablie avec COMPTOIR"); Statement s = conn.createStatement ( ); s.executeQuery ("SELECT [Nom du produit],[Prix unitaire], [Unités en stock] FROM Produits"); ResultSet rs = s.getResultSet ( ); données = new String [nbLignes][3]; int i = 0; while (rs.next ( )){ données[i][0] = rs.getString("Nom du produit"); données[i][1] = rs.getString ("Prix unitaire"); données[i][2] = rs.getString("Unités en stock"); i++; } Affichage graphique d’une table (2) Affichage graphique d'une table (2) Les lignes du ResultSet sont mémorisées dans un tableau d'Object à deux dimensions. Toutes les valeurs des champs d'une ligne peuvent être lues comme des Strings (si les valeurs sont numériques à l'origine dans la base de données, comme c'est le cas ici pour le champ "Prix unitaire" par exemple, la méthode getString convertit cette valeur numérique en String)
Affichage graphique d’une table (3) rs.close ( ); s.close ( ); } catch (Exception e) {System.err.println ("Pb SQL");} finally { if (conn != null) { try { conn.close ( ); System.out.println ("Connexion terminee"); catch (Exception e) { } String[ ] nomsColonnes = {"produit", "Prix unitaire", "Quantité en stock"}; JTable table = new JTable(données, nomsColonnes); table.setPreferredScrollableViewportSize(new Dimension(500, 70)); JScrollPane scrollPane = new JScrollPane(table); getContentPane().add(scrollPane, BorderLayout.CENTER); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent evt) { System.exit(0); }); Affichage graphique d’une table (2) L’affichage des lignes de la table produit se fera dans une Jtable dont le constructeur prend en entrée le tableau d’objets Données et un tableau de chaînes de caractères qui seront les titres des colonnes. Pour que le Jtable soit muni d’ascenseurs, il faut le disposer à l’intérieur d’un JScrollPane
Utilisation de l'éditeur de requête d'ACCESS (1) Sélectionner "Requêtes" dans le panneau de gauche, cliquez sur le bouton "Nouveau" dans la barre d'outils et sélectionnez "Assistant requête simple"
Utilisation de l'éditeur de requête d'ACCESS (2) Choisir la table sur laquelle porte la "requête simple" (un SELECT) et sélectionner les champs visés par la requête
Utilisation de l'éditeur de requête d'ACCESS (3) Choisissez une requête détaillée, puis "Modifier la structure"
Utilisation de l'éditeur de requête d'ACCESS (4) Ajoutez vos contraintes sur les valeurs des champs (comme sous EXCEL avec les "zones de critères" pour les "filtrages élaborés")
Utilisation de l'éditeur de requête d'ACCESS (5) Déroulez le menu "Affichage" de la fenêtre principale d'ACCESS et choisissez l'item "Mode SQL"…vous n'avez plus qu'à copier le code SQL dans votre code Java…