Java : Base de Données

publicité
J530 (JBD)
Java : Base de Données
juin 2006
~ Brigitte Groléas ~
1



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 ~
2
Application JAVA
API JDBC
Jdbc Driver Manager
Jdbc ODBC Driver
JDBC Driver
Pour MySql
JDBC Driver
Pour Oracle
ODBC Driver
Access
juin 2006
SQL server
MySql
~ Brigitte Groléas ~
Oracle
3
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 ~
4
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 ~
5
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 ~
6
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 ~
7
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 jdbc:oracle:thin:@elios. univ-paris8.fr:1521:employes
employes est le SID de votre base
juin 2006
~ Brigitte Groléas ~
8
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 ~
9
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 ~
10
L’implémentation sous Odbc
class Rbd {
Statement stmt = null;
Connection con=null;
public Rbd () {
try {
Attention aux Majuscules
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
} catch (Exception e) {
System.out.println("Failed to load JDBC/ODBC driver.");
return;
}
juin 2006
~ Brigitte Groléas ~
11
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 ~
12
Fermeture de la connexion
public void finalize() {
Pour fermer la connexion
try {
ODBC lors de la destruction
de l'instance
con.close();
// fermeture de la connexion
}
catch (Exception e) {
e.printStackTrace();
}
}
juin 2006
~ Brigitte Groléas ~
13
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 ~
14
Implémentation sous Oracle
try {
con = DriverManager.getConnection
("jdbc:oracle:thin:@poseidon:1521:orcl","stage","st
age");
stmt = con.createStatement();
} catch (Exception e) {
System.err.println("problems connecting to ");
}
juin 2006
~ Brigitte Groléas ~
15
Vrai ou Faux
1.
2.
3.
4.
5.
à vous
Java se connecte toujours à une base de données
avec les droits d'administrateur ?
Une seule connexion est possible par lien odbc ?
Oracle sous Windows est accessible soit par odbc
soit par un driver propre ?
Le nom de la base est toujours identique au nom
du sid ?
Lors d'un lien odbc, le nom de la base n'apparaît
jamais en clair ?
juin 2006
~ Brigitte Groléas ~
16
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 ~
17
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 ~
18
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 ~
19
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 ~
20
Vrai ou Faux ?
1.
2.
3.
4.
à vous
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 ?
Il est possible de créer plusieurs Statement à partir
d'une connexion ?
Le curseur se trouve sur la première ligne du
ResultSet après un executeQuery() ?
Si la requête sql ne retourne aucun enregistrement
de la base, la méthode executeQuery() génère une
exception de type SqlException ?
juin 2006
~ Brigitte Groléas ~
21
à 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 ~
22
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 ~
23
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 ~
24
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 ~
25
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 ~
26
Les différents types de Statement



juin 2006
Ordinaires
Pré-compilés
Procédures stockées
~ Brigitte Groléas ~
27
à vous ...



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
juin 2006
~ Brigitte Groléas ~
28
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 ~
29
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 ~
30
Les paramètres
Les paramètres sont renseignés par leur position :
er ? est paul
 pStmt.setString (1,"paul") le 1
ème ? est 23
 pStmt.setInt (2, 23) le 2
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 ~
31
à vous ...


juin 2006
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
~ Brigitte Groléas ~
32
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 23
csSstmt.executeQuery();
juin 2006
~ Brigitte Groléas ~
33
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 ~
34
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 ~
35
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 ~
36
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 ~
37
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 ~
38
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 ~
39
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);
juin 2006
~ Brigitte Groléas ~
40
Téléchargement