[go: up one dir, main page]

0% ont trouvé ce document utile (0 vote)
22 vues75 pages

Cours Java JDBC

Ce document présente une introduction à JDBC (Java DataBase Connectivity) pour gérer une base de données en Java, en détaillant les étapes de mise en place, d'utilisation, et de gestion des transactions. Il aborde également des concepts tels que la connexion à la base de données, l'exécution de requêtes SQL, et l'utilisation de requêtes préparées pour éviter les injections SQL. Enfin, il mentionne l'utilisation de HikariCP pour le pooling de connexions.

Transféré par

Walid officiel
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
22 vues75 pages

Cours Java JDBC

Ce document présente une introduction à JDBC (Java DataBase Connectivity) pour gérer une base de données en Java, en détaillant les étapes de mise en place, d'utilisation, et de gestion des transactions. Il aborde également des concepts tels que la connexion à la base de données, l'exécution de requêtes SQL, et l'utilisation de requêtes préparées pour éviter les injections SQL. Enfin, il mentionne l'utilisation de HikariCP pour le pooling de connexions.

Transféré par

Walid officiel
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
Vous êtes sur la page 1/ 75

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 / 62


Plan

1 Introduction

2 Mise en place

3 Utilisation

4 Transactions

5 Restructuration du code
Classes connexion et DAO
DataSource et fichier de propriétés

6 Pool de connexions avec HikariCP

7 Cas d’une relation

H & H: Research and Training 2 / 62


Introduction

JDBC

Pour se connecter à une base de données avec Java


Il nous faut un JDBC (qui varie selon le SGBD utilisé)
JDBC : Java DataBase Connectivity
H I ©
deE
SGBD : Système de Gestion de BasesU
L
données

L MO
r e f E
A ch
©

H & H: Research and Training 3 / 62


Introduction

JDBC

Pour se connecter à une base de données avec Java


Il nous faut un JDBC (qui varie selon le SGBD utilisé)
JDBC : Java DataBase Connectivity
H I ©
deE
SGBD : Système de Gestion de BasesU
L
données

L MO
r e f E
A ch
JDBC ? ©
API (interface d’application) créée par Sun Microsystems
Permettant de communiquer avec les bases de données

H & H: Research and Training 3 / 62


Introduction

JDBC
JDBC

API de JSE

Permettant la connexion et l’exécution de requêtes SQL depuis un programme


Java
H I ©
Composé de
U EL
O
Driver
f E LM
ch
DriverManager
r e
© A
Connection
Statement
ResultSet
SQLException
...

H & H: Research and Training 4 / 62


Introduction

JDBC

JDBC : avantages JDBC : inconvénients

H I ©
EL
Multi-base de données Pas de driver universel

Support pour les requêtes et les


O U
Trop verbeux
procédures stockées

f E LM Code souvent redondant

asynchrone
ch r
Fonctionnant en synchrone et
e Complexe

©A
Pas besoin de convertir les données

H & H: Research and Training 5 / 62


Mise en place

JDBC

JDBC
H I ©
Aller à https: UEL
O
f E LM
//dev.mysql.com/downloads/connector/j/?os=26

r e
Télécharger et Décompresser l’archive .zip
ch
©A

H & H: Research and Training 6 / 62


Mise en place

JDBC

Intégrer le driver dans votre projet


H I ©
EL
Faire un clic droit sur le nom du projet et aller dans New >
Folder
M OU
E
Renommer le répertoiref libLpuis valider
r e
cdehl’archive
© A
Copier le .jar décompressée dans lib

H & H: Research and Training 7 / 62


Mise en place

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

H I ©
UEL
O
f E LM
ch r e
©A

H & H: Research and Training 8 / 62


Mise en place

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

Ou aussi
H I ©
U EL
Faire clic droit sur le projet dans Package Explorer et aller dans Properties
O
LM
Properties

f E
Dans Java Build Path, aller dans l’onglet Libraries
r e
ch
©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 8 / 62


Mise en place

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

Ou aussi
H I ©
U EL
Faire clic droit sur le projet dans Package Explorer et aller dans Properties
O
LM
Properties

f E
Dans Java Build Path, aller dans l’onglet Libraries
r e
ch
©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 8 / 62


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 cours_jdbc;

USE cours_jdbc;

H I ©
EL
CREATE TABLE personne (
num INT PRIMARY KEY AUTO_INCREMENT,
O U
LM
nom VARCHAR(30),
prenom VARCHAR(30)
)ENGINE=InnoDB;
r e f E
ch
SHOW TABLES;
©A
INSERT INTO personne (nom, prenom) VALUES
("Wick", "John"),
("Dalton", "Jack");

SELECT * FROM personne;

H & H: Research and Training 9 / 62


Utilisation

JDBC

Trois étapes
H I ©
Charger le driver JDBC (pour MySQL dans
U L cas)
Enotre
L
Établir la connexion avec la baseMdeOdonnées
r
Créer et exécuterhdese fE
c requêtes SQL
©A

H & H: Research and Training 10 / 62


Utilisation

JDBC

H I ©
Avant de commencer
UEL
O
f E LM
Tous les imports de ce chapitre sont de java.sql.*;

ch r e
©A

H & H: Research and Training 11 / 62


Utilisation

JDBC
Chargement du driver 5

try {
Class.forName("com.mysql.jdbc.Driver");
}
catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
H I ©
}
UEL
O
f E LM
Ou
ch r e
try { ©A
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
}
catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
}

H & H: Research and Training 12 / 62


Utilisation

JDBC
Chargement du driver 8

try {
Class.forName("com.mysql.cj.jdbc.Driver");
}
catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
H I ©
}
UEL
O
f E LM
Ou
ch r e
try {
©A
DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver()
);
}
catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
}

H & H: Research and Training 13 / 62


Utilisation

JDBC

Explication

Pour se connecter à la base de données, il faut spécifier une URL de la forme


jdbc:mysql://hote:port/nombd
H I ©
U EL
O
hote : adresse du serveur MySQL (dans notre cas localhost ou
127.0.0.1)

f E LM
r e
port : port TCP/IP utilisé par MySQL (par défaut est 3306)

chde la base de données MySQL


A
nombd : le nom
©
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 14 / 62


Utilisation

JDBC

Connexion à la base

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


String user = "root";
String password = "";
Connection connexion = null;
H I ©
EL
try {
connexion = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
O U
}
e.printStackTrace();

f E LM
finally {
if (connexion != null)
ch r e
try {
©A
connexion.close();
} catch (SQLException ignore) {
ignore.printStackTrace();
}
}

H & H: Research and Training 15 / 62


Utilisation

JDBC

Quelques paramètres à rajouter à la chaı̂ne de connexion pour résoudre les problèmes suivants

Problème d’incompatibilité avec l’heure de Paris : serverTimezone=UTC

Problème SSL : useSSL=false

H I
Problème avec la demande de clé : allowPublicKeyRetrieval=True©
U EL
Problème de base de données inexistante : createDatabaseIfNotExist=true
O
Problème avec les lettres accentuées :
f E LM
ch r e
characterEncoding=UTF-8&useUnicode=yes

©A

H & H: Research and Training 16 / 62


Utilisation

JDBC

Quelques paramètres à rajouter à la chaı̂ne de connexion pour résoudre les problèmes suivants

Problème d’incompatibilité avec l’heure de Paris : serverTimezone=UTC

Problème SSL : useSSL=false

H I
Problème avec la demande de clé : allowPublicKeyRetrieval=True©
U EL
Problème de base de données inexistante : createDatabaseIfNotExist=true
O
Problème avec les lettres accentuées :
f E LM
ch r e
characterEncoding=UTF-8&useUnicode=yes

©A
Exemple

String url =
"jdbc:mysql://localhost:3306/cours_jdbc?serverTimezone=UTC&useSSL=false
&allowPublicKeyRetrieval=True";

H & H: Research and Training 16 / 62


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
String selectRequest = "SELECT * FROM Personne;";
H I ©
// Exécution de la requête
UEL
O
ResultSet result = statement.executeQuery(selectRequest);

f E LM
ch r e
©A

H & H: Research and Training 17 / 62


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
String selectRequest = "SELECT * FROM Personne;";
H I ©
// Exécution de la requête
U EL
O
ResultSet result = statement.executeQuery(selectRequest);

f E LM
ch r e
On utilise
©A
execute() pour les requêtes de création : CREATE.

executeQuery() pour les requêtes de lecture : SELECT.

executeUpdate() pour les requêtes d’écriture : INSERT, UPDATE et DELETE.

H & H: Research and Training 17 / 62


Utilisation

JDBC

Pour récupérer les données, on peut indiquer le nom de la colonne

H I ©
EL
while (result.next()) {
int num = result.getInt("num");
O U
LM
String nom = result.getString("nom");

r e E
String prenom = result.getString("prenom");
f
System.out.println(num + " " + nom + " " + prenom);
ch
©A
}

H & H: Research and Training 18 / 62


Utilisation

JDBC

Ou aussi son indice dans la table

H I ©
EL
while (result.next()) {
int num = result.getInt(1);
O U
LM
String nom = result.getString(2);

r e E
String prenom = result.getString(3);
f
System.out.println(num + " " + nom + " " + prenom);
ch
©A
}

H & H: Research and Training 19 / 62


Utilisation

JDBC

Pour faire une insertion

Statement statement = connexion.createStatement();


String insertRequest = "INSERT INTO Personne (nom,prenom) VALUES ('Wick','John');";

©
int nbr = statement.executeUpdate(insertRequest);
if (nbr != 0) {

H I
EL
System.out.println("insertion réussie");
}

O U
f E LM
ch r e
©A

H & H: Research and Training 20 / 62


Utilisation

JDBC

Pour faire une insertion

Statement statement = connexion.createStatement();


String insertRequest = "INSERT INTO Personne (nom,prenom) VALUES ('Wick','John');";

©
int nbr = statement.executeUpdate(insertRequest);
if (nbr != 0) {

H I
EL
System.out.println("insertion réussie");
}

O U
f E LM
ch r
La méthode executeUpdate() retourne
e
©A
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 20 / 62


Utilisation

JDBC

Pour récupérer la valeur de la clé primaire auto-générée

Statement statement = connexion.createStatement();

I ©
String insertRequest = "INSERT INTO Personne (nom, prenom) VALUES ('Wick','John');";
H
UEL
// on demande le renvoi des valeurs attribuées à la clé primaire
statement.executeUpdate(insertRequest, Statement.RETURN_GENERATED_KEYS);
O
E
ResultSet resultat = statement.getGeneratedKeys();
f LM
// on parcourt les valeurs attribuées à l'ensemble de tuples ajoutés

ch r e
// on vérifie s'il contient au moins une valeur

©A
if (resultat.next()) {
System.out.println("Identifiant généré pour la personne : " + resultat.getInt(1));
}

H & H: Research and Training 21 / 62


Utilisation

JDBC

Pour éviter les injections SQL, il faut utiliser les requêtes préparées

String request = "INSERT INTO Personne (nom, prenom) VALUES (?, ?);";
PreparedStatement ps = connexion.prepareStatement(request, PreparedStatement.
RETURN_GENERATED_KEYS);
ps.setString(1, "Wick");
H I ©
EL
ps.setString(2, "John");
ps.executeUpdate();
ResultSet resultat = ps.getGeneratedKeys();
O U
LM
if (resultat.next()) {
System.out.println("Identifiant généré pour la personne : " + resultat.getInt(1));
}

r e f E
ch
©A

H & H: Research and Training 22 / 62


Utilisation

JDBC

Pour éviter les injections SQL, il faut utiliser les requêtes préparées

String request = "INSERT INTO Personne (nom, prenom) VALUES (?, ?);";
PreparedStatement ps = connexion.prepareStatement(request, PreparedStatement.
RETURN_GENERATED_KEYS);
ps.setString(1, "Wick");
H I ©
EL
ps.setString(2, "John");
ps.executeUpdate();
ResultSet resultat = ps.getGeneratedKeys();
O U
LM
if (resultat.next()) {
System.out.println("Identifiant généré pour la personne : " + resultat.getInt(1));
}

r e f E
ch
©A
Attention à l’ordre des attributs

H & H: Research and Training 22 / 62


Transactions

JDBC

Transactions

H I ©
EL
Ensemble de requête SQL

O U
LM
Appliquant le principe soit tout (toutes les requête SQL) soit rien

e f
Activées par défaut avec MySQL
r E
ch
©A
Pouvant être désactivées et gérées par le développeur

H & H: Research and Training 23 / 62


Transactions

JDBC

Pour désactiver l’auto-commit


connection.setAutoCommit(false);

H I ©
UEL
O
f E LM
ch r e
©A

H & H: Research and Training 24 / 62


Transactions

JDBC

Pour désactiver l’auto-commit


connection.setAutoCommit(false);

H I ©
UEL
Pour valider une transaction
O
connection.commit();
f E LM
ch r e
©A

H & H: Research and Training 24 / 62


Transactions

JDBC

Pour désactiver l’auto-commit


connection.setAutoCommit(false);

H I ©
UEL
Pour valider une transaction
O
connection.commit();
f E LM
ch r e
© A
Pour annuler une transaction
connection.rollback();

H & H: Research and Training 24 / 62


Transactions

JDBC

Exemple avec les transactions

// désactiver l'auto-commit
connexion.setAutoCommit(false);

H I ©
String request = "INSERT INTO Personne (nom,prenom) VALUES (?,?);";

EL
PreparedStatement ps = connexion.prepareStatement(request, PreparedStatement.
RETURN_GENERATED_KEYS);
ps.setString(1, "Wick");
O U
LM
ps.setString(2, "John");
ps.executeUpdate();

// valider l'insertion
r e f E
connexion.commit();
ch
©A
ResultSet resultat = ps.getGeneratedKeys();
if (resultat.next()) {
System.out.println("Identifiant généré pour la personne : " + resultat.getInt(1));
}

H & H: Research and Training 25 / 62


Restructuration du code Classes connexion et DAO

JDBC

Organisation du code

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


motDePasse...) relatives à notre connexion dans une classe
H I ©
connexion
U EL
M O
Pour chaque table de la base
f E Ldecolonnes
données, on crée une classe

h r e
java ayant comme attributs les de cette table
c le code correspondant à l’accès aux données
© Atout
Il faut mettre
(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 26 / 62


Restructuration du code Classes connexion et DAO

JDBC
La classe MySqlConnection

package org.eclipse.config;

import java.sql.Connection;
import java.sql.DriverManager;

public class MySqlConnection {

private static Connection connexion = null;

H I ©
static {

U EL
O
try {

LM
String url = "jdbc:mysql://localhost:3306/cours_jdbc";
String utilisateur = "root";
String motDePasse = "";

r e f E
ch
Class.forName("com.mysql.cj.jdbc.Driver");

©A
connexion = DriverManager.getConnection(url, utilisateur, motDePasse);
} catch (Exception e) {
e.printStackTrace();
}
}

private MySqlConnection() { }

public static Connection getConnection() {


return connexion;
}
}

H & H: Research and Training 27 / 62


Restructuration du code Classes connexion et DAO

JDBC
La classe Personne
package org.eclipse.model;

public class Personne {


H I ©
private int num; U EL
O
private String nom;
private String prenom; f E LM
ch r e
©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 28 / 62


Restructuration du code Classes connexion et DAO

JDBC
L’interface PersonneDao
package org.eclipse.dao;

import java.util.List;
H I ©
U
import org.eclipse.model.Personne;EL
M O
L
f E { personne);
public interface PersonneDao
r e
Personnehsave(Personne
© Ac remove(Personne personne);
boolean
Personne update(Personne personne);
Personne findById(int id);
List<Personne> getAll();
}

H & H: Research and Training 29 / 62


Restructuration du code Classes connexion et DAO

JDBC

I ©
Déclarons une classe PersonneDaoImpl dans org.eclipse.dao
H
U ELPersonneDao {
public class PersonneDaoImpl implements

L MO
}
r e f E
A ch
©

H & H: Research and Training 30 / 62


Restructuration du code Classes connexion et DAO

JDBC
Implémentons la méthode save

@Override
public Personne save(Personne personne) {
Connection c = MySqlConnection.getConnection();
try {
PreparedStatement ps = c.prepareStatement("INSERT INTO personne (nom,
prenom) VALUES (?,?); ", PreparedStatement.RETURN_GENERATED_KEYS);
ps.setString(1, personne.getNom());
ps.setString(2, personne.getPrenom());
H I ©
EL
ps.executeUpdate();
ResultSet resultat = ps.getGeneratedKeys();
if (resultat.next()) {
O U
LM
personne.setNum(resultat.getInt(1));
return personne;
}

r
} catch (SQLException e) {
e f E
ch
e.printStackTrace();

©A
}
finally {
try {
c.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}

H & H: Research and Training 31 / 62


Restructuration du code Classes connexion et DAO

Exemple de la méthode save en utilisant les transactions

@Override
public Personne save(Personne personne) {
Connection c = MySqlConnection.getConnection();
try {
c.setAutoCommit(false);
PreparedStatement ps = c.prepareStatement("INSERT INTO personne (nom,
prenom) VALUES (?,?); ", PreparedStatement.RETURN_GENERATED_KEYS);
ps.setString(1, personne.getNom());
ps.setString(2, personne.getPrenom());
ps.executeUpdate();
H I ©
EL
ResultSet resultat = ps.getGeneratedKeys();
if (resultat.next()) {
c.commit();
O U
LM
personne.setNum(resultat.getInt(1));
return personne;
}
} catch (SQLException e) {
r e f E
ch
e.printStackTrace();

©A
}
finally {
try {
c.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}

H & H: Research and Training 32 / 62


Restructuration du code Classes connexion et DAO

JDBC
La méthode findById

@Override
public Personne findById(int id) {
Personne personne = null;
Connection c = MySqlConnection.getConnection();
if (c != null) {
try {
String request = "SELECT * FROM personne WHERE num = ?;";
H I ©
EL
PreparedStatement ps = c.prepareStatement(request);

U
ps.setInt(1, id);
ResultSet r = ps.executeQuery();
O
LM
if (r.next())
personne = new Personne(r.getInt("num"), r.getString("nom"), r.

r
} catch (SQLException e) {
e f E
getString("prenom"));

ch
e.printStackTrace();

©A
} finally {
try {
c.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return personne;
}

H & H: Research and Training 33 / 62


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 {

H I ©
EL
public static void main(String args []) {

O
PersonneDaoImpl personneDaoImpl = new PersonneDaoImpl(); U
f E LM
Personne personne = new Personne ("Wick", "John");
Personne insertedPersonne = personneDaoImpl.save(personne);

ch r e
©A
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 34 / 62


Restructuration du code Classes connexion et DAO

JDBC

H I ©
EL
Remarque

O U
LM
N’oublions pas d’implémenter les trois autres méthodes de l’interface
PersonneDao.
r e f E
ch
©A

H & H: Research and Training 35 / 62


Restructuration du code Classes connexion et DAO

JDBC

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

H I ©
Nous devons créer autant d’interfaces DAO que tables de la
EL
bases de données
M OU
f E L une seule interface GenericDao
Pour éviter cela, on peut utiliser
avec un type génh e
r que toutes les classes d’accès aux
c érique
© A
données doivent l’implémenter.

H & H: Research and Training 36 / 62


Restructuration du code Classes connexion et DAO

JDBC
L’interface générique GenericDao

package org.eclipse.dao;

import java.util.List;

public interface GenericDao<Entity, PK> {


H I ©
U EL
List<Entity> findAll();
O
f
Entity findById(PK id);E LM
r e
ch entity);
A
Entity save(Entity
©
Entity update(Entity entity);

boolean remove(PK id);

H & H: Research and Training 37 / 62


Restructuration du code Classes connexion et DAO

JDBC

La classe PersonneDaoImpl

package org.eclipse.dao;

public class PersonneDaoImpl implements GenericDao<Personne, Integer> {


H I ©
...
U EL
O
LM
}

r e f E
ch
©A

H & H: Research and Training 38 / 62


Restructuration du code Classes connexion et DAO

JDBC

La classe PersonneDaoImpl

package org.eclipse.dao;

public class PersonneDaoImpl implements GenericDao<Personne, Integer> {


H I ©
...
U EL
O
LM
}

r e f E
ch
©A
Le reste du code est le même.

H & H: Research and Training 38 / 62


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

JDBC

Encore de la restructuration du code


Mettre les données (url, nomUtilisateur, motDePasse...) relatives à
H I ©
notre connexion dans un fichier de propriétés que nous appelons
U EL
O
db.properties (utilisé par certain framework comme Spring)

f E LM
ch r e
Créer une nouvelle classe (DataSourceFactory) qui va lire et
construire les différentes propriétés de la connexion
©A
Utiliser DataSourceFactory dans MySqlConnection

H & H: Research and Training 39 / 62


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

JDBC

I ©
Le fichier db.properties situé à la racine du projet (ayant la forme clé = valeur, le
H
EL
nom de la clé est à choisir par l’utilisateur)

O
url=jdbc:mysql://localhost:3306/cours_jdbc?serverTimezone=UTC U
username=root
password=root
f E LM
ch r e
©A

H & H: Research and Training 40 / 62


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

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

package org.eclipse.config;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

import javax.sql.DataSource;

import com.mysql.cj.jdbc.MysqlDataSource;
H I ©
public class MyDataSourceFactory {
U EL
O
LM
public static DataSource getMySQLDataSource() {

E
Properties props = new Properties();
FileInputStream fis = null;

r e f
MysqlDataSource mysqlDataSource = null;
try {
ch
©A
fis = new FileInputStream("db.properties");
props.load(fis);
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 41 / 62


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

JDBC

Remarque
H I ©
U EL
Dans MyDataSourceFactory, on ne précise pas le driver
O
f E LM
com.mysql.jdbc.Driver car on utilise un objet de la classe

ch r e
MysqlDataSource qui charge lui même le driver.

©A

H & H: Research and Training 42 / 62


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

La classe MySqlConnection du package org.eclipse.config

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

public class MySqlConnection {

private static Connection connexion = null;

H I ©
EL
private MySqlConnection() {

O U
LM
DataSource dataSource = MyDataSourceFactory.getMySQLDataSource();
try {

e f E
connexion = dataSource.getConnection();
r
ch
} catch (SQLException e) {

©A
e.printStackTrace();
}
}
public static Connection getConnection() {
if (connexion == null) {
new MySqlConnection();
}
return connexion;
}

H & H: Research and Training 43 / 62


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

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


package org.eclipse.test;

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

public class Main {

H I ©
public static void main(String args []) {
U EL
O
f E LM
PersonneDaoImpl personneDaoImpl = new PersonneDaoImpl();
Personne personne = new Personne ("Wick", "John");

ch r e
Personne insertedPersonne = personneDaoImpl.save(personne);

©A
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 44 / 62


Pool de connexions avec HikariCP

JDBC

H I ©
EL
Rappel

O U
LM
Notre approche est idéale pour une application de petite taille ou
mono-utilisateur.
r e f E
ch
©A

H & H: Research and Training 45 / 62


Pool de connexions avec HikariCP

JDBC

Problématique

Chaque méthode d’une classe DAO ouvre la connexion, exécute


une requête puis ferme la connexion.
H I ©
La connexion à une base de données
UEL
O
application Web),
f E LM
a un coût non négligeable (l’opération la plus coûteuse dans une

r e
h ée par des threads.
ne peut êtrecpartag
© A

H & H: Research and Training 46 / 62


Pool de connexions avec HikariCP

JDBC

Problématique

Chaque méthode d’une classe DAO ouvre la connexion, exécute


une requête puis ferme la connexion.
H I ©
La connexion à une base de données
UEL
O
application Web),
f E LM
a un coût non négligeable (l’opération la plus coûteuse dans une

r e
h ée par des threads.
ne peut êtrecpartag
© A

Quelle solution alors ?

H & H: Research and Training 46 / 62


Pool de connexions avec HikariCP

JDBC

Solution : utiliser un pool de connexions déjà ouvertes (connection pooling)

Le nombre de connexions ouvertes est paramétrable : au démarrage de


I ©
l’application, un nombre de connexions sera créé en fonction d’un nombre
H
donné.
UEL
O
LM
Les connexions resteront toujours ouvertes.

e f E
Le pool de connexions se charge de retourner un objet Connection aux
r
ch
méthodes de l’application qui la demandent.

©A
Le client qui appelle la méthode connection.close perd la connexion sans la
fermer réellement. La connexion sera libérée et pourra être redistribuée de
nouveau.

H & H: Research and Training 47 / 62


Pool de connexions avec HikariCP

JDBC
Techniquement, comment faire ?

Utiliser DataSource à la place de DriverManager.

Utiliser une implémentation Java pour le Connection pool.

H I ©
UEL
O
f E LM
ch r e
©A

H & H: Research and Training 48 / 62


Pool de connexions avec HikariCP

JDBC
Techniquement, comment faire ?

Utiliser DataSource à la place de DriverManager.

Utiliser une implémentation Java pour le Connection pool.

H I ©
UEL
O
LM
Exemples d’implémentation de Connection pool pour Java

HikariCP
r e f E
ch
©A
BoneCP

DBPool

Apache DBCP

c3p0

...

H & H: Research and Training 48 / 62


Pool de connexions avec HikariCP

JDBC

HikariCP, pourquoi ?
Plus performant
Plus utilisé
H I ©
Écrit en Java UEL
O
...
f E LM
ch r e
©A

H & H: Research and Training 49 / 62


Pool de connexions avec HikariCP

JDBC

HikariCP, pourquoi ?
Plus performant
Plus utilisé
H I ©
Écrit en Java UEL
O
...
f E LM
ch r e
©A
Dépôt GitHub
https://github.com/brettwooldridge/HikariCP

H & H: Research and Training 49 / 62


Pool de connexions avec HikariCP

JDBC

Intégrer HikariCP dans le projet

Aller à https://jar-download.com/artifacts/com.
H I ©
zaxxer/HikariCP/5.0.1
UEL
O
Télécharger et Décompresser l’archive
f E LM
r e
Déplacer les deux fichiers .jar (HikariCP et slf4j) dans le
ch
A
dossier lib du projet
©
Ajouter les deux fichiers au build path du projet

H & H: Research and Training 50 / 62


Pool de connexions avec HikariCP

JDBC

Remplaçons la clé url de db.properties

url=jdbc:mysql://localhost:3306/cours_jdbc?serverTimezone=UTC
username=root
H I ©
EL
password=root

O U
f E LM
Par jdbcUrl

ch r e
©A
jdbcUrl=jdbc:mysql://localhost:3306/cours_jdbc?serverTimezone=UTC
username=root
password=root

H & H: Research and Training 51 / 62


Pool de connexions avec HikariCP

JDBC

Créons une classe DataSource avec un constructeur privé


package org.eclipse.config;

H I ©
public class DataSource {
UEL
L M{O
r e f E
private DataSource()

} A ch
©
}

H & H: Research and Training 52 / 62


Pool de connexions avec HikariCP

JDBC

Déclarons les deux attributs suivants

package org.eclipse.config;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
H I ©
UEL
public class DataSource {
O
private static HikariDataSource ds;
f E LM
r e
private static HikariConfig conf = new HikariConfig("db.properties");

ch
©A
private DataSource() {

H & H: Research and Training 53 / 62


Pool de connexions avec HikariCP

JDBC
Définissons une méthode getConnection() qui retournera un objet Connection

package org.eclipse.config;

import java.sql.Connection;
import java.sql.SQLException;

import com.zaxxer.hikari.HikariConfig;
H I ©
import com.zaxxer.hikari.HikariDataSource;
UEL
O
LM
public class DataSource {

r e
private static HikariDataSource ds;f E
ch
private static HikariConfig conf = new HikariConfig("db.properties");

©A
private DataSource() { }

public static Connection getConnection() throws SQLException {


ds = new HikariDataSource(conf);
return ds.getConnection();
}
}

H & H: Research and Training 54 / 62


Pool de connexions avec HikariCP

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


package org.eclipse.test;

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

public class Main {

H I ©
public static void main(String args []) {
UEL
O
f E LM
PersonneDaoImpl personneDaoImpl = new PersonneDaoImpl();
Personne personne = new Personne ("Wick", "John");

ch r e
Personne insertedPersonne = personneDaoImpl.save(personne);

©A
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 55 / 62


Pool de connexions avec HikariCP

JDBC

valeur souhaitée
H I ©
Pour fixer le nombre de connexion de la pool, on ajoute la clé maximumPoolSize avec la

UEL
O
jdbcUrl=jdbc:mysql://localhost:3306/cours_jdbc?serverTimezone=UTC

LM
username=root
password=root
maximumPoolSize=10
r e f E
ch
©A

H & H: Research and Training 56 / 62


Cas d’une relation

JDBC
Considérons la classe Adresse suivante

package com.example.demo.model;

public class Adresse {


private Integer id;
private String rue;
private String codePostal;
H I ©
private String ville;
UEL
O
LM
public Adresse() {
}

r e f E
ch
public Adresse(Integer id, String rue, String codePostal, String
ville) {
this.id = id;
this.rue = rue;
©A
this.codePostal = codePostal;
this.ville = ville;
}

// + getters / setters / toString

H & H: Research and Training 57 / 62


Cas d’une relation

JDBC

Dans Personne, définissons un nouvel attribut adresses


public class Personne {

private Integer num;


H I ©
private String nom;
UEL
O
LM
private String prenom;

r e f E
ch
private List<Adresse> adresses;
©A
// + getter / setter / toString

H & H: Research and Training 58 / 62


Cas d’une relation
Exécutons le script suivant pour mettre à jour la base de données avec les nouvelles tables

DROP DATABASE cours_jdbc;


CREATE DATABASE cours_jdbc;
USE cours_jdbc;

CREATE TABLE personne(


num INT PRIMARY KEY AUTO_INCREMENT,
nom VARCHAR(30),
prenom VARCHAR(30)
)ENGINE=InnoDB;

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

H I ©
CREATE TABLE adresse(
id INT PRIMARY KEY AUTO_INCREMENT,
U EL
rue VARCHAR(30),
O
LM
code_postal VARCHAR(30),
ville VARCHAR(30)
)ENGINE=InnoDB;

r e f E
ch
INSERT INTO adresse (rue, code_postal, ville) VALUES

©A
("paradis", "13006", "Marseille"),
("plantes", "75014", "Paris");

CREATE TABLE personne_adresse(


id INT PRIMARY KEY AUTO_INCREMENT,
num_personne INT,
id_adresse INT,
FOREIGN KEY (num_personne) REFERENCES personne (num),
FOREIGN KEY (id_adresse) REFERENCES adresse (id)
)ENGINE=InnoDB;

INSERT INTO personne_adresse (num_personne, id_adresse) VALUES (1, 1), (1, 2), (2, 2);

H & H: Research and Training 59 / 62


Cas d’une relation

JDBC

Exercice 1
H I ©
Créez une classe AdresseDao qui implémente Dao
UEL
O
Implémentez les méthodes de Dao
f E LM
r e
Dans main, testez toutes les méthodes implémentées dans
ch
©A
AdresseDao.

H & H: Research and Training 60 / 62


Cas d’une relation

JDBC

Dans AdresseDao, implémenter les méthodes suivantes


H I ©
EL
public List<Adresse> findAdressesByPersonneId(int id) {
}
M OU
f E L idPers, int idAdr) {
public Adresse findAdresseById(int
}
chr e
© A

H & H: Research and Training 61 / 62


Cas d’une relation

JDBC

Implémenter les méthodes suivantes dans une classe DAO


H I ©
EL
public int mapPersonneAdresse(Integer idPers, Integer idAdr) {
U
}
O
E LM
public int unmapPersonneAdresse(Integer idPers, Integer idAdr) {
f
}

ch r e
©A

H & H: Research and Training 62 / 62

Vous aimerez peut-être aussi