Java & MySQL (JDBC) + “ORM maison”
Objectif
Se connecter à MySQL (WAMP), exécuter des requêtes sécurisées (PreparedStatement), gérer transactions et mapper les lignes en objets via un DAO.
Pré-requis poste
- Driver JDBC : mysql-connector-j 8.x (fichier .jar) — Ajouter au projet Eclipse (Right click → Build Path → Add External Archives…).
- MySQL sous WAMP actif, user
root
(ou dédié), mot de passe configuré.
Schéma d’exemple
CREATE DATABASE IF NOT EXISTS school CHARACTER SET utf8mb4;
USE school;
CREATE TABLE IF NOT EXISTS student (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(80) NOT NULL,
year INT NOT NULL,
average DOUBLE NOT NULL
);
INSERT INTO student(name, year, average) VALUES
('Alice',2,14.5), ('Bob',2,13.0), ('Chloé',1,16.2);
Code : utilitaire de connexion
// src/db/Db.java
package db;
import java.sql.*;
public final class Db {
private Db() {}
private static final String URL = "jdbc:mysql://localhost:3306/school?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";
private static final String USER = "root"; // adapter si besoin
private static final String PASS = ""; // adapter si besoin
public static Connection get() throws SQLException {
return DriverManager.getConnection(URL, USER, PASS);
}
}
Entité & DAO
// src/model/StudentEntity.java
package model;
public record StudentEntity(int id, String name, int year, double average) {}
// src/dao/StudentDao.java
package dao;
import model.StudentEntity;
import db.Db;
import java.sql.*;
import java.util.*;
public class StudentDao {
public List<StudentEntity> findAll() throws SQLException {
String sql = "SELECT id,name,year,average FROM student";
try (Connection c = Db.get();
PreparedStatement ps = c.prepareStatement(sql);
ResultSet rs = ps.executeQuery()) {
List<StudentEntity> out = new ArrayList<>();
while (rs.next()) {
out.add(map(rs));
}
return out;
}
}
public Optional<StudentEntity> findById(int id) throws SQLException {
String sql = "SELECT id,name,year,average FROM student WHERE id=?";
try (Connection c = Db.get();
PreparedStatement ps = c.prepareStatement(sql)) {
ps.setInt(1, id);
try (ResultSet rs = ps.executeQuery()) {
return rs.next() ? Optional.of(map(rs)) : Optional.empty();
}
}
}
public int insert(String name, int year, double average) throws SQLException {
String sql = "INSERT INTO student(name,year,average) VALUES (?,?,?)";
try (Connection c = Db.get();
PreparedStatement ps = c.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
ps.setString(1, name);
ps.setInt(2, year);
ps.setDouble(3, average);
ps.executeUpdate();
try (ResultSet keys = ps.getGeneratedKeys()) {
return keys.next() ? keys.getInt(1) : -1;
}
}
}
public boolean update(int id, String name, int year, double average) throws SQLException {
String sql = "UPDATE student SET name=?, year=?, average=? WHERE id=?";
try (Connection c = Db.get();
PreparedStatement ps = c.prepareStatement(sql)) {
ps.setString(1, name);
ps.setInt(2, year);
ps.setDouble(3, average);
ps.setInt(4, id);
return ps.executeUpdate() == 1;
}
}
public boolean delete(int id) throws SQLException {
String sql = "DELETE FROM student WHERE id=?";
try (Connection c = Db.get();
PreparedStatement ps = c.prepareStatement(sql)) {
ps.setInt(1, id);
return ps.executeUpdate() == 1;
}
}
private static StudentEntity map(ResultSet rs) throws SQLException {
return new StudentEntity(
rs.getInt("id"),
rs.getString("name"),
rs.getInt("year"),
rs.getDouble("average")
);
}
}
Transactions (exemple)
// Exemple d'opération atomique sur 2 updates
try (var c = db.Db.get()) {
try {
c.setAutoCommit(false);
// ... plusieurs updates/inserts ...
c.commit();
} catch (Exception ex) {
c.rollback();
throw ex;
} finally {
c.setAutoCommit(true);
}
}
TP (à rendre)
- Installer le driver JDBC dans le projet Eclipse.
- Créer la base
school
et la tablestudent
. - Écrire un programme
MainJdbc
qui :- a) insère un nouvel étudiant,
- b) liste tous les étudiants,
- c) met à jour une moyenne,
- d) supprime un étudiant,
- e) encapsule b)+c)+d) dans une transaction.
- Bonus : écrire un mini “ORM maison” générique — une méthode utilitaire qui mappe un
ResultSet
enrecord
via un RowMapper<T> fonctionnel.
Corrigé (pistes)
@FunctionalInterface interface RowMapper<T> { T map(java.sql.ResultSet rs) throws java.sql.SQLException; }
Vigilances
- Utiliser PreparedStatement (paramètres
?
) pour éviter l’injection SQL. - Fermer les ressources via
try-with-resources
. - Configurer l’URL JDBC selon votre mot de passe MySQL.
Ce contenu est réservé aux membres du site. Si vous êtes un utilisateur existant, veuillez vous connecter. Les nouveaux utilisateurs peuvent s'inscrire ci-dessous.