Archives Wild Code School
Spring

Spring & JDBC 3 : Update

Quête 8 sur 16

Objectifs

  • Créer une route qui met à jour les données

Template

Afin de mettre à jour un sorcier, il va te falloir un formulaire qui récupère les données déjà connues et qui envoie les modifications en POST :

html
<form action="/wizard/update" method="post">
    <input th:value="${wizard.id}" name="id" type="hidden">
    <label for="wizard-first-name">First name:</label>
    <input th:value="${wizard.firstName}" id="wizard-first-name" name="firstName" placeholder="Harry" required type="text">
    <br><br>
    <label for="wizard-last-name">Last name:</label>
    <input th:value="${wizard.lastName}" id="wizard-last-name" name="lastName" placeholder="Potter" required type="text">
    <br><br>
    <label for="wizard-birthday">Birthday:</label>
    <input th:value="${wizard.birthday}" id="wizard-birthday" name="birthday" placeholder="1980-07-31" required type="date">
    <br><br>
    <label for="wizard-birth-place">Birth Place:</label>
    <input th:value="${wizard.birthPlace}" id="wizard-birth-place" name="birthPlace" placeholder="London" required type="text">
    <br><br>
    <label for="wizard-biography">Biography:</label>
    <textarea th:text="${wizard.biography}" id="wizard-biography" name="biography"></textarea>
    <br><br>
    <label for="wizard-is-muggle">Is Muggle ?</label>
    <input th:checked="${wizard.muggle}" id="wizard-is-muggle" name="muggle" type="checkbox" value="true">
    <br><br>
    <input type="submit" value="Send">
</form>

Tu peux remarquer ici l'utilisation d'un champ caché :

html
<input th:value="${wizard.id}" name="id" type="hidden">

Le but est d'envoyer l'identifiant du sorcier à modifier, car il servira dans la future requête.

Controller

Il va falloir créer deux routes : une première en GET, qui affiche le contenu du sorcier à éditer :

java
@GetMapping("/wizard/update")
public String getWizardUpdate(Model model,
                              @RequestParam Long id) {

    model.addAttribute("wizard", repository.findById(id));

    return "wizard_update";
}

La seconde route correspond à l'envoie en POST du formulaire précédent :

java
@PostMapping("/wizard/update")
public String postWizardUpdate(Model model,
                         @RequestParam Long id,
                         @RequestParam String firstName,
                         @RequestParam String lastName,
                         @RequestParam Date birthday,
                         @RequestParam String birthPlace,
                         @RequestParam(required = false, defaultValue = "") String biography,
                         @RequestParam(required = false, defaultValue = "false") boolean muggle
) {
    model.addAttribute("wizard", repository.update(id, firstName, lastName,
            birthday, birthPlace, biography, muggle));

    return "wizard_get";
}

Tu remarqueras que deux routes peuvent avoir le même chemin, ici /wizard/update, du moment que les méthodes HTTP sont différentes (ici GET et POST).

Repository

Tu as dû remarquer l'appel de la méthode update du repository :

java
public Wizard update(Long id, String firstName, String lastName, Date birthday,
                   String birthPlace, String biography, boolean muggle) {

    try {
        Connection connection = DriverManager.getConnection(
                DB_URL, DB_USER, DB_PASSWORD
        );
        PreparedStatement statement = connection.prepareStatement(
                "UPDATE wizard SET first_name=?, last_name=?, birthday=?, birth_place=?, biography=?, is_muggle=? WHERE id=?"
        );
        statement.setString(1, firstName);
        statement.setString(2, lastName);
        statement.setDate(3, birthday);
        statement.setString(4, birthPlace);
        statement.setString(5, biography);
        statement.setBoolean(6, muggle);
        statement.setLong(7, id);

        if (statement.executeUpdate() != 1) {
            throw new SQLException("failed to update data");
        }
        return new Wizard(id, firstName, lastName, birthday,
                birthPlace, biography, muggle);
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return null;
}

La méthode qui exécute la requête de mise à jour est executeUpdate. La méthode retourne le nombre de tuples modifiés en base de données. Si ce nombre est différent de 1 : le processus n'a pas fonctionné. C'est pour cela qu'une erreur est levée !

Challenge

Mise à jour d'une école de la base de données

Fais un fork du dépôt suivant : https://github.com/WildCodeSchool/quest-spring-jdbc-update.

Attention: ce projet n'est pas le même que celui de la quête précédente !

Tu reprends le développement d'un site de fan d'Harry Potter afin d'y ajouter des fonctionnalités. En l'état, le site permet la modification d'un personnage de l'univers de la série.

La base de données est la même que celle de la quête précédente. Cependant, si tu l'as effacée, tu peux importer la base de données spring_jdbc_quest contenue dans le fichier suivant.

L'utilisateur est le même que celui de la quête précédente : h4rryp0tt3r avec le mot de passe Horcrux4life! et tous les droits possibles sur la base de données spring_jdbc_quest.

Tu vas commencer par tester le site et voir comment tout cela fonctionne.

Attention à bien regarder toutes les classes du dépôt avant de commencer le challenge !

  1. Tester que le site fonctionne correctement
  2. Ajouter la modification d'une école à partir d'un formulaire, sur la route /school/update

Critères de validation

  • Le projet s'exécute bien sur la base de données et l'utilisateur requis.
  • Il est possible de mettre à jour une école.
  • L'école est bien modifiée après sa mise à jour.
  • Le code JDBC est bien présent dans un repository et non un controller.