Подтвердить что ты не робот

Spring Загрузка - Загрузка исходных данных

Мне интересно, какой лучший способ загрузить исходные данные базы данных до запуска приложения? Я ищу что-то, что заполнит мою базу данных H2 данными.

Например, у меня есть модель домена "Пользователь", я могу получить доступ к пользователям, перейдя к/пользователям, но изначально в базе данных не будет пользователей, поэтому я должен их создать. Есть ли все-таки, чтобы заполнить базу данных данными автоматически?

В настоящий момент у меня есть Bean, который создается экземпляром контейнера и создает для меня пользователей.

Пример:

@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"));
    }
}

Но я очень сомневаюсь, что это лучший способ сделать это. Или это?

4b9b3361

Ответ 1

Вы можете просто создать файл data.sql в папке src/main/resources, и он будет автоматически выполнен при запуске. В этом файле вы просто добавляете несколько операторов вставки, например:

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

Точно так же вы можете создать schema.sql файл (или schema-h2.sql), а также создать свою схему:

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

Хотя обычно вам не нужно этого делать, поскольку Spring boot уже настраивает Hibernate для создания вашей схемы на основе ваших сущностей для базы данных в памяти. Если вы действительно хотите использовать schema.sql, вам придется отключить эту функцию, добавив ее в свой application.properties:

spring.jpa.hibernate.ddl-auto=none

Дополнительную информацию можно найти в документации по инициализации базы данных.


Если вы используете Spring boot 2, инициализация базы данных работает только для встроенных баз данных (H2, HSQLDB,...). Если вы хотите использовать его и для других баз данных, вам нужно изменить свойство spring.datasource.initialization-mode:

spring.datasource.initialization-mode=always

Если вы используете несколько поставщиков баз данных, вы можете назвать свой файл data-h2.sql или data-mysql.sql в зависимости от того, какую платформу базы данных вы хотите использовать.

Чтобы это работало, вам нужно настроить свойство spring.datasource.platform:

spring.datasource.platform=h2

Ответ 2

Если я просто хочу вставить простые тестовые данные, я часто реализую ApplicationRunner. Реализации этого интерфейса запускаются при запуске приложения и могут использовать, например. авторизованный репозиторий для вставки некоторых тестовых данных.

Я думаю, что такая реализация будет немного более явной, чем ваша, потому что интерфейс подразумевает, что ваша реализация содержит то, что вы хотели бы сделать непосредственно после того, как ваше приложение будет готово.

Ваша реализация будет выглядеть sth. например:

@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"));
    }
}

Ответ 3

В качестве предложения попробуйте следующее:

@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("");
    }
}

Вариант 2: Инициализировать с помощью сценариев схемы и данных

Предпосылки: в application.properties вы должны упомянуть об этом:

spring.jpa.hibernate.ddl-auto=none (иначе скрипты будут игнорироваться спящим режимом, и он будет сканировать проект для аннотированных классов @Entity и/или @Table)

Затем в вашем классе MyApplication вставьте это:

@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;
}

Где папка scripts находится в папке resources (IntelliJ Idea)

Надеюсь, что это поможет кому-то

Ответ 4

Вы можете добавить свойство spring.datasource.data в application.properties котором перечислены файлы sql, которые вы хотите запустить. Как это:

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

Затем будут выполняться операторы вставки sql в каждом из этих файлов, что позволит вам сохранить порядок

Ответ 5

Вы можете использовать что-то вроде этого:

@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"));
      };
   }
}

Ответ 6

Spring Загрузка позволяет вам использовать простой script для инициализации вашей базы данных, используя Spring Batch.

Тем не менее, если вы хотите использовать что-то более сложное для управления версиями DB и т.д., Spring Boot хорошо интегрируется с Flyway.

См. также:

Ответ 7

В Spring Boot 2 data.sql не работал со мной, как в весенней загрузке 1.5

import.sql

Кроме того, файл с именем import.sql в корне пути к классам выполняется при запуске, если Hibernate создает схему с нуля (то есть, если для свойства ddl-auto установлено значение create или create-drop).

Обратите внимание, очень важно, если вы вставляете ключи не могут быть дублированы, не используйте ddl-auto, свойство устанавливается на обновление, потому что при каждом перезапуске вставляются одни и те же данные снова

Для получения дополнительной информации вы посетите весенний веб-сайт

https://docs.spring.io/spring-boot/docs/current/reference/html/howto-database-initialization.html

Ответ 8

Вот как я это понял:

@Component
public class ApplicationStartup implements ApplicationListener<ApplicationReadyEvent> {

    /**
     * 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
    }

}

Спасибо автору этой статьи:

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

Ответ 9

Вы можете просто создать файл import.sql в src/main/resources, а Hibernate выполнит его при создании схемы.

Ответ 10

Я решил подобную проблему следующим образом:

@Component
public class DataLoader {

    @Autowired
    private UserRepository userRepository;

    //method invoked during the startup
    @PostConstruct
    public void loadData() {
        userRepository.save(new User("user"));
    }

    //method invoked during the shutdown
    @PreDestroy
    public void removeData() {
        userRepository.deleteAll();
    }
}

Ответ 11

Вы можете зарегистрироваться и прослушивать события, чтобы добиться этого, как показано ниже:

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

Когда запускается ContextRefreshEvent, мы получаем доступ ко всем автоматически подключаемым bean-компонентам в приложении, включая модели и репозитории.

Ответ 12

Если кто-то изо всех сил пытается сделать так, чтобы это работало даже после принятого ответа, для меня работало только добавление в мой src/test/resources/application.yml подробностей datasource H2:

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

Ответ 13

Это тоже будет работать.

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

Ответ 14

Самое компактное (для динамических данных) размещение решения @mathias-dpunkt в MainApp (с 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()));
  }
}

Ответ 15

Если вы хотите вставить только несколько строк и у вас есть JPA Setup. Вы можете использовать ниже

    @SpringBootApplication
        @Slf4j
        public class HospitalManagementApplication {

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

            @Bean
            ApplicationRunner init(PatientRepository repository) {
                return (ApplicationArguments args) ->  dataSetup(repository);
            } 

            public void dataSetup(PatientRepository repository){
            //inserts

     }