Spring Boot: carga de datos iniciales

Me pregunto cuál es la mejor forma de cargar los datos iniciales de la base de datos antes de que comience la aplicación. Lo que estoy buscando es algo que llene mi base de datos H2 con datos.

Por ejemplo, tengo un modelo de dominio “Usuario”. Puedo acceder a los usuarios yendo a / usuarios, pero inicialmente no habrá usuarios en la base de datos, así que tengo que crearlos. ¿Hay alguna forma de llenar la base de datos con datos automáticamente?

Por el momento, tengo un Bean que obtiene una instancia del contenedor y crea usuarios para mí.

Ejemplo:

@Component public class DataLoader { private UserRepository userRepository; @Autowired public DataLoader(UserRepository userRepository) { this.userRepository = userRepository; LoadUsers(); } private void LoadUsers() { userRepository.save(new User("lala", "lala", "lala")); } } 

Pero dudo mucho que sea la mejor manera de hacerlo. ¿O es eso?

    Simplemente puede crear un archivo data.sql (o data-h2.sql si solo desea que se aplique en caso de que H2 sea su base de datos) en su carpeta src / main / resources y se ejecutará automáticamente al inicio. En este archivo, simplemente agrega algunas instrucciones de inserción, p. Ej .:

     INSERT INTO users (username, firstname, lastname) VALUES ('lala', 'lala', 'lala'), ('lolo', 'lolo', 'lolo'); 

    Del mismo modo, puede crear un archivo schema.sql (o schema-h2.sql) para crear su esquema:

     CREATE TABLE task ( id INTEGER PRIMARY KEY, description VARCHAR(64) NOT NULL, completed BIT NOT NULL); 

    Aunque normalmente no debería tener que hacer esto, ya que Spring boot ya configura Hibernate para crear su esquema basado en sus entidades para una base de datos en memoria. Si realmente desea usar schema.sql, deberá deshabilitar esta característica agregando esto a su application.properties:

     spring.jpa.hibernate.ddl-auto=none 

    Se puede encontrar más información en la documentación sobre la inicialización de la base de datos .


    Si está utilizando Spring boot 2 , la inicialización de la base de datos solo funciona para bases de datos incrustadas (H2, HSQLDB, …). Si también desea usarlo para otras bases de datos, debe cambiar la propiedad spring.datasource.initialization-mode :

     spring.datasource.initialization-mode=always 

    Si solo quiero insertar datos de prueba simples, a menudo implemento un ApplicationRunner . Las implementaciones de esta interfaz se ejecutan al inicio de la aplicación y pueden usar, por ejemplo, un repository autocableado para insertar algunos datos de prueba.

    Creo que tal implementación sería un poco más explícita que la suya porque la interfaz implica que su implementación contiene algo que le gustaría hacer directamente después de que su aplicación esté lista.

    Su implementación se vería algo así. Me gusta esto:

     @Component public class DataLoader implements ApplicationRunner { private UserRepository userRepository; @Autowired public DataLoader(UserRepository userRepository) { this.userRepository = userRepository; } public void run(ApplicationArguments args) { userRepository.save(new User("lala", "lala", "lala")); } } 

    Como sugerencia prueba esto:

     @Bean public CommandLineRunner loadData(CustomerRepository repository) { return (args) -> { // save a couple of customers repository.save(new Customer("Jack", "Bauer")); repository.save(new Customer("Chloe", "O'Brian")); repository.save(new Customer("Kim", "Bauer")); repository.save(new Customer("David", "Palmer")); repository.save(new Customer("Michelle", "Dessler")); // fetch all customers log.info("Customers found with findAll():"); log.info("-------------------------------"); for (Customer customer : repository.findAll()) { log.info(customer.toString()); } log.info(""); // fetch an individual customer by ID Customer customer = repository.findOne(1L); log.info("Customer found with findOne(1L):"); log.info("--------------------------------"); log.info(customer.toString()); log.info(""); // fetch customers by last name log.info("Customer found with findByLastNameStartsWithIgnoreCase('Bauer'):"); log.info("--------------------------------------------"); for (Customer bauer : repository .findByLastNameStartsWithIgnoreCase("Bauer")) { log.info(bauer.toString()); } log.info(""); } } 

    Opción 2: Inicializar con scripts de esquema y datos

    Prerrequisitos: en application.properties debes mencionar esto:

    spring.jpa.hibernate.ddl-auto=none (de lo contrario, hibernate ignorará los scripts y escaneará el proyecto para las clases anotadas @Entity y / o @Table )

    Luego, en su clase MyApplication , pegue esto:

     @Bean(name = "dataSource") public DriverManagerDataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("org.h2.Driver"); dataSource.setUrl("jdbc:h2:~/myDB;MV_STORE=false"); dataSource.setUsername("sa"); dataSource.setPassword(""); // schema init Resource initSchema = new ClassPathResource("scripts/schema-h2.sql"); Resource initData = new ClassPathResource("scripts/data-h2.sql"); DatabasePopulator databasePopulator = new ResourceDatabasePopulator(initSchema, initData); DatabasePopulatorUtils.execute(databasePopulator, dataSource); return dataSource; } 

    Donde la carpeta de scripts se encuentra en resources carpeta de resources (IntelliJ Idea)

    Espero que ayude a alguien

    Spring Boot le permite usar un script simple para inicializar su base de datos, usando Spring Batch .

    Aún así, si desea utilizar algo un poco más elaborado para administrar versiones de DB, etc., Spring Boot se integra bien con Flyway .

    Ver también:

    • Inicialización de la base de datos Spring Boot

    Así es como lo tengo:

     @Component public class ApplicationStartup implements ApplicationListener { /** * This event is executed as late as conceivably possible to indicate that * the application is ready to service requests. */ @Autowired private MovieRepositoryImpl movieRepository; @Override public void onApplicationEvent(final ApplicationReadyEvent event) { seedData(); } private void seedData() { movieRepository.save(new Movie("Example")); // ... add more code } } 

    Gracias al autor de este artículo:

    http://blog.netgloo.com/2014/11/13/run-code-at-spring-boot-startup/

    Puedes usar algo como esto:

     @SpringBootApplication public class Application { @Autowired private UserRepository userRepository; public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean InitializingBean sendDatabase() { return () -> { userRepository.save(new User("John")); userRepository.save(new User("Rambo")); }; } } 

    Puede agregar una propiedad spring.datasource.data a application.properties enumere los archivos sql que desea ejecutar. Me gusta esto:

     spring.datasource.data=classpath:accounts.sql, classpath:books.sql, classpath:reviews.sql 

    Las instrucciones de inserción sql en cada uno de estos archivos se ejecutarán, lo que le permite mantener las cosas ordenadas

    Simplemente puede crear un archivo import.sql en src/main/resources e Hibernate lo ejecutará cuando se cree el esquema.

    puedes registrarte e incluso escuchar para lograr eso como a continuación:

     @EventListener public void seed(ContextRefreshedEvent event) { userRepository.save(new User("lala", "lala", "lala")); } 

    Cuando se activa el ContextRefreshEvent, obtenemos acceso a todos los beans autoconectados en la aplicación, incluidos los modelos y repositorys.

    Esto también funcionará.

      @Bean CommandLineRunner init (StudentRepo studentRepo){ return args -> { // Adding two students objects List names = Arrays.asList("udara", "sampath"); names.forEach(name -> studentRepo.save(new Student(name))); }; } 

    El más compacto (para datos dynamics) pone la solución @ mathias-dpunkt en MainApp (con Lombok @AllArgsConstructor ):

     @SpringBootApplication @AllArgsConstructor public class RestaurantVotingApplication implements ApplicationRunner { private final VoteRepository voteRepository; private final UserRepository userRepository; public static void main(String[] args) { SpringApplication.run(RestaurantVotingApplication.class, args); } @Override public void run(ApplicationArguments args) { voteRepository.save(new Vote(userRepository.getOne(1), LocalDate.now(), LocalTime.now())); } } 

    Si alguien está luchando para que esto funcione incluso después de la respuesta aceptada , para mí solo trabajo agregando en mi src/test/resources/application.yml los detalles de la fuente de datasource H2:

     spring: datasource: platform: h2 url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1 driver-class-name: org.h2.Driver username: sa password: