SlideShare une entreprise Scribd logo
1  sur  51
Télécharger pour lire hors ligne
Java et bases de données
JDBC - Stratégies - Pattern DAO - Hibernate
Version du 25/08/2015
JDBC
• API orientée objet unifiée d’accès aux SGBD
• Soumission de requête via un driver
• Accès aux SGBD
• Soit par un driver JDBC adapté
• Soit par des passerelles
• (ex : passerelle JDBC->ODBC)
Process de requétage
1. Chargement du driver
2. Connexion à la base
3. Création de Statement
• Envoi de la requête
• Avec ou sans préparation
4. Prise en compte du résultat éventuel
• Via un ResultSet
5. Fermeture de la connexion
1 - Chargement du
driver
import java.sql.*;
class Cnx
{
public Cnx()
{
try 

{
Class.forName("com.mysql.jdbc.Driver").newInstance();
}
catch (ClassNotFoundException e)
{
System.out.println("Driver spécifié non trouvé");
}
}

}
Accès direct au driver
par une chaîne de
caractères
On utilise
les prototypes
de java.sql
2 - Connexion à la base
Connection cnx;
try
{
cnx=DriverManager.getConnection
("jdbc:mysql://localhost/Bibliotheque","user","passwd");
}
catch (SQLException e)
{
System.out.println("Impossible de se connecter sur la base") ;
System.out.println(e) ;
}
Comment récupérer la
connexion ?
• Il faut éviter à tout prix de relancer X fois la
procédure “chargement driver / connexion”
• Outil de préservation d’unicité : le singleton
Connection cnx=Cnx.getCnx().getConnection();
• Dans un contexte Web, on peut passer par les
séquences d’initialisations du serveur
• Utilisation de Pools de connexion
3 - Création de
Statement
// L’instance de Statement est générée par l’objet connexion
Statement st=cnx.createStatement();


// Exemple de requête avec résultat

ResultSet rs=st.executeQuery("SELECT * FROM table");



// Exemple de requête sans résultat

st.executeUpdate

("DELETE FROM table WHERE num = 1");

4 - Exploitation des
résultats
• Après le SELECT : Exploitation du ResultSet
• Accès aux colonnes par :
• Index (à partir de 1)
XXX getXXX(int index);
• Nom de colonne
XXX getXXX(String nomCol);
Parcours d’un ResultSet
• On utilise la méthode next();
• Certains drivers intègrent d’autres
méthodes :
• previous()
• relative(int mv)
• Toutes retournent un booléan pour inclusion
directe dans un while(...)
Exemples de parcours
d’un ResultSet
while(rs.next())

{

int num=rs.getInt(“num”);

String titre=rs.getString(“titre”);

}
while(rs.next())

{

int num=rs.getInt(1);

String titre=rs.getString(2);

}
5 - Fin de connexion
• Il faut penser à fermer tous les objets
rs.close();

st.close();

cnx.close();
• Il est important de fermer la connexion
• Nombre d’accès limités par SGBD
• Ne pas monopoliser ces ressources !
• Cas particulier : si la connexion est dans un
singleton
Récupération d’une clé
générée
• Certaines tables génèrent automatiquement
leur clé lors d’un INSERT
• (auto_increment sous MySQL)
• Récupération de la clé après le INSERT
• Avec JDBC>=3 :
statement.getGeneratedKeys()
• Sous MySQL : SELECT LAST_INSERT_ID
• Autre SGBD : voir driver propriétaire
Récupération de la clé
String req=”INSERT …“;
st.executeUpdate(sql);
// Récupération avec Statement.getGeneratedKeys()
rs = st.getGeneratedKeys();
if (rs.next())
cle = rs.getInt(1);
// Récupération avec MySQL LAST_INSERT_ID()
rs = st.executeQuery("SELECT LAST_INSERT_ID()");
if (rs.next())
cle = rs.getInt(1);
Les statement préparés
• Permet de faciliter l’écriture de requêtes
complexes
• Stockées dans le SGBD, seuls les paramètres
sont envoyés d’un appel à l’autre
• Permet d’éviter divers problèmes de
syntaxe...
• ...et divers problèmes de sécurité
• + quelques bénéfices de performance
Exemple de
PreparedStatement
// Création du Statement
PreparedStatement phrase= cnx.prepareStatement(
 " INSERT into TABLE (chaine, entier, reel) VALUES (?,?,?) ");


// Mise en place des paramètres
phrase.setString(1, "uneChaine");
phrase.setInt(2, 56);
phrase.setDouble(3, 3.314456);


// Exécution de la requête
phrase.executeUpdate();
Liste de
paramètres
Intérêts du
PreparedStatement
• Légèrement plus efficace (pré-exécution sur
le SGBD)
• Evite des problèmes de syntaxe
• Oublis de ‘ ‘ pour des chaînes,‘ intempestifs
• Protège (partiellement) des injections SQL
• Insertion illicites de requêtes
Traitements batchs
Connection connection = ... ;
Statement statement = connection.createStatement();
if(connection.getMetaData().supportsBatchUpdates()){
connection.setAutoCommit(false);
statement.clearBatch(); //on supprime les anciens batch
statement.addBatch("INSERT ....");
statement.addBatch("UPDATE ...");
statement.addBatch("...");
int[] resultat = statement.executeBatch();
//voir les différents types de retour possibles
connection.commit();
connection.setAutoCommit(false);
}
Intégration des accès à la
base dans les objets
• Un des rôles des objets métiers est de faire la
liaison avec la base de données
• 3 cas principaux sont à traiter :
• Liaison simple une instance = un enreg
• Instances encapsulant des listes
• Structures hiérarchiques (héritage)
Exemple d’intégration
d’appels à la base
• Une classe User utilisée dans un site Web
• On peut :
• Se connecter avec un login/mot de passe
• A vérifier avec un SELECT
• S’enregistrer en donnant un login, un mot
de passe, un nom, une adresse...
• A concrétiser avec un INSERT INTO...
Structure de la classe
User
• C’est un objet CRUD 

(Create/Read/Update/Delete)
• Exemple de création/
enregistrement :

User u=new User();

u.setNom(“.....”);

...

u.insert();
User
login
password
nom
select(login,password)
insert()
update()
delete()
On verra plus
tard qu’il vaut mieux
utiliser un pattern
DAO
Procédure de login
• Comment faire à la fois :
• Contrôler si un login/pass est correct
• Charger les données du user (nom...)
• Empêcher qu’une instance de User soit
incohérente en mémoire (login/pass
incorrect mais encapsulés dans un objet)
• Solution : on utilise un constructeur
• Avec une lancée d’exception éventuelle
Constructeur de User
public class User()

{

public User(String login, String pwd) 

throws UserInexistantException()

{

String sql=”SELECT nom FROM user

WHERE login=’”+login+”’ AND pwd=’”+pwd+”’”;

if(rs.next()) // le login existe

this.nom=rs.getString(“nom”); // on charge les données

else // le login n’existe pas

throw new LoginIncorrectException(login);

}
Exploitation de
liaisons 1-N
• En objet : c’est un attribut qui contient des
instances d’autres objets
• En SGBD : c’est le résultat d’une requête avec
une clé secondaire
• Il va donc falloir faire une requête qui va
remplir la liste
• Problème : comment instancier chacun des
éléments de la liste ?
Exemple de liste en
objet
public class Catalogue
{
private ArrayList<Produit> liste;
public void rech(String texte)
{
// remplissage de la liste
}
…
}
public class Produit
{
private int cle;
private String nom;
...
public void load(int cle)
{
// lecture d’un enregistrement
}
}
Remplissage
“procédural”
public void rech(String texte)
{
sql=”SELECT * FROM produit WHERE ...”;
while(...)
{
Produit p=new Produit();
p.setNom(rs.getString(“nom”));
...

liste.add(p);
}
}
Problème :
on gère la lecture d’un produit
en dehors de la classe Produit
-> non respect de la notion 

d’encapsulation
Remplissage “objet”
public void rech(String texte)
{
sql=”SELECT cle FROM produit WHERE ...”;
while(...)
{
cle=rs.getInt(“cle”);
Produit p=new Produit();
p.load(cle);
liste.add(p);
}
}
Problème :
On génère un grand nombre
de requête (N+1 requêtes,
N étant le nombre de produits)
Solution mixte
public void rech(String texte)
{
sql=”SELECT * FROM produit WHERE ...”;
while(...)
{
Produit p=new Produit();
p.load(rs);
liste.add(p);
}
}
Dans cette solution, on passe
à ‘load’ directement le ResultSet
“rs” afin de traiter la requête à
la source
L’héritage dans un
modèle relationnel
• Problématique : il n’est pas possible de définir
directement une structure d’héritage dans un
système de tables
• Plusieurs solutions sont possibles :
• 1 table regroupant tout
• 1 table par classe fille
• 1 table par classe fille + 1 table pour la
classe mère
Modèle à une table
• A partir d’une hiérarchie de classe Produit ->
Cd ou Livre :
Table produit :
-refprod
-type

-nom
-prix
-dureecd
-nbpageslivres La table contient à la
fois les infos du CD, et celles
du livre
Cette solution est
valable si CD et Livre ont peu
de données divergentesLe type est
encodé dans un
champ
Une table par classe fille
sans factorisation
• A partir d’une hiérarchie de classe Produit ->
Cd ou Livre :
La table Livre contient
toutes les données
d’un livre
Cette solution facilite les requêtes mais
complique les recherches
inter-catégories
Table CD :
-refprod
-nom
-prix
-dureecd
Table Livre :
-refprod
-nom
-prix
-nbpages
1 table par classe fille +
1 table pour classe mère
• A partir d’une hiérarchie de classe Produit ->
Cd ou Livre :
Table Produit :
-refprod
-type

-nom
-prix
La table Livre contient
uniquement les données
propres au livre
Cette solution concilie factorisation
et particularité des types de produits
Table CD :
-refprod
-dureecd
Table Livre :
-refprod
-nbpages
Lecture base d’une
classe polymorphe
• On passe par une Factory qui va délivrer
suivant les cas une instance de CD, de Livre...
Produit p=ProduitFactory.getProduit(int cle);
‘p’ sera en fait une
instance de CD, de Livre..
Factory modèle à 1 table
public static Produit getProduit(int cle)
{
Produit p=null;
sql=”SELECT * FROM produit WHERE ...”;
if(...)
{
type=rs.getString(“type”);
if(type.equals(“cd”))
{
p=new CD();
p.load(rs);
}
}
return p;
}
Factory modèle à N tables
public static Produit getProduit(int cle)
{
Produit p=null;
p=new CD();
if(!p.load(cle))
{
p=new Livre();
if(!p.load(cle))
{
...
}
else p=null;
}
return p;
}
On ne peut que faire des
tests en cascade
Factory modèle à N tables +1
public static Produit getProduit(int cle)
{
Produit p=null;
sql=”SELECT * FROM produit WHERE ...”;
if(...)
{
type=rs.getString(“type”);
if(type.equals(“cd”))
{
p=new CD();
p.load(rs);
}
}
return p;
}
C’est
dans chacune des méthodes
“load()” que l’on va faire une jointure
entre les données ‘mère’ et
‘fille’
Conclusion sur ces
différents scénarios
• Le scénario « 1 table » est peu satisfaisant
d’un point de vue SGBD, mais finalement
limpide à gérer par la Factory
• Le scénario 2 est un peu trop ‘batard’ pour
être utile
• Le scénario « N tables +1 » est un bon
compromis difficulté/propreté de structure
• D’autres structures sont envisageables (ex :
tables décrivant des listes de champs)
Pattern DAO
• Data Access Object
• Permet de résoudre plusieurs problèmes :
• Eviter que les instances d’objets métiers
soient trop lourdes en mémoire
• Permettre des traitements différenciés
suivant les supports (lecture dans un fichier
texte, dans un XML, dans une base…)
• Séparer la partie métier d’aspects beaucoup
plus techniques
Implémentation d’un DAO
UserDAO<User,Integer>
User select(login,password)
insert(User)
update(User)
User
login
password
nom
UserMySQLDAO<User,Integer>
Connection cnx
User select(Integer i)
User select(login,password)
insert(User)
update(User)
DAO<T,U>
<<abstract>>
T select(U id)
insert(T)
update(T)
Utilisation d’un objet
DAO
User u=new User();
u.setNom(« Leponge »);
u.setPrenom(« Bob »);
UserDAO dao = new UserMySQLDAO(cnx);
dao.insert(u);
Hibernate
Persistence d’objet en Java
Rendre un objet
persistant
• Pour rendre un objet persistant, il suffit de le lier à
la session
• session.save(objet);
• La clé pourra éventuellement être générée
automatiquement, et délivrée par save() :
• Long cle=(Long)session.save(objet);
• (clé déclarée assigned dans le HBM)
• Cette clé sera également dans objet.getRef()
Sauvegarde par
saveOrUpdate
• Si la clé a été renseignée dans l’objet :
• Si la clé existe en base : UPDATE
• Si la clé n’existe pas : INSERT
• Si la clé n’a pas été renseignée : INSERT
• Si l’objet existe en base et n’a pas été modifié
en mémoire : pas de requête générée
Chargement d’un objet
Client c=(Client)session.load(Client.class,new Long(12));
• ou :
Client c=new Client();

session.load(c,new Long(12));
• version sans lancement d’exception (renvoie null si l’objet
n’existe pas)
Client c=

(Client)session.get(Client.class,new Long(12));

if(c==null)

c=new Client();
Requêtage HQL
Query q=session.createQuery(“...”);

q.setString(0,”..”);

q.setInt(1,”...”);

List l=q.list(); // émission de la requête
• S’il n’y a qu’un résultat :
Client c=(Client)q.uniqueResult();
Paramètres d’une
requête• Par numéro :
FROM Client WHERE nom=? AND age=?
q.setString(0,”Dupont”); // commence à 0
• Par nom :
FROM Client WHERE nom=:nom AND age=:age
q.setString(“nom”,”Dupont”);
• Listés :
FROM Client WHERE nom IN (:liste)
q.setParameterList(“liste”,unTableau);
Récupération plusieurs
objets d’un coup
Query q = sess.createQuery(
"SELECT facture,client FROM Facture facture 

JOIN Client facture.client client");

List l=q.list();

Iterator it=l.iterator();
while ( it.hasNext() ) {
Object[] tuple = (Object[]) it.next();
Facture f= tuple[0];
Client c = tuple[1];
....
}
Association N-1
unidirectionnelle
<class name="Item">
<id name="ref" column="refitem">
<generator class="native"/>
</id>

<many-to-one name=”prod” class=”Produit”>
<column="refprod"
not-null="true"/>

</many-to-one>
</class>
<class name="Produit">
<id name="ref" column="refprod">
<generator class="native"/>
</id>
</class>
create table Item ( 

refitem bigint not null primary key

refprod bigint not null )
create table Produit ( 

refprod bigint not null primary key)
public class Item ( 

private Long ref;

private Produit prod;
)
public class Produit (
private Long ref;

)
Association 1-1
unidirectionnelle
<class name="Client">
<id name="ref" column="refcli">
<generator class="native"/>
</id>

<many-to-one name=”panier” class=”Panier”>
<column="refpanier"

unique=”true”
not-null="true"/>

</many-to-one>
</class>
<class name="Panier">
<id name="ref" column="refpanier">
<generator class="native"/>
</id>
</class>
create table Client ( 

refcli bigint not null primary key

refpanier bigint not null )
create table Panier ( 

refpanier bigint not null primary key)
public class Client ( 

private Long ref;

private Panier panier;
)
public class Panier (
private Long ref;

)
Association 1-N
unidirectionnelle
<class name="Client">
<id name="ref" column="refclient">
<generator class="native"/>
</id>
<set name="factures">
<key column="refclient"
not-null="true"/>
<one-to-many class="Facture"/>
</set>
</class>
<class name="Facture">
<id name="ref" column="reffacture">
<generator class="native"/>
</id>
</class>
create table Client ( 

refclient bigint not null primary key )
create table Facture ( 

reffacture bigint not null primary key,

refclient bigint not null )
public class Client ( 

private Long ref;

private List factures;
)
public class Facture (
private Long ref;

)
Représentation
d’héritage avec une table
<class name="Produit" table="produit" abstract=”true” discriminator-value=”-”>
<id name="ref" column="ref">
<generator class="native"/>
</id>
<discriminator column="type" type="character"/>
<property name="titre"/>


<subclass name="Livre" discriminator-value="L">
<property name="nbpages"/>
</subclass>
<subclass name="CD" discriminator-value="C">
<property name="duree"/>
<property name="maisondisque"/>
</subclass>
</class>
create table produit (
ref BIGINT not null,
type CHAR(1) not null,
titre VARCHAR(255),
duree FLOAT,
maisondisque VARCHAR(255),
nbpages INTEGER,
primary key (ref)
)
Représentation d’héritage
avec plusieurs tables
<class name="Produit" table="produit" abstract=”true”>
<id name="ref" column="refprod">
<generator class="native"/>
</id>
<discriminator column="type" type="character"/>
<property name="titre"/>


<join-subclass name="CD" table="cd">
<key column="refprod"/>
<property name="maisondisque"/>
</subclass>
</class>
create table produit (
ref BIGINT not null,
type CHAR(1) not null,
titre VARCHAR(255),
duree FLOAT,
maisondisque VARCHAR(255),
nbpages INTEGER,
primary key (ref)
)
create table cd (
ref BIGINT not null,
maisondisque VARCHAR(255),
primary key (ref)
)

Contenu connexe

Tendances

POO Java Chapitre 4 Heritage et Polymorphisme
POO Java Chapitre 4 Heritage et PolymorphismePOO Java Chapitre 4 Heritage et Polymorphisme
POO Java Chapitre 4 Heritage et PolymorphismeMouna Torjmen
 
Tp2 - WS avec JAXRS
Tp2 - WS avec JAXRSTp2 - WS avec JAXRS
Tp2 - WS avec JAXRSLilia Sfaxi
 
Formation JAVA/J2EE
Formation JAVA/J2EEFormation JAVA/J2EE
Formation JAVA/J2EEInes Ouaz
 
Java 8 - collections et stream
Java 8 - collections et streamJava 8 - collections et stream
Java 8 - collections et streamFranck SIMON
 
POO Java Chapitre 2 Encapsulation
POO Java Chapitre 2 EncapsulationPOO Java Chapitre 2 Encapsulation
POO Java Chapitre 2 EncapsulationMouna Torjmen
 
Cours javascript
Cours javascriptCours javascript
Cours javascriptkrymo
 
Exercice 1 java Héritage
Exercice 1 java HéritageExercice 1 java Héritage
Exercice 1 java HéritageNadaBenLatifa
 
Appalications JEE avec Servlet/JSP
Appalications JEE avec Servlet/JSPAppalications JEE avec Servlet/JSP
Appalications JEE avec Servlet/JSPYouness Boukouchi
 
Correction examen-java-avancé-1
Correction examen-java-avancé-1Correction examen-java-avancé-1
Correction examen-java-avancé-1vangogue
 
Chapitre 6 traitement des exceptions
Chapitre 6  traitement des exceptionsChapitre 6  traitement des exceptions
Chapitre 6 traitement des exceptionsAmir Souissi
 
Examen principal- php - correction
Examen principal- php - correctionExamen principal- php - correction
Examen principal- php - correctionInes Ouaz
 
Introduction à JavaScript
Introduction à JavaScriptIntroduction à JavaScript
Introduction à JavaScriptAbdoulaye Dieng
 
Angular Framework présentation PPT LIGHT
Angular Framework présentation PPT LIGHTAngular Framework présentation PPT LIGHT
Angular Framework présentation PPT LIGHTtayebbousfiha1
 
Cours les Listes doublement chainées Prof. KHALIFA MANSOURI
Cours les Listes doublement chainées Prof. KHALIFA MANSOURI Cours les Listes doublement chainées Prof. KHALIFA MANSOURI
Cours les Listes doublement chainées Prof. KHALIFA MANSOURI Mansouri Khalifa
 
Exercice 2 java Héritage
Exercice 2  java HéritageExercice 2  java Héritage
Exercice 2 java HéritageNadaBenLatifa
 
Java cours n° 2 - classe-objet-constructeur
Java   cours n° 2 - classe-objet-constructeurJava   cours n° 2 - classe-objet-constructeur
Java cours n° 2 - classe-objet-constructeurAbdelwahab Naji
 

Tendances (20)

POO Java Chapitre 4 Heritage et Polymorphisme
POO Java Chapitre 4 Heritage et PolymorphismePOO Java Chapitre 4 Heritage et Polymorphisme
POO Java Chapitre 4 Heritage et Polymorphisme
 
Tp2 - WS avec JAXRS
Tp2 - WS avec JAXRSTp2 - WS avec JAXRS
Tp2 - WS avec JAXRS
 
Formation JAVA/J2EE
Formation JAVA/J2EEFormation JAVA/J2EE
Formation JAVA/J2EE
 
Java 8 - collections et stream
Java 8 - collections et streamJava 8 - collections et stream
Java 8 - collections et stream
 
POO Java Chapitre 2 Encapsulation
POO Java Chapitre 2 EncapsulationPOO Java Chapitre 2 Encapsulation
POO Java Chapitre 2 Encapsulation
 
Cours javascript
Cours javascriptCours javascript
Cours javascript
 
Exercice 1 java Héritage
Exercice 1 java HéritageExercice 1 java Héritage
Exercice 1 java Héritage
 
Appalications JEE avec Servlet/JSP
Appalications JEE avec Servlet/JSPAppalications JEE avec Servlet/JSP
Appalications JEE avec Servlet/JSP
 
Correction examen-java-avancé-1
Correction examen-java-avancé-1Correction examen-java-avancé-1
Correction examen-java-avancé-1
 
Les collections en Java
Les collections en JavaLes collections en Java
Les collections en Java
 
Support de cours angular
Support de cours angularSupport de cours angular
Support de cours angular
 
Corrige tp java
Corrige tp javaCorrige tp java
Corrige tp java
 
Cours javascript v1
Cours javascript v1Cours javascript v1
Cours javascript v1
 
Chapitre 6 traitement des exceptions
Chapitre 6  traitement des exceptionsChapitre 6  traitement des exceptions
Chapitre 6 traitement des exceptions
 
Examen principal- php - correction
Examen principal- php - correctionExamen principal- php - correction
Examen principal- php - correction
 
Introduction à JavaScript
Introduction à JavaScriptIntroduction à JavaScript
Introduction à JavaScript
 
Angular Framework présentation PPT LIGHT
Angular Framework présentation PPT LIGHTAngular Framework présentation PPT LIGHT
Angular Framework présentation PPT LIGHT
 
Cours les Listes doublement chainées Prof. KHALIFA MANSOURI
Cours les Listes doublement chainées Prof. KHALIFA MANSOURI Cours les Listes doublement chainées Prof. KHALIFA MANSOURI
Cours les Listes doublement chainées Prof. KHALIFA MANSOURI
 
Exercice 2 java Héritage
Exercice 2  java HéritageExercice 2  java Héritage
Exercice 2 java Héritage
 
Java cours n° 2 - classe-objet-constructeur
Java   cours n° 2 - classe-objet-constructeurJava   cours n° 2 - classe-objet-constructeur
Java cours n° 2 - classe-objet-constructeur
 

Similaire à JAVA, JDBC et liaison base de données

Marzouk une introduction à jdbc
Marzouk une introduction à jdbcMarzouk une introduction à jdbc
Marzouk une introduction à jdbcabderrahim marzouk
 
Java Database Connectivity
Java Database ConnectivityJava Database Connectivity
Java Database ConnectivityKorteby Farouk
 
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018Loic Yon
 
Présentaion sur le modéle JDBC JEE .pptx
Présentaion sur le modéle JDBC JEE .pptxPrésentaion sur le modéle JDBC JEE .pptx
Présentaion sur le modéle JDBC JEE .pptxsalmachtioui1
 
Fmin103 0910 tpjdbc
Fmin103 0910 tpjdbcFmin103 0910 tpjdbc
Fmin103 0910 tpjdbcKarim Amane
 
GWT : under the hood
GWT : under the hoodGWT : under the hood
GWT : under the hoodsvuillet
 
Introduction à scala
Introduction à scalaIntroduction à scala
Introduction à scalaSOAT
 
Introduction à JavaScript
Introduction à JavaScriptIntroduction à JavaScript
Introduction à JavaScriptAbdoulaye Dieng
 
Eric Moreau: AOP in .Net sing PostSharp
Eric Moreau: AOP in .Net sing PostSharpEric Moreau: AOP in .Net sing PostSharp
Eric Moreau: AOP in .Net sing PostSharpMSDEVMTL
 
Accès aux bases de données via jdbc
Accès aux bases de données via jdbcAccès aux bases de données via jdbc
Accès aux bases de données via jdbcRachid Lajouad
 
WS User Group - Spring Batch - Xebia
WS User Group - Spring Batch - XebiaWS User Group - Spring Batch - Xebia
WS User Group - Spring Batch - XebiaOlivier BAZOUD
 
Présentation Javascript à l'ESI (Alger)
Présentation Javascript à l'ESI (Alger)Présentation Javascript à l'ESI (Alger)
Présentation Javascript à l'ESI (Alger)Dr Samir A. ROUABHI
 

Similaire à JAVA, JDBC et liaison base de données (20)

Marzouk une introduction à jdbc
Marzouk une introduction à jdbcMarzouk une introduction à jdbc
Marzouk une introduction à jdbc
 
Android ORMLite
Android   ORMLiteAndroid   ORMLite
Android ORMLite
 
Jdbc
JdbcJdbc
Jdbc
 
Java Database Connectivity
Java Database ConnectivityJava Database Connectivity
Java Database Connectivity
 
Cours_Java.pdf
Cours_Java.pdfCours_Java.pdf
Cours_Java.pdf
 
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
 
Présentaion sur le modéle JDBC JEE .pptx
Présentaion sur le modéle JDBC JEE .pptxPrésentaion sur le modéle JDBC JEE .pptx
Présentaion sur le modéle JDBC JEE .pptx
 
Fmin103 0910 tpjdbc
Fmin103 0910 tpjdbcFmin103 0910 tpjdbc
Fmin103 0910 tpjdbc
 
Jdbc
JdbcJdbc
Jdbc
 
GWT : under the hood
GWT : under the hoodGWT : under the hood
GWT : under the hood
 
Introduction à scala
Introduction à scalaIntroduction à scala
Introduction à scala
 
Introduction à JavaScript
Introduction à JavaScriptIntroduction à JavaScript
Introduction à JavaScript
 
Présentation nouveauté java7
Présentation nouveauté java7Présentation nouveauté java7
Présentation nouveauté java7
 
Eric Moreau: AOP in .Net sing PostSharp
Eric Moreau: AOP in .Net sing PostSharpEric Moreau: AOP in .Net sing PostSharp
Eric Moreau: AOP in .Net sing PostSharp
 
Part1
Part1Part1
Part1
 
Accès aux bases de données via jdbc
Accès aux bases de données via jdbcAccès aux bases de données via jdbc
Accès aux bases de données via jdbc
 
WS User Group - Spring Batch - Xebia
WS User Group - Spring Batch - XebiaWS User Group - Spring Batch - Xebia
WS User Group - Spring Batch - Xebia
 
Hibernate
HibernateHibernate
Hibernate
 
Présentation Javascript à l'ESI (Alger)
Présentation Javascript à l'ESI (Alger)Présentation Javascript à l'ESI (Alger)
Présentation Javascript à l'ESI (Alger)
 
Spark - Ippevent 19-02-2015
Spark - Ippevent 19-02-2015Spark - Ippevent 19-02-2015
Spark - Ippevent 19-02-2015
 

Plus de Jean David Olekhnovitch (12)

Designs Patterns
Designs PatternsDesigns Patterns
Designs Patterns
 
Python
PythonPython
Python
 
Internet mobile : conception de sites et d'applications
Internet mobile : conception de sites et d'applicationsInternet mobile : conception de sites et d'applications
Internet mobile : conception de sites et d'applications
 
Développement web mobile avec IONIC 2
Développement web mobile avec IONIC 2Développement web mobile avec IONIC 2
Développement web mobile avec IONIC 2
 
Agilité et Entreprise libérée
Agilité et Entreprise libéréeAgilité et Entreprise libérée
Agilité et Entreprise libérée
 
Télétravail et égilité : un mariage impossible ?
Télétravail et égilité : un mariage impossible ?Télétravail et égilité : un mariage impossible ?
Télétravail et égilité : un mariage impossible ?
 
Java - implémentation des concepts objets
Java - implémentation des concepts objetsJava - implémentation des concepts objets
Java - implémentation des concepts objets
 
Java - notions de bases pour développeur
Java - notions de bases pour développeurJava - notions de bases pour développeur
Java - notions de bases pour développeur
 
Internet mobile
Internet mobileInternet mobile
Internet mobile
 
Ecommerce
EcommerceEcommerce
Ecommerce
 
Genielogiciel
GenielogicielGenielogiciel
Genielogiciel
 
Plan d'action WAI
Plan d'action WAIPlan d'action WAI
Plan d'action WAI
 

JAVA, JDBC et liaison base de données

  • 1. Java et bases de données JDBC - Stratégies - Pattern DAO - Hibernate Version du 25/08/2015
  • 2. JDBC • API orientée objet unifiée d’accès aux SGBD • Soumission de requête via un driver • Accès aux SGBD • Soit par un driver JDBC adapté • Soit par des passerelles • (ex : passerelle JDBC->ODBC)
  • 3. Process de requétage 1. Chargement du driver 2. Connexion à la base 3. Création de Statement • Envoi de la requête • Avec ou sans préparation 4. Prise en compte du résultat éventuel • Via un ResultSet 5. Fermeture de la connexion
  • 4. 1 - Chargement du driver import java.sql.*; class Cnx { public Cnx() { try 
 { Class.forName("com.mysql.jdbc.Driver").newInstance(); } catch (ClassNotFoundException e) { System.out.println("Driver spécifié non trouvé"); } }
 } Accès direct au driver par une chaîne de caractères On utilise les prototypes de java.sql
  • 5. 2 - Connexion à la base Connection cnx; try { cnx=DriverManager.getConnection ("jdbc:mysql://localhost/Bibliotheque","user","passwd"); } catch (SQLException e) { System.out.println("Impossible de se connecter sur la base") ; System.out.println(e) ; }
  • 6. Comment récupérer la connexion ? • Il faut éviter à tout prix de relancer X fois la procédure “chargement driver / connexion” • Outil de préservation d’unicité : le singleton Connection cnx=Cnx.getCnx().getConnection(); • Dans un contexte Web, on peut passer par les séquences d’initialisations du serveur • Utilisation de Pools de connexion
  • 7. 3 - Création de Statement // L’instance de Statement est générée par l’objet connexion Statement st=cnx.createStatement(); 
 // Exemple de requête avec résultat
 ResultSet rs=st.executeQuery("SELECT * FROM table");
 
 // Exemple de requête sans résultat
 st.executeUpdate
 ("DELETE FROM table WHERE num = 1");

  • 8. 4 - Exploitation des résultats • Après le SELECT : Exploitation du ResultSet • Accès aux colonnes par : • Index (à partir de 1) XXX getXXX(int index); • Nom de colonne XXX getXXX(String nomCol);
  • 9. Parcours d’un ResultSet • On utilise la méthode next(); • Certains drivers intègrent d’autres méthodes : • previous() • relative(int mv) • Toutes retournent un booléan pour inclusion directe dans un while(...)
  • 10. Exemples de parcours d’un ResultSet while(rs.next())
 {
 int num=rs.getInt(“num”);
 String titre=rs.getString(“titre”);
 } while(rs.next())
 {
 int num=rs.getInt(1);
 String titre=rs.getString(2);
 }
  • 11. 5 - Fin de connexion • Il faut penser à fermer tous les objets rs.close();
 st.close();
 cnx.close(); • Il est important de fermer la connexion • Nombre d’accès limités par SGBD • Ne pas monopoliser ces ressources ! • Cas particulier : si la connexion est dans un singleton
  • 12. Récupération d’une clé générée • Certaines tables génèrent automatiquement leur clé lors d’un INSERT • (auto_increment sous MySQL) • Récupération de la clé après le INSERT • Avec JDBC>=3 : statement.getGeneratedKeys() • Sous MySQL : SELECT LAST_INSERT_ID • Autre SGBD : voir driver propriétaire
  • 13. Récupération de la clé String req=”INSERT …“; st.executeUpdate(sql); // Récupération avec Statement.getGeneratedKeys() rs = st.getGeneratedKeys(); if (rs.next()) cle = rs.getInt(1); // Récupération avec MySQL LAST_INSERT_ID() rs = st.executeQuery("SELECT LAST_INSERT_ID()"); if (rs.next()) cle = rs.getInt(1);
  • 14. Les statement préparés • Permet de faciliter l’écriture de requêtes complexes • Stockées dans le SGBD, seuls les paramètres sont envoyés d’un appel à l’autre • Permet d’éviter divers problèmes de syntaxe... • ...et divers problèmes de sécurité • + quelques bénéfices de performance
  • 15. Exemple de PreparedStatement // Création du Statement PreparedStatement phrase= cnx.prepareStatement(  " INSERT into TABLE (chaine, entier, reel) VALUES (?,?,?) "); 
 // Mise en place des paramètres phrase.setString(1, "uneChaine"); phrase.setInt(2, 56); phrase.setDouble(3, 3.314456); 
 // Exécution de la requête phrase.executeUpdate(); Liste de paramètres
  • 16. Intérêts du PreparedStatement • Légèrement plus efficace (pré-exécution sur le SGBD) • Evite des problèmes de syntaxe • Oublis de ‘ ‘ pour des chaînes,‘ intempestifs • Protège (partiellement) des injections SQL • Insertion illicites de requêtes
  • 17. Traitements batchs Connection connection = ... ; Statement statement = connection.createStatement(); if(connection.getMetaData().supportsBatchUpdates()){ connection.setAutoCommit(false); statement.clearBatch(); //on supprime les anciens batch statement.addBatch("INSERT ...."); statement.addBatch("UPDATE ..."); statement.addBatch("..."); int[] resultat = statement.executeBatch(); //voir les différents types de retour possibles connection.commit(); connection.setAutoCommit(false); }
  • 18. Intégration des accès à la base dans les objets • Un des rôles des objets métiers est de faire la liaison avec la base de données • 3 cas principaux sont à traiter : • Liaison simple une instance = un enreg • Instances encapsulant des listes • Structures hiérarchiques (héritage)
  • 19. Exemple d’intégration d’appels à la base • Une classe User utilisée dans un site Web • On peut : • Se connecter avec un login/mot de passe • A vérifier avec un SELECT • S’enregistrer en donnant un login, un mot de passe, un nom, une adresse... • A concrétiser avec un INSERT INTO...
  • 20. Structure de la classe User • C’est un objet CRUD 
 (Create/Read/Update/Delete) • Exemple de création/ enregistrement :
 User u=new User();
 u.setNom(“.....”);
 ...
 u.insert(); User login password nom select(login,password) insert() update() delete() On verra plus tard qu’il vaut mieux utiliser un pattern DAO
  • 21. Procédure de login • Comment faire à la fois : • Contrôler si un login/pass est correct • Charger les données du user (nom...) • Empêcher qu’une instance de User soit incohérente en mémoire (login/pass incorrect mais encapsulés dans un objet) • Solution : on utilise un constructeur • Avec une lancée d’exception éventuelle
  • 22. Constructeur de User public class User()
 {
 public User(String login, String pwd) 
 throws UserInexistantException()
 {
 String sql=”SELECT nom FROM user
 WHERE login=’”+login+”’ AND pwd=’”+pwd+”’”;
 if(rs.next()) // le login existe
 this.nom=rs.getString(“nom”); // on charge les données
 else // le login n’existe pas
 throw new LoginIncorrectException(login);
 }
  • 23. Exploitation de liaisons 1-N • En objet : c’est un attribut qui contient des instances d’autres objets • En SGBD : c’est le résultat d’une requête avec une clé secondaire • Il va donc falloir faire une requête qui va remplir la liste • Problème : comment instancier chacun des éléments de la liste ?
  • 24. Exemple de liste en objet public class Catalogue { private ArrayList<Produit> liste; public void rech(String texte) { // remplissage de la liste } … } public class Produit { private int cle; private String nom; ... public void load(int cle) { // lecture d’un enregistrement } }
  • 25. Remplissage “procédural” public void rech(String texte) { sql=”SELECT * FROM produit WHERE ...”; while(...) { Produit p=new Produit(); p.setNom(rs.getString(“nom”)); ...
 liste.add(p); } } Problème : on gère la lecture d’un produit en dehors de la classe Produit -> non respect de la notion 
 d’encapsulation
  • 26. Remplissage “objet” public void rech(String texte) { sql=”SELECT cle FROM produit WHERE ...”; while(...) { cle=rs.getInt(“cle”); Produit p=new Produit(); p.load(cle); liste.add(p); } } Problème : On génère un grand nombre de requête (N+1 requêtes, N étant le nombre de produits)
  • 27. Solution mixte public void rech(String texte) { sql=”SELECT * FROM produit WHERE ...”; while(...) { Produit p=new Produit(); p.load(rs); liste.add(p); } } Dans cette solution, on passe à ‘load’ directement le ResultSet “rs” afin de traiter la requête à la source
  • 28. L’héritage dans un modèle relationnel • Problématique : il n’est pas possible de définir directement une structure d’héritage dans un système de tables • Plusieurs solutions sont possibles : • 1 table regroupant tout • 1 table par classe fille • 1 table par classe fille + 1 table pour la classe mère
  • 29. Modèle à une table • A partir d’une hiérarchie de classe Produit -> Cd ou Livre : Table produit : -refprod -type
 -nom -prix -dureecd -nbpageslivres La table contient à la fois les infos du CD, et celles du livre Cette solution est valable si CD et Livre ont peu de données divergentesLe type est encodé dans un champ
  • 30. Une table par classe fille sans factorisation • A partir d’une hiérarchie de classe Produit -> Cd ou Livre : La table Livre contient toutes les données d’un livre Cette solution facilite les requêtes mais complique les recherches inter-catégories Table CD : -refprod -nom -prix -dureecd Table Livre : -refprod -nom -prix -nbpages
  • 31. 1 table par classe fille + 1 table pour classe mère • A partir d’une hiérarchie de classe Produit -> Cd ou Livre : Table Produit : -refprod -type
 -nom -prix La table Livre contient uniquement les données propres au livre Cette solution concilie factorisation et particularité des types de produits Table CD : -refprod -dureecd Table Livre : -refprod -nbpages
  • 32. Lecture base d’une classe polymorphe • On passe par une Factory qui va délivrer suivant les cas une instance de CD, de Livre... Produit p=ProduitFactory.getProduit(int cle); ‘p’ sera en fait une instance de CD, de Livre..
  • 33. Factory modèle à 1 table public static Produit getProduit(int cle) { Produit p=null; sql=”SELECT * FROM produit WHERE ...”; if(...) { type=rs.getString(“type”); if(type.equals(“cd”)) { p=new CD(); p.load(rs); } } return p; }
  • 34. Factory modèle à N tables public static Produit getProduit(int cle) { Produit p=null; p=new CD(); if(!p.load(cle)) { p=new Livre(); if(!p.load(cle)) { ... } else p=null; } return p; } On ne peut que faire des tests en cascade
  • 35. Factory modèle à N tables +1 public static Produit getProduit(int cle) { Produit p=null; sql=”SELECT * FROM produit WHERE ...”; if(...) { type=rs.getString(“type”); if(type.equals(“cd”)) { p=new CD(); p.load(rs); } } return p; } C’est dans chacune des méthodes “load()” que l’on va faire une jointure entre les données ‘mère’ et ‘fille’
  • 36. Conclusion sur ces différents scénarios • Le scénario « 1 table » est peu satisfaisant d’un point de vue SGBD, mais finalement limpide à gérer par la Factory • Le scénario 2 est un peu trop ‘batard’ pour être utile • Le scénario « N tables +1 » est un bon compromis difficulté/propreté de structure • D’autres structures sont envisageables (ex : tables décrivant des listes de champs)
  • 37. Pattern DAO • Data Access Object • Permet de résoudre plusieurs problèmes : • Eviter que les instances d’objets métiers soient trop lourdes en mémoire • Permettre des traitements différenciés suivant les supports (lecture dans un fichier texte, dans un XML, dans une base…) • Séparer la partie métier d’aspects beaucoup plus techniques
  • 38. Implémentation d’un DAO UserDAO<User,Integer> User select(login,password) insert(User) update(User) User login password nom UserMySQLDAO<User,Integer> Connection cnx User select(Integer i) User select(login,password) insert(User) update(User) DAO<T,U> <<abstract>> T select(U id) insert(T) update(T)
  • 39. Utilisation d’un objet DAO User u=new User(); u.setNom(« Leponge »); u.setPrenom(« Bob »); UserDAO dao = new UserMySQLDAO(cnx); dao.insert(u);
  • 41. Rendre un objet persistant • Pour rendre un objet persistant, il suffit de le lier à la session • session.save(objet); • La clé pourra éventuellement être générée automatiquement, et délivrée par save() : • Long cle=(Long)session.save(objet); • (clé déclarée assigned dans le HBM) • Cette clé sera également dans objet.getRef()
  • 42. Sauvegarde par saveOrUpdate • Si la clé a été renseignée dans l’objet : • Si la clé existe en base : UPDATE • Si la clé n’existe pas : INSERT • Si la clé n’a pas été renseignée : INSERT • Si l’objet existe en base et n’a pas été modifié en mémoire : pas de requête générée
  • 43. Chargement d’un objet Client c=(Client)session.load(Client.class,new Long(12)); • ou : Client c=new Client();
 session.load(c,new Long(12)); • version sans lancement d’exception (renvoie null si l’objet n’existe pas) Client c=
 (Client)session.get(Client.class,new Long(12));
 if(c==null)
 c=new Client();
  • 44. Requêtage HQL Query q=session.createQuery(“...”);
 q.setString(0,”..”);
 q.setInt(1,”...”);
 List l=q.list(); // émission de la requête • S’il n’y a qu’un résultat : Client c=(Client)q.uniqueResult();
  • 45. Paramètres d’une requête• Par numéro : FROM Client WHERE nom=? AND age=? q.setString(0,”Dupont”); // commence à 0 • Par nom : FROM Client WHERE nom=:nom AND age=:age q.setString(“nom”,”Dupont”); • Listés : FROM Client WHERE nom IN (:liste) q.setParameterList(“liste”,unTableau);
  • 46. Récupération plusieurs objets d’un coup Query q = sess.createQuery( "SELECT facture,client FROM Facture facture 
 JOIN Client facture.client client");
 List l=q.list();
 Iterator it=l.iterator(); while ( it.hasNext() ) { Object[] tuple = (Object[]) it.next(); Facture f= tuple[0]; Client c = tuple[1]; .... }
  • 47. Association N-1 unidirectionnelle <class name="Item"> <id name="ref" column="refitem"> <generator class="native"/> </id>
 <many-to-one name=”prod” class=”Produit”> <column="refprod" not-null="true"/>
 </many-to-one> </class> <class name="Produit"> <id name="ref" column="refprod"> <generator class="native"/> </id> </class> create table Item ( 
 refitem bigint not null primary key
 refprod bigint not null ) create table Produit ( 
 refprod bigint not null primary key) public class Item ( 
 private Long ref;
 private Produit prod; ) public class Produit ( private Long ref;
 )
  • 48. Association 1-1 unidirectionnelle <class name="Client"> <id name="ref" column="refcli"> <generator class="native"/> </id>
 <many-to-one name=”panier” class=”Panier”> <column="refpanier"
 unique=”true” not-null="true"/>
 </many-to-one> </class> <class name="Panier"> <id name="ref" column="refpanier"> <generator class="native"/> </id> </class> create table Client ( 
 refcli bigint not null primary key
 refpanier bigint not null ) create table Panier ( 
 refpanier bigint not null primary key) public class Client ( 
 private Long ref;
 private Panier panier; ) public class Panier ( private Long ref;
 )
  • 49. Association 1-N unidirectionnelle <class name="Client"> <id name="ref" column="refclient"> <generator class="native"/> </id> <set name="factures"> <key column="refclient" not-null="true"/> <one-to-many class="Facture"/> </set> </class> <class name="Facture"> <id name="ref" column="reffacture"> <generator class="native"/> </id> </class> create table Client ( 
 refclient bigint not null primary key ) create table Facture ( 
 reffacture bigint not null primary key,
 refclient bigint not null ) public class Client ( 
 private Long ref;
 private List factures; ) public class Facture ( private Long ref;
 )
  • 50. Représentation d’héritage avec une table <class name="Produit" table="produit" abstract=”true” discriminator-value=”-”> <id name="ref" column="ref"> <generator class="native"/> </id> <discriminator column="type" type="character"/> <property name="titre"/> 
 <subclass name="Livre" discriminator-value="L"> <property name="nbpages"/> </subclass> <subclass name="CD" discriminator-value="C"> <property name="duree"/> <property name="maisondisque"/> </subclass> </class> create table produit ( ref BIGINT not null, type CHAR(1) not null, titre VARCHAR(255), duree FLOAT, maisondisque VARCHAR(255), nbpages INTEGER, primary key (ref) )
  • 51. Représentation d’héritage avec plusieurs tables <class name="Produit" table="produit" abstract=”true”> <id name="ref" column="refprod"> <generator class="native"/> </id> <discriminator column="type" type="character"/> <property name="titre"/> 
 <join-subclass name="CD" table="cd"> <key column="refprod"/> <property name="maisondisque"/> </subclass> </class> create table produit ( ref BIGINT not null, type CHAR(1) not null, titre VARCHAR(255), duree FLOAT, maisondisque VARCHAR(255), nbpages INTEGER, primary key (ref) ) create table cd ( ref BIGINT not null, maisondisque VARCHAR(255), primary key (ref) )