juin 2006~ Brigitte Groléas ~ 1 J530 (JBD) Java : Base de Données
juin 2006~ Brigitte Groléas ~ 2 Jdbc sont des Api d’interaction avec un SGBD Permet à un programme Java d’interagir sur une base de données, selon un principe de client/serveur. Le client est le programme Java tandis que le serveur est la base de données. Cette interaction peut se faire localement ou à distance.
juin 2006~ Brigitte Groléas ~ 3 Access Application JAVA Jdbc Driver Manager API JDBC Jdbc ODBC Driver JDBC Driver Pour Oracle JDBC Driver Pour MySql ODBC Driver SQL server MySql Oracle
juin 2006~ Brigitte Groléas ~ 4 Architecture DriverManager : est le gestionnaire de tous les drivers chargés par un programme Java. Chaque programme Java charge le ou les drivers dont il a besoin. Il y a un driver différent par Sgbd. Exception faites que toutes les données accessibles par ODBC nécessitent le même driver.
juin 2006~ Brigitte Groléas ~ 5 Les différents types de drivers Il existe 4 types de drivers : 1. Les drivers génériques JDBC-ODBC : sont utilisés pour toutes les données accessibles par ODBC ( MS Access SQL Server, Oracle, Excel, ….) L’accès est uniquement local. pont écrit en partenariat avec Microsoft pour les Sgbdr sous Windows Ce driver est fourni avec le JDK et s’appelle sun.jdbc.odbc.JdbcOdbcDriver
juin 2006~ Brigitte Groléas ~ 6 Type 2 2 Drivers java, partiellement écrits en Java, qui reposent sur des librairies propriétaires. (souvent écrites en C). Pour ces 2 premiers types, l’appel est de la forme : jdbc :driver :source Ex : jdbc:odbc:client Client est le nom source ODBC Déclaration de la source de données ODBC A partir du panneau de configuration - outils d'administration - sources de données Odbc Parmi la liste des pilotes disponibles, choisissez celui qui correspond à votre Sgbd Créer une nouvelle source de données : 1. choisissez un nom et 2. sélectionnez votre base.
juin 2006~ Brigitte Groléas ~ 7 Type 3 Les drivers 100 % java. Ils communiquent localement ou à distance avec le Sgbd, et disposent d’un protocole réseau générique. Le driver de type 3 pour Oracle s'appelle OCI
juin 2006~ Brigitte Groléas ~ 8 Type 4 1. Ils sont aussi 100% en java, mais utilisent un protocole propriétaire au SGBD Pour ces 2 types, l’appel est de la forme : jdbc:driver:adresse exemple : jdbc:mysql://elios.univ-paris8.fr/employes ou univ-paris8.fr:1521:employes employes est le SID de votre base
juin 2006~ Brigitte Groléas ~ 9 Type 4 (suite) Le driver de type 4 pour Oracle s'appelle thin. Il faut charger un fichier appelé ojdbc14.jar Sous Eclipse : File - New - Projet, Java projet, nommez le projet, puis next, choisir l'onglet Librairie, puis add external jar sélectionner LE FICHIER ojdbc14
juin 2006~ Brigitte Groléas ~ 10 Les classes utiles La méthode statique forName(xxx) de la classe Class, permet le chargement de la classe du driver dans la VM. La classe java.sql.Connection : permet la connexion à la base de données ou au lien Odbc, elle prend en argument l'url de la base, le login de connexion et le mot de passe. La classe Statement du package java.sql, permet de créer un canal de communication avec la base.
juin 2006~ Brigitte Groléas ~ 11 L’implémentation sous Odbc class Rbd { Statement stmt = null; Connection con=null; public Rbd () { try { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); } catch (Exception e) { System.out.println("Failed to load JDBC/ODBC driver."); return; } Attention aux Majuscules
juin 2006~ Brigitte Groléas ~ 12 L’implémentation sous Odbc try { con = DriverManager.getConnection ( "jdbc:odbc:cnrs", "",""); //URL,login,passwd stmt = con.createStatement(); } catch (Exception e) { System.err.println("problems connecting to "); }
juin 2006~ Brigitte Groléas ~ 13 Fermeture de la connexion public void finalize() { try { con.close(); // fermeture de la connexion } catch (Exception e) { e.printStackTrace(); } Pour fermer la connexion ODBC lors de la destruction de l'instance
juin 2006~ Brigitte Groléas ~ 14 Implémentation sous Oracle class Rbd { Statement stmt = null; Connection con=null; public Rbd () { try { Class.forName("oracle.jdbc.driver.OracleDriver"); } catch (Exception e) { System.out.println("Failed to load Oracle driver."); return; }
juin 2006~ Brigitte Groléas ~ 15 Implémentation sous Oracle try { con = DriverManager.getConnection age"); stmt = con.createStatement(); } catch (Exception e) { System.err.println("problems connecting to "); }
juin 2006~ Brigitte Groléas ~ 16 Vrai ou Faux 1. Java se connecte toujours à une base de données avec les droits d'administrateur ? 2. Une seule connexion est possible par lien odbc ? 3. Oracle sous Windows est accessible soit par odbc soit par un driver propre ? 4. Le nom de la base est toujours identique au nom du sid ? 5. Lors d'un lien odbc, le nom de la base n'apparaît jamais en clair ? à vous
juin 2006~ Brigitte Groléas ~ 17 Le ResultSet java.sql.Statement est un canal de communication établi sur une connexion. Elle dispose d'une méthode executeQuery qui prend en argument une requête sql de type select et renvoie un Objet de type ResultSet. Le ResultSet peut être assimilé à un tableau d'enregistrements dans lequel le nom des colonnes correspond au nom des champs de la base. Les données sont accessibles soit par le nom du champ soit par le numéro de la colonne.
juin 2006~ Brigitte Groléas ~ 18 Le ResultSet Le type des champs de la base de données doit à priori être connu, puisqu'il détermine la méthode à utiliser pour retourner l'objet resultSet.getString (xx) retourne une String resultSet.getInt (xx) retourne un entier Le déplacement dans un ResultSet est par défaut 'en avance seul'. La méthode resultSet.next() permet de se positionner sur le premier enregistrement du ResultSet puis d'avancer à l'enregistrement suivant.
juin 2006~ Brigitte Groléas ~ 19 Accès aux données public void recherche(String req) { //génère une requête sur la base. Attention, pas de ; derrière la requête try {// req contient : “SELECT * FROM ages” ResultSet result = stmt.executeQuery( req); result.next(); String bdnom = result.getString("nom"); int bdage = result.getInt("age"); // result.getString( 1 ) récupère la String de la première colonne System.out.println ("nom : "+bdnom+" age: "+bdage); }
juin 2006~ Brigitte Groléas ~ 20 Accès aux données Les mises à jour, insert, create et update de la base se font par : int res = stmt.executeUpdate(« INSERT INTO ages VALUES(‘toto’,12)”); boolean getBoolean(int); boolean getBoolean(String); byte getByte(int); byte getByte(String); Date getDate(int); Date getDate(String); double getDouble(int); double getDouble(String); float getFloat(int); float getFloat(String); int getInt(int); int getInt(String); long getLong(int); long getLong(String); short getShort(int); short getShort(String); String getString(int); String getString(String);
juin 2006~ Brigitte Groléas ~ 21 Vrai ou Faux ? 1. Pour récupérer les informations d'une base de données, il faut impérativement connaître le nom des champs de la table ? 2. Il est possible de créer plusieurs Statement à partir d'une connexion ? 3. Le curseur se trouve sur la première ligne du ResultSet après un executeQuery() ? 4. Si la requête sql ne retourne aucun enregistrement de la base, la méthode executeQuery() génère une exception de type SqlException ? à vous
juin 2006~ Brigitte Groléas ~ 22 à vous... Créer une base sous Oracle qui contienne une table Identité : Nom, Prenom, Age (entier), Solde (réel), Etat (booléen). Afficher la totalité de la table dans une Jtable avec le texte débiteur si le champs Etat de la base contient vrai.
juin 2006~ Brigitte Groléas ~ 23 Les dates et objets de grande taille Le type DATE sql correspond au type java java.sql.Date et s’obtient par getDate() BLOB Binary Large Object et CLOB Character Large Objet de SQL, pour stocker des données de grandes tailles (exemple des fichiers). Ils correspondent en Java au type java.lang.Objet et s’obtiennent avec getObjet()
juin 2006~ Brigitte Groléas ~ 24 Curseurs multi-directionnel et dynamique Par défaut, un ResultSet est en avance seule et en lecture seule. CreateStatement peut prendre 2 arguments : createStatement(int direction, int maj) Les directions sont : ResultSet.TYPE_FORWARD_ONLY ResultSet.TYPE_SCROLL_INSENSITIVE ResultSet.TYPE_SCROLL_SENSITIVE
juin 2006~ Brigitte Groléas ~ 25 Les curseurs Modificateurs des options du curseur ResultSet.CONCUR_READ_ONLY ResultSet.CONCUR_READ_UPDATABLE Curseur multi-directionnel : Stmt = rs.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)
juin 2006~ Brigitte Groléas ~ 26 Les curseurs Curseur Dynamique : Stmt = rs.createaStatement(ResultSet.TYPE_SCROLL_INSE NSITIVE, ResultSet.CONCUR_READ_UPDATABLE) Les modifications ne sont prises en compte qu’après un rs.updateRow();
juin 2006~ Brigitte Groléas ~ 27 Les différents types de Statement Ordinaires Pré-compilés Procédures stockées
juin 2006~ Brigitte Groléas ~ 28 Modifiez l'exemple précédent pour permettre l'ajout et la suppression de lignes lorsque l'on clique respectivement sur le bouton Ajouter ou Supprimer. Lors de l'ajout d'un enregistrement, une fenêtre popup permet de saisir les nouvelles données Lors de la suppression, une fenêtre popup permet de saisir la valeur du champs nom de l'enregistrement à supprimer dans la base à vous...
juin 2006~ Brigitte Groléas ~ 29 Statement java.sql.Statement Interprété à chaque exécution Long à l'exécution ResultSet result = stmt.executeQuery( "SELECT * FROM ages WHERE nom = 'martin' and age < 12 "); Attention, pas de ; derrière la requête
juin 2006~ Brigitte Groléas ~ 30 Pré-compilés java.sql.PreparedStatement Paramétrables, préparées pour être exécutées plusieurs fois, gérées par le programme Rapide, le type de Statement le plus utilisé PreparedStatement pStmt =con.prepareStatement( “SELECT * FROM ages WHERE nom = ? and age < ? ");
juin 2006~ Brigitte Groléas ~ 31 Les paramètres Les paramètres sont renseignés par leur position : pStmt.setString (1,"paul") le 1 er ? est paul pStmt.setInt (2, 23) le 2 ème ? est 23 Exécution de la requête une fois que les paramètres sont renseignés : pStmt.executeQuery(); Ou executeUpdate() pour les autres types de requêtes
juin 2006~ Brigitte Groléas ~ 32 Dans le programme précédent, remplacez l'utilisation de requêtes simples par des requêtes pré-compilées. Insérer un champ Inscription de type Date que vous ferez afficher dans votre Jtable à vous...
juin 2006~ Brigitte Groléas ~ 33 Procédures Stockées java.sql.CallableStatement Paramétrables, Ecrites dans le langage interne au Sgbd CallableStatement csStmt. = con.prepareCall(" { call pubs.GetRage(?) }"); csSstmt.setInt (1, 23) le 1 er paramètre est 23 csSstmt.executeQuery();
juin 2006~ Brigitte Groléas ~ 34 Transactions Une transaction est un groupe de requêtes devant être exécutées de façon indivisible. Par exemple, le transfert d'un ordre de virement, les ordres de mise à jour de table... La transaction doit être validée (commit) ou annulée ( rollback) Au début de la transaction: con.setAutoCommit( false); Statement st = ….... INSERT....
juin 2006~ Brigitte Groléas ~ 35 Transactions A là fin de la transaction validation de la transaction: con.commit(); ou annulation de la transaction con.rollback();
juin 2006~ Brigitte Groléas ~ 36 Traitement par lots Objectif : réduire le coût d'une série de mises à jour Statement stmt = con.createStatement(); // ajout des différentes requêtes st.addBatch("INSERT INTO ages VALUES( 'Paul',12)); st.addBatch("INSERT INTO ages VALUES( 'Pierre',14)); st.addBatch("INSERT INTO ages VALUES( 'Raoul',112)); // exécution des requêtes int [] res = stmt.executeBatch();
juin 2006~ Brigitte Groléas ~ 37 Recherche de la structure de la base Permet de découvrir le schéma de la base à l'exécution Récupération des enregistrements d'une table : Statement stmt = con.createStatement(); ResultSet rs = st.executeQuery("SELECT * FROM ages"); Récupération d'un objet de la classe ResultSetMetaData décrivant le ResultSet ResultSetMetaData rsmd =rs.getMetaData();
juin 2006~ Brigitte Groléas ~ 38 Recherche de la structure de la base Interrogation du ResultSetMetaData pour découvrir le schéma de la table ages : int colnbre = rsmd.getColumnCount(); String colLabel = rsmd.getColumnLabel(i); String colType = rsmd.getColumnTypeName(i); Informations sur les tables contenues dans la base DataBaseMetaData dbmd = con.getMetaData(); Récupération des tables utilisateur de la base : ResultSet tables = dbmd.getTable(null,null,null, {"Table"});
juin 2006~ Brigitte Groléas ~ 39 Recherche de la structure de la base Récupération des noms de table while( tables.next() ) { String tableName = tables.getString ("TABLES_NAME"); }
juin 2006~ Brigitte Groléas ~ 40 Valeur unique générée automatiquement Valeur incrémentée à chaque ajout d'enregistrement Type auto_increment (MySQL), serial (PostGReSQL) CREATE TABLE users ( id INT, AUTO_INCREMENT, nom VARCHAR(30)) String req = "INSERT INTO users (nom) VALUES ('paul')"; Stmt.executeStatement( req, Statement.RETURN_GENERATED_KEYS ); ResultSet rs = stmt.geGenerateKeys(); rs.next(); int key = rs.getInt(1);