Seb-Info

Java (partie 5)

Java (partie 5)

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)

  1. Installer le driver JDBC dans le projet Eclipse.
  2. Créer la base school et la table student.
  3. É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.
  4. Bonus : écrire un mini “ORM maison” générique — une méthode utilitaire qui mappe un ResultSet en record 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.

Connexion pour les utilisateurs enregistrés
   
Nouvel utilisateur ?
*Champ requis
Powered by WP-Members