Aller au contenu

MySQL avec Express.js

Attention

Exemple de code à refaire

Installation

Pour nous permettre d'interragir avec une base de données MySQL nous allons installer un nouveau module avec npm.

npm install mysql

Création du pool de connexions

Ensuite nous allons créer le fichier ./src/config/db.js où nous allons déclarer un pool de connexion à notre BD. Notez aussi que j'utilise le module dotenv pour enregistrer les informations de connexion à la base de données

Note

On aurait aussi pu créer une connexion au lieu d'un pool, mais ce dernier est mieux adapté pour gérer de multiples utilisateurs. Pour plus de détail, cet article (anglais) résume bien la situation : Why is Connection Pooling better than Single Connection

.env
MYSQL_HOST="localhost"
MYSQL_USER="root"
MYSQL_PASSWORD="**********"
MYSQL_DATABASE="**********"
MYSQL_CONNECTION_LIMIT = 10
.src/config/db.js
const mysql = require("mysql");
const dotenv = require("dotenv");
dotenv.config();

const pool = mysql.createPool({
    connectionLimit: process.env.MYSQL_CONNECTION_LIMIT,
    host: process.env.MYSQL_HOST,
    user: process.env.MYSQL_USER,
    password: process.env.MYSQL_PASSWORD,
    database: process.env.MYSQL_DATABASE
});

module.exports = pool;

Utilisation

Maintenant pour lancer des requêtes à notre base de données MySQL il suffit d'importer le module db qu'on vient de créer et d'utiliser la fonction query()

script.js
// À ajuster selon votre structure
const sql = require("../config/db.js");

...

const requete = `SELECT nom, prenom FROM professeurs WHERE id = ?`;
const params = [id]

sql.query(requete, params, (erreur, resultat) => {
    // fonction à exécuter une fois la requête exécutée
    // erreur : Si une erreur SQL est survenur, objet contentant des informations sur celle-ci
    // resultat : Le résultat de la requète sous forme d'un tableau d'objets.
});

Attention l'objet resultat est toujours un tableau d'objets, même s'il n'y a qu'une ligne de résultat. Si on veut accéder à la valeur d'une colonne de la première ligne de résultat par exemple on peut faire resultat[0].nomColonneDansLaRequête. Dans l'exemple plus haut resultat[0].prenom me retournerait le prénom du professeur de la première ligne de résultat.

Dans l'objet erreur vous pouvez récupérer des informations sur l'erreur comme le code d'erreur SQL (erreur.sqlState) et un message explicatif (erreur.sqlMessage).

script.js
console.log(`Erreur SQL (${erreur.sqlState}) : ${erreur.sqlMessage}`);

On va aussi englober notre code dans une promesse (Promise). Pour plus de détail sur les promesses, voir la page sur l'asynchronisme.

Exemple

Voici un exemple complet d'une requête SELECT avec le modèle, la route et le controleur.

professeurs.model.js
// À ajuster selon la structure
const sql = require("../config/db.js");

class Professeur {
    constructor(professeur) => {
        this.prenom = professeur.prenom;
        this.nom = professeur.nom;
    };

    static trouverUnProfesseur = (id) => {
        return new Promise((resolve, reject) => {

            const requete = `SELECT nom, prenom FROM professeurs WHERE id = ?`;
            const params = [id]

            sql.query(requete, params, (erreur, resultat) => {
                if (erreur) {
                    // S'il y a une erreur, je la retourne avec reject()
                    reject(erreur);
                }
                // Sinon je retourne le résultat sans faire de validation, c'est possible que le résultat soit vide
                resolve(resultat);
            });
        });
    };
}

module.exports = Professeur;
professeurs.controller.js
// À ajuster selon la structure
const Professeur = require("../models/professeurs.model.js");

exports.trouverUnProfesseur = (req, res) => {
    // Teste si le paramètre id est présent et valide
    if(!req.params.id || parseInt(req.params.id) <= 0){
        res.status(400);
        res.send({
            message: "L'id du professeur est obligatoire et doit être supérieur à 0"
        });
        return;
    }

    // Appel à la fonction trouverUnProfesseur dans le modèle
    Professeur.trouverUnProfesseur(req.params.id)
    // Si c'est un succès
    .then((professeur) => {
        // S'il n'y a aucun résultat, on retourne un message d'erreur avec le code 404
        if (!professeur[0]) {
            res.status(404);
            res.send({
                message: `Professeur introuvable avec l'id ${req.params.id}`
            });
            return;
        }
        // Sinon on retourne le premier objet du tableau de résultat car on ne devrait avoir qu'un professeur par id
        res.send(professeur[0]);
    })
    // S'il y a eu une erreur au niveau de la requête, on retourne un erreur 500 car c'est du serveur que provient l'erreur.
    .catch((erreur) => {
        console.log('Erreur : ', erreur);
        res.status(500)
        res.send({
            message: "Erreur lors de la récupération du professeur avec l'id " + req.params.id
        });
    });
};
professeurs.route.js
const express = require('express');
const router = express.Router();
// À ajuster selon la structure
const professeursController = require('../controllers/professeurs.controller');

router.get('/:id', (req, res) => {
    // ici on ne fait que lancer la bonne fonction du controlleur. L'important est que l'objet res soit 
    // utilisé dans le controller (il y a un send() de fait) 
    professeursController.trouverUnProfesseur(req, res);
});

module.exports = router;

Références et autres exemples