Skip to content

Seeding SQL

Pour insérer des données de façon automatique au lancement de l'application (seeding), on pourra ajouter un script SQL dans le dossier de ressources pour qu'il soit exécuté au début de l'application.

  • Créez un script SQL correspondant au langage de votre SGBD et nommez le data.sql
  • Insérez les instructions d'insertion dans les tables au script
  • Placez ce fichier à la racine du dossier resources.

On devra aussi ajouter un peu de configuration au fichier application.properties.

spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.defer-datasource-initialization=true
spring.sql.init.mode=always

Ainsi, lors du démarrage de l'application, le script data.sql sera exécuté et les données insérées dans les tables.

Notez bien

Remarquez que j'ai utilisé la configuration de l'initialisation du schéma create-drop. Ceci fera en sotre qu'on évite de toujours insérer les données à chaque fois qu'on démarre l'application.

Seeding de modèles avec CommandLineRunner

Le script data.sql est pratique pour insérer des données simples. Cependant, certaines données nécessitent de la logique Java pour être créées correctement. Par exemple :

  • Encoder un mot de passe avant de l'enregistrer.
  • Vérifier si un utilisateur existe déjà avant de le créer.
  • Associer un utilisateur à un ou plusieurs rôles.
  • etc.

Pour ces situations, nous pouvons utiliser un CommandLineRunner, une interface de Spring qui permet d'exécuter du code au démarrage de l'application.

Création de la classe DataSeeder

Créez une classe DataSeeder dans votre projet et ajoutez les annotations @Configuration et @Bean.

@Configuration
public class DataSeeder {

    @Bean
    public CommandLineRunner seedData() {
        return args -> {
            // Code exécuté au démarrage
        };
    }
}
  • @Configuration indique à Spring que cette classe contient de la configuration.
  • @Bean indique à Spring que la méthode retourne un objet qu'il doit gérer.
  • CommandLineRunner permet d'exécuter le code de la lambda au démarrage de l'application, une fois le contexte Spring initialisé.

Accéder aux respositories et aux services

Nous pouvons demander à Spring de fournir les objets dont nous avons besoin en les ajoutant aux paramètres de la méthode annotée @Bean.

@Configuration
public class DataSeeder {

    @Bean
    public CommandLineRunner seedData(
        IUtilisateurRepository utilisateurRepository,
        IRoleRepository roleRepository,
        PasswordEncoder passwordEncoder
    ) {
        return args -> {
            // Code exécuté au démarrage
        };
    }
}

Spring injecte automatiquement les dépendances nécessaires, à condition qu'elles soient correctement déclarées dans l'application.

Nous pouvons ainsi utiliser les repositories pour rechercher et enregistrer des entités, ainsi que les services pour effectuer des opérations nécessitant une logique particulière.

Exemple

Role roleUser = roleRepository.findByNom("ROLE_USER");

if (roleUser == null) {
    roleUser = new Role();
    roleUser.setNom("ROLE_USER");
    roleRepository.save(roleUser);
}

Utilisateur baseAdmin = utilisateurRepository.findFirstByUsername("admin");

if (baseAdmin == null) {
    baseAdmin = Utilisateur.builder()
            .username("admin")
            .password(passwordEncoder.encode("admin"))
            .roles(new HashSet<>(Set.of(roleAdmin)))
            .build();

    utilisateurRepository.save(baseAdmin);