Vous êtes sur la page 1sur 47

Java : gérer une base de données avec JDBC

Achref El Mouelhi

Docteur de l’université d’Aix-Marseille


Chercheur en programmation par contrainte (IA)
Ingénieur en génie logiciel

elmouelhi.achref@gmail.com

H & H: Research and Training 1 / 41


Plan

1 Introduction

2 Utilisation

3 Transactions

4 Restructuration du code
Classes connexion et dao
DataSource et fichier de propriétés

H & H: Research and Training 2 / 41


Introduction

JDBC

Pour se connecter à une base de données


Il nous faut un JDBC (qui varie selon le SGBD utilisé)
JDBC : Java DataBase Connectivity
I c

deE
SGBD : Système de Gestion de BasesU
H
L ées
donn

L MO
h r e fE
A c
c

H & H: Research and Training 3 / 41


Introduction

JDBC

Pour se connecter à une base de données


Il nous faut un JDBC (qui varie selon le SGBD utilisé)
JDBC : Java DataBase Connectivity
I c

deE
SGBD : Système de Gestion de BasesU
H
L ées
donn

L MO
h r e fE
c
JDBC ? c A
Une API (interface d’application) créée par Sun Microsystems
Il permet d’accéder aux bases de données en utilisant un driver
JDBC

H & H: Research and Training 3 / 41


Introduction

JDBC

I c

JDBC 8.0.13
EL H
U
MO
Aller sur
L
https://dev.mysql.com/downloads/file/?id=480292
f E l’archive .zip
Télécharger et Dh
c r e
écompresser
c
A

H & H: Research and Training 4 / 41


Introduction

JDBC

Intégrer le driver dans votre projet


I c

E
Faire un clic droit sur le nom du projet et aller
H
Ldans New >
U
Folder
L MO
Renommer le répertoire
r e E puis valider
f lib
A h
cde l’archive décompressée dans lib
c
Copier le .jar

H & H: Research and Training 5 / 41


Introduction

JDBC
Ajouter JDBC au path du projet

Faire clic droit sur .jar qu’on a placé dans lib

Aller dans Build Path et choisir Add to Build Path

I c

ELH
U
L MO
f E
chre
c A

H & H: Research and Training 6 / 41


Introduction

JDBC
Ajouter JDBC au path du projet

Faire clic droit sur .jar qu’on a placé dans lib

Aller dans Build Path et choisir Add to Build Path

I c

Ou aussi
ELH
U
MO
Faire clic droit sur le projet dans Package Explorer et aller dans Properties
L
Properties
f E
hre
Dans Java Build Path, aller dans l’onglet Libraries
c
c A

Cliquer sur Add JARs

Indiquer le chemin du .jar qui se trouve dans le répertoire lib du projet

Appliquer

H & H: Research and Training 6 / 41


Introduction

JDBC
Ajouter JDBC au path du projet

Faire clic droit sur .jar qu’on a placé dans lib

Aller dans Build Path et choisir Add to Build Path

I c

Ou aussi
ELH
U
MO
Faire clic droit sur le projet dans Package Explorer et aller dans Properties
L
Properties
f E
hre
Dans Java Build Path, aller dans l’onglet Libraries
c
c A

Cliquer sur Add JARs

Indiquer le chemin du .jar qui se trouve dans le répertoire lib du projet

Appliquer

Vérifier qu’une section Referenced Libraries a apparu.

H & H: Research and Training 6 / 41


Utilisation

JDBC
Avant de commencer, voici le script SQL qui permet de créer la base de
données utilisée dans ce cours

CREATE DATABASE jdbc;

USE jdbc;
I c

E LH
CREATE TABLE personne(
num INT PRIMARY KEY AUTO_INCREMENT, OU
L M
nom VARCHAR(30),
prenom VARCHAR(30)
ref E
);
c h
c A
SHOW TABLES;

INSERT INTO personne (nom, prenom) VALUES ("Wick", "John"),


("Dalton", "Jack");

SELECT * FROM personne;

H & H: Research and Training 7 / 41


Utilisation

JDBC

Trois étapes I c

H
L cas)
Enotre
Charger le driver JDBC (pour MySQL dansU
la L
Établir la connexion avec E
MO
base de données

c h ref
c A
Créer et exécuter des requêtes SQL

H & H: Research and Training 8 / 41


Utilisation

JDBC

I c

EL H
Avant de commencer
O U
Tous les imports de ce chapitre sontM
fE L de java.sql.*;

c h r e
c
A

H & H: Research and Training 9 / 41


Utilisation

JDBC
Chargement du driver 5
try {
Class.forName("com.mysql.jdbc.Driver");
}
catch (ClassNotFoundException e) { I c

System.out.println(e.getMessage());
ELH
U
}
L MO
r8e f E
c h
Chargement du driver
try { c A
Class.forName("com.mysql.cj.jdbc.Driver");
}
catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
}
H & H: Research and Training 10 / 41
Utilisation

JDBC

Se connecter à la base de données


Il faut spécifier l’URL (de la forme
I c
jdbc:mysql://hote:port/nombd) H
ELMySQL est installé
U
MO
hote : le nom de l’hôte sur lequel le serveur
L
(dans notre cas localhost ou 127.0.0.1)
Eé par défaut par MySQL est 3306
futilis
r e
port : le port TCP/IP
h
nombd :A le c
nom de la base de données MySQL
c
Il faut aussi le nom d’utilisateur et son mot de passe (qui
permettent de se connecter à la base de données MySQL)

H & H: Research and Training 11 / 41


Utilisation

JDBC

Connexion à la base

String url = "jdbc:mysql://localhost:3306/jdbc";


String user = "root";
String password = "";
Connection connexion = null;
I c

try {
ELH
U
connexion = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
L MO
f E
hre
}
finally {
c
c A
if (connexion != null)
try {

connexion.close();
} catch (SQLException ignore) {
ignore.printStackTrace();
}
}

H & H: Research and Training 12 / 41


Utilisation

JDBC

I c

En cas de problème avec le chargement du driver, modifier l’URL
de connexion ainsi :
ELH
U
String url =
L MO
f E
"jdbc:mysql://localhost:3306/jdbc?useSSL=false&
serverTimezone=UTC";
chre
c A

H & H: Research and Training 13 / 41


Utilisation

JDBC
Préparation et exécution de la requête
// création de la requête (statement)
Statement statement = connexion.createStatement();

// Préparation de la requête
I c

EL H
String request = "SELECT * FROM Personne;";
O U
// Exécution de la requête M
ResultSet result = e fE L
c h r statement.executeQuery(request);

c A

H & H: Research and Training 14 / 41


Utilisation

JDBC
Préparation et exécution de la requête
// création de la requête (statement)
Statement statement = connexion.createStatement();

// Préparation de la requête
I c

EL H
String request = "SELECT * FROM Personne;";
O U
// Exécution de la requête M
ResultSet result = e fE L
c h r statement.executeQuery(request);

c
A
On utilise
executeQuery() pour les requêtes de lecture : select.
executeUpdate() pour les requêtes d’écriture : insert,
update, delete et create.
H & H: Research and Training 14 / 41
Utilisation

JDBC

Récupération des données


while (result.next()) {
I c

// on indique chaque fois le nom de la colonne
ELH
et le type
U
int num = result.getInt("num");
L MO
f E
String nom = result.getString("nom");
chre
String prenom = result.getString("prenom");
c A

System.out.println(num + " " + nom + " " +
prenom);
}

H & H: Research and Training 15 / 41


Utilisation

JDBC

On peut faire aussi


while (result.next()) {
// on peut indiquer aussi l’index de la colonne
I c

et le type
ELH
U
int idPersonne = result.getInt(1);
L MO
E
String nom = result.getString(2);
f
A c hre
String prenom = result.getString(3);

c
pour tous les autres attributs
// pareil
System.out.println(nom + " " + prenom);
}

H & H: Research and Training 16 / 41


Utilisation

JDBC

Pour faire une insertion


Statement statement = connexion.createStatement();
String request = "INSERT INTO Personne (nom,prenom)
VALUES (’Wick’,’John’);";
I c

int nbr = statement.executeUpdate(request);
ELH
if (nbr ! = 0)
U
System.out.println("insertion réussie");
L MO
f E
chre
c A

H & H: Research and Training 17 / 41


Utilisation

JDBC

Pour faire une insertion


Statement statement = connexion.createStatement();
String request = "INSERT INTO Personne (nom,prenom)
VALUES (’Wick’,’John’);";
I c

int nbr = statement.executeUpdate(request);
ELH
if (nbr ! = 0)
U
System.out.println("insertion réussie");
L MO
f E
A c hre
c
La méthode
executeUpdate() retourne

0 en cas d’échec de la requête d’insertion, et 1 en cas de succès

le nombre de lignes respectivement mises à jour ou supprimées

H & H: Research and Training 17 / 41


Utilisation

JDBC
Pour récupérer la valeur de la clé primaire auto-générée
Statement statement = connexion.createStatement();
String request = "INSERT INTO Personne (nom,prenom) VALUES (’
Wick’,’John’);";

I c

primaire
ELH
// on demande le renvoi des valeurs attribuées à la clé

U
MO
statement.executeUpdate(request,Statement.RETURN_GENERATED_KEYS
);
f E L
h re attribuées à l’ensemble de tuples
// on parcourt les valeurs
c
c A = statement.getGeneratedKeys();
ajoutés
ResultSet resultat

// on vérifie s’il contient au moins une valeur


if (resultat.next()) {
System.out.println("Le numéro généré pour cette personne :
" + resultat.getInt(1));
}

H & H: Research and Training 18 / 41


Utilisation

JDBC

Pour éviter les injections SQL, il faut utiliser les requêtes préparées
(pour la consultation, l’ajout, la suppression et la modification)
String request = "INSERT INTO Personne (nom,prenom)
VALUES (?,?);";
I c

PreparedStatement ps = connexion.prepareStatement(
ELH
U
request,PreparedStatement.RETURN_GENERATED_KEYS);
ps.setString(1, "Wick");
L MO
ps.setString(2, "John");
f E
ps.executeUpdate();
chre
c A
ResultSet resultat = ps.getGeneratedKeys();

if (resultat.next())
System.out.println("Le numéro généré pour cette
personne : " + resultat.getInt(1));

H & H: Research and Training 19 / 41


Utilisation

JDBC

Pour éviter les injections SQL, il faut utiliser les requêtes préparées
(pour la consultation, l’ajout, la suppression et la modification)
String request = "INSERT INTO Personne (nom,prenom)
VALUES (?,?);";
I c

PreparedStatement ps = connexion.prepareStatement(
ELH
request,PreparedStatement.RETURN_GENERATED_KEYS);
U
ps.setString(1, "Wick");
L MO
ps.setString(2, "John");
f E
ps.executeUpdate();
chre
c A
ResultSet resultat = ps.getGeneratedKeys();

if (resultat.next())
System.out.println("Le numéro généré pour cette
personne : " + resultat.getInt(1));

Attention à l’ordre des attributs

H & H: Research and Training 19 / 41


Transactions

JDBC

Les transactions
I c

ensemble de requête SQL
EL H
U
MOles requête SQL) soit rien
appliquant le principe soit tout (toutes
L
e
activées par défautravec
E
f MySQL
A h
c ées et gérées par le développeur
pouvant c être désactiv

H & H: Research and Training 20 / 41


Transactions

JDBC

Pour désactiver l’auto-commit


connection.setAutoCommit(false);

I c

ELH
U
Pour valider une transaction
L MO
f E
hre
connection.commit(false);
c
c A

Pour annuler une transaction
connection.rollback(false);

H & H: Research and Training 21 / 41


Transactions

JDBC
Exemple avec les transactions
// désactiver l’auto-commit
connexion.setAutoCommit(false);

String request = "INSERT INTO Personne (nom,prenom) VALUES


I c

(?,?);";
ELH
PreparedStatement ps = connexion.prepareStatement(request,
U
MO
PreparedStatement.RETURN_GENERATED_KEYS);
ps.setString(1, "Wick");
ps.setString(2, "John");
f E L
ps.executeUpdate();
chre
c A

// valider l’insertion
connexion.commit();

ResultSet resultat = ps.getGeneratedKeys();


if (resultat.next())
System.out.println("Le numéro généré pour cette personne :
" + resultat.getInt(1));

H & H: Research and Training 22 / 41


Restructuration du code Classes connexion et dao

JDBC

Organisation du code

Il faut mettre toutes les données (url, nomUtilisateur,


I c

ELH
motDePasse...) relatives à notre connexion dans une classe
connexion U
L MO
E
Pour chaque table de la base de données, on crée une classe
f
hre
java ayant comme attributs les colonnes de cette table
c
c A

Il faut mettre tout le code correspondant à l’accès aux données
(de la base de données) dans des nouvelles classes et interfaces
(qui constitueront la couche DAO : Data Access Object)

H & H: Research and Training 23 / 41


Restructuration du code Classes connexion et dao

La classe MyConnection

package org.eclipse.config;
public class MyConnection {
private static String url = "jdbc:mysql://localhost:3306/jdbc?useSSL=
false&serverTimezone=UTC";
private static String utilisateur = "root";
private static String motDePasse = "";
private static Connection connexion = null;
I c

private MyConnection() {
try {
ELH
U
MO
Class.forName("com.mysql.cj.jdbc.Driver");

motDePasse );
f E L
connexion = DriverManager.getConnection( url, utilisateur,

hre
} catch ( Exception e ) {
c
c A
e.printStackTrace();

}
}

public static Connection getConnection() {
if (connexion == null) {
new MyConnection();
}
return connexion;
}

H & H: Research and Training 24 / 41


Restructuration du code Classes connexion et dao

JDBC

La classe MyConnection (suite)


public static void stop() {
if (connexion != null) {
I c

try {
ELH
U
connexion.close();
L MO
} catch (SQLException e) {
f E
e.printStackTrace();
chre
c A
}
}
}
}

H & H: Research and Training 25 / 41


Restructuration du code Classes connexion et dao

JDBC

La classe Personne
package org.eclipse.model;

public class Personne{


I c

ELH
U
MO
private int num;
private String nom;
f E L
hre
private String prenom;
c
c A

// + getters + setters + constructeur sans param
ètre + constructeur avec 2 paramètres nom et
prénom + constructeur avec 3 paramètres

H & H: Research and Training 26 / 41


Restructuration du code Classes connexion et dao

JDBC

L’interface PersonneDao
package org.eclipse.dao;

import java.util.List;
I c

EL H
U
MO
import org.eclipse.model.Personne;

fE L
h r e
public interface PersonneDao {
c save(Personne personne);

void
A
Personne
c remove(Personne personne);
Personne update(Personne personne);
Personne findById(int id);
List<Personne> getAll();
}

H & H: Research and Training 27 / 41


Restructuration du code Classes connexion et dao

La classe PersonneDaoImpl définie dans org.eclipse.dao

public class PersonneDaoImpl implements PersonneDao {


@Override
public Personne save(Personne personne) {
Connection c = MyConnection.getConnection();
if (c != null) {
try {
PreparedStatement ps = c.prepareStatement("insert into
I c

RETURN_GENERATED_KEYS);
ELH
personne (nom,prenom) values (?,?); ", PreparedStatement.

ps.setString(1, personne.getNom());
U
ps.setString(2, personne.getPrenom());
L MO
ps.executeUpdate();
f E
hre
ResultSet resultat = ps.getGeneratedKeys();
if (resultat.next()) {
c
c A
personne.setNum(resultat.getInt(1));

}

return personne;

} catch (SQLException e) {
e.printStackTrace();
}
}
return null;
}

H & H: Research and Training 28 / 41


Restructuration du code Classes connexion et dao

Exemple de la méthode save en utilisant les transactions

public Personne save(Personne personne) {


Connection c = MyConnection.getConnection();
if (c != null) {
try {
c.setAutoCommit(false);
PreparedStatement ps = c.prepareStatement("insert into

c

personne (nom,prenom) values (?,?); ", PreparedStatement.
I
RETURN_GENERATED_KEYS);
ps.setString(1, personne.getNom());
ELH
ps.setString(2, personne.getPrenom());
U
ps.executeUpdate();
L MO
E
ResultSet resultat = ps.getGeneratedKeys();
f
hre
if (resultat.next()) {
c.commit();
c
c A
personne.setNum(resultat.getInt(1));

}

return personne;

} catch (SQLException e) {
e.printStackTrace();
}
}
return null;
}

H & H: Research and Training 29 / 41


Restructuration du code Classes connexion et dao

JDBC
La classe PersonneDaoImpl (suite)

@Override
public Personne findById(int id) {
Personne personne = null;
Connection c = MyConnection.getConnection();
if (c != null) {
I c

try {

ELH
PreparedStatement ps = c.prepareStatement("select * from
U
MO
personne where num = ?; ");
ps.setInt(1, id);

E L
ResultSet r =ps.executeQuery();
f
hre
if (r.next())

c
personne = new Personne(r.getInt("num"),r.getString("nom"),r.

c A
getString("prenom"));

} catch (SQLException e) {
e.printStackTrace();
}
}
return personne;
}
}

Il faut implémenter toutes les méthodes de l’interface PersonneDao


H & H: Research and Training 30 / 41
Restructuration du code Classes connexion et dao

Le Main pour tester toutes ces classes


package org.eclipse.classes;

import org.eclipse.dao.PersonneDaoImpl;
import org.eclipse.model.Personne;

public class Main {


I c
public static void main(String args []) { L
E H
O U
L M =("Wick","John");
PersonneDaoImpl personneDaoImpl
Personne personne = newE
new PersonneDaoImpl();

ref = personneDaoImpl.save(personne);
Personne

A c h
Personne insertedPersonne

c
if (insertedPersonne != null)
System.out.println("personne numéro " + insertedPersonne.
getNum() + " a été insérée");
else
System.out.println("problème d’insertion");
}
}

H & H: Research and Training 31 / 41


Restructuration du code Classes connexion et dao

JDBC

I c
Remarque EL H
U
Oautres méthodes de
M
N’oublions pas d’implémenter les quatre
L
l’interface Dao
h r e fE
A c
c

H & H: Research and Training 32 / 41


Restructuration du code Classes connexion et dao

JDBC

Utilisation de la généricité avec les DAO


I c
H
EL tables de la
Nous devons créer autant d’interfaces DAO que
U
bases de données
L MO
Pour éviter cela, on peut E une seule interface Dao avec un
ef utiliser
rtoutes
A h
type génériquecque les classes d’accès aux données
doivent cl’implémenter.

H & H: Research and Training 33 / 41


Restructuration du code Classes connexion et dao

JDBC

L’interface Dao
package org.eclipse.dao;

I c

import java.util.List;
ELH
public interface Dao <T> { MO
U
f E L
c h re obj);
T save(T obj);
void remove(T
A obj);
Tcupdate(T

T findById(int id);
List<T> getAll();
}

H & H: Research and Training 34 / 41


Restructuration du code Classes connexion et dao

JDBC

La classe PersonneDaoImpl
I c

package org.eclipse.dao;
EL H
U
MO Dao<Personne>{
public class PersonneDaoImpl implements
L
...
h r e fE
A c
c
pour le reste
Rien ne change

H & H: Research and Training 35 / 41


Restructuration du code DataSource et fichier de propriétés

JDBC

Encore de la restructuration du code


I c

H
Mettre les données (url, nomUtilisateur, motDePasse...) relatives à
EL
U
notre connexion dans un fichier de propriétés que nous appelons
MO
db.properties (utilisé par certain framework comme Spring)
L
f E
A c hre
Créer une nouvelle classe (DataSourceFactory) qui va lire et
construire les différentes propriétés de la connexion
c
Utiliser DataSourceFactory dans MyConnection

H & H: Research and Training 36 / 41


Restructuration du code DataSource et fichier de propriétés

JDBC

Le fichier db.properties situé à la racine du projet (ayant la


I c

forme clé = valeur, le nom de la clé est à choisir par
l’utilisateur) EL H
U
L MO
url=jdbc:mysql://localhost:3306/jdbc?useSSL=false&
serverTimezone=UTCf E
username=root chre
c A
password=root

H & H: Research and Training 37 / 41


Restructuration du code DataSource et fichier de propriétés

Créons la classe MyDataSourceFactory dans org.eclipse.config


import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import javax.sql.DataSource;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

public class MyDataSourceFactory {


public static DataSource getMySQLDataSource() {
I c

Properties props = new Properties();
ELH
FileInputStream fis = null;
U
MysqlDataSource mysqlDataSource = null;
try {
L MO
f E
hre
fis = new FileInputStream("db.properties");
props.load(fis);
c
c A
mysqlDataSource = new MysqlDataSource();

mysqlDataSource.setURL(props.getProperty("url"));
mysqlDataSource.setUser(props.getProperty("username"));
mysqlDataSource.setPassword(props.getProperty("password"));
} catch (IOException e) {
e.printStackTrace();
}
return mysqlDataSource;
}
}
H & H: Research and Training 38 / 41
Restructuration du code DataSource et fichier de propriétés

JDBC

I c
Remarque H
EpasL le driver
Dans MyDataSourceFactory, on ne pr O U
écise
com.mysql.jdbc.Driver car Lon M
f Elui même le driver.
utilise un objet de la classe

c h e
MysqlDataSource quircharge

c
A

H & H: Research and Training 39 / 41


Restructuration du code DataSource et fichier de propriétés

La classe MyConnection du package org.eclipse.config

import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;

public class MyConnection {

private static Connection connexion = null;


I c

private MyConnection() {
ELH
U
MO
DataSource dataSource = MyDataSourceFactory.getMySQLDataSource();
L
try {
f E
hre
connexion = dataSource.getConnection();

c
} catch (SQLException e) {

c A
e.printStackTrace();

}
}

public static Connection getConnection() {
if (connexion == null) {
new MyConnection();
}
return connexion;
}

H & H: Research and Training 40 / 41


Restructuration du code DataSource et fichier de propriétés

Relançons le Main et vérifier que tout fonctionne correctement


package org.eclipse.classes;

import org.eclipse.dao.PersonneDaoImpl;
import org.eclipse.model.Personne;

public class Main {


I c
public static void main(String args []) { L
E H
O U
L M =("Wick","John");
PersonneDaoImpl personneDaoImpl
Personne personne = newE
new PersonneDaoImpl();

ref = personneDaoImpl.save(personne);
Personne

A c h
Personne insertedPersonne

c
if (insertedPersonne != null)
System.out.println("personne numéro " + insertedPersonne.
getNum() + " a été insérée");
else
System.out.println("problème d’insertion");
}
}

H & H: Research and Training 41 / 41

Vous aimerez peut-être aussi