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 DriverPour Oracle
JDBC DriverPour 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 :sourceEx : jdbc:odbc:client
Client est le nom source ODBCDé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 et2. 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:adresseexemple :
jdbc:mysql://elios.univ-paris8.fr/employes
ou jdbc:oracle:thin:@elios. 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
("jdbc:oracle:thin:@poseidon:1521:orcl","stage","stage");
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_ONLYResultSet.TYPE_SCROLL_INSENSITIVEResultSet.TYPE_SCROLL_SENSITIVE
juin 2006 ~ Brigitte Groléas ~ 25
Les curseurs
Modificateurs des options du curseurResultSet.CONCUR_READ_ONLYResultSet.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_INSENSITIVE, 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 1er ? 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 1er paramètre est 23csSstmt.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 à jourStatement stmt = con.createStatement(); // ajout des différentes requêtesst.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 baseDataBaseMetaData 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'enregistrementType 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);