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
};
}
}
@Configurationindique à Spring que cette classe contient de la configuration.@Beanindique à Spring que la méthode retourne un objet qu'il doit gérer.CommandLineRunnerpermet 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);