17

What is the right way for creating test data upon server startup and inserting them into the database (I'm using a JPA/JDBC backed Postgres instance).

Preferably in form of creating Entities and having them persisted through a Repository interface rather than writing plain SQL code. Something like RoR's Rake db:seed helper.

If the framework exposes a hook for doing stuff when all the beans have been injected and the database is ready, that could also work.

Paghillect
  • 822
  • 1
  • 11
  • 30

3 Answers3

47

You can catch ApplicationReadyEvent then insert demo data, for example:

@Component
public class DemoData {

    @Autowired
    private final EntityRepository repo;

    @EventListener
    public void appReady(ApplicationReadyEvent event) {

        repo.save(new Entity(...));
    }
}

Or you can implement CommandLineRunner or ApplicationRunner, to load demo data when an application is fully started:

@Component
public class DemoData implements CommandLineRunner {

    @Autowired
    private final EntityRepository repo;

    @Override
    public void run(String...args) throws Exception {

        repo.save(new Entity(...));
    }
}

@Component
public class DemoData implements ApplicationRunner {

    @Autowired
    private final EntityRepository repo;

    @Override
    public void run(ApplicationArguments args) throws Exception {

        repo.save(new Entity(...));
    }
}

Or even implement them like a Bean right in your Application (or other 'config') class:

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public CommandLineRunner demoData(EntityRepository repo) {
        return args -> { 

            repo.save(new Entity(...));
        }
    }
}
Cepr0
  • 28,144
  • 8
  • 75
  • 101
8

From Spring documentation: http://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/reference/htmlsingle/#howto-database-initialization

Initialize a database using Hibernate A file named import.sql in the root of the classpath will be executed on startup if Hibernate creates the schema from scratch (that is if the ddl-auto property is set to create or create-drop). This can be useful for demos and for testing if you are careful, but probably not something you want to be on the classpath in production. It is a Hibernate feature (nothing to do with Spring).

Moshe Arad
  • 3,587
  • 4
  • 18
  • 33
  • What is meant by root of the classpath ? the root of the src folder ? cause I think this definition is rather dependent on the build tool/platform. – Paghillect Jun 25 '17 at 20:36
  • If you are using Maven, then a folder like: /src/main/resources @Parsoa – Moshe Arad Jun 25 '17 at 20:40
  • Thanks. Anyway this approach seems quite error prone and time consuming for the amount of data I need to insert. I'd like it better if there was a Java solution. – Paghillect Jun 25 '17 at 20:45
  • This is the only solution to what you are trying to achieve according to spring boot documentation – Moshe Arad Jun 25 '17 at 20:48
4

You can do like this

    @SpringBootApplication
    public class H2Application {

        public static void main(String[] args) {
            SpringApplication.run(H2Application.class, args);
        }

        @Bean
        CommandLineRunner init (StudentRepo studentRepo){
            return args -> {
                List<String> names = Arrays.asList("udara", "sampath");
                names.forEach(name -> studentRepo.save(new Student(name)));
            };
        }
    }
Udara S.S Liyanage
  • 6,189
  • 9
  • 33
  • 34