[spring] 스프링 부트-초기 데이터로드

응용 프로그램이 시작되기 전에 초기 데이터베이스 데이터를로드하는 가장 좋은 방법이 무엇인지 궁금합니다. 내가 찾고있는 것은 H2 데이터베이스를 데이터로 채울 무언가입니다.

예를 들어, / users로 이동하여 사용자에게 액세스 할 수있는 도메인 모델 “User”가 있지만 처음에는 데이터베이스에 사용자가 없으므로 사용자를 만들어야합니다. 어쨌든 데이터베이스를 자동으로 데이터로 채울 수 있습니까?

현재 컨테이너에 의해 인스턴스화되고 사용자를 생성하는 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"));
    }
}

그러나 그것이 최선의 방법이라고 의심합니다. 아니면?



답변

src / main / resources 폴더 에 data.sql 파일을 만들면 시작할 때 자동으로 실행됩니다. 이 파일에는 다음과 같은 삽입 문 만 추가하면됩니다.

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 부트는 이미 메모리 데이터베이스에 대한 엔티티를 기반으로 스키마를 작성하도록 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


답변

간단한 테스트 데이터를 삽입하고 싶다면 종종을 구현합니다 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"));
    }
}


답변

제안으로 이것을 시도하십시오 :

@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 아이디어)

누군가에게 도움이되기를 바랍니다.


답변

실행할 SQL 파일 spring.datasource.dataapplication.properties나열 하는 특성을 추가 할 수 있습니다 . 이처럼 :

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

이러한 각 파일의 sql insert 문이 실행되어 깔끔하게 유지할 수 있습니다.

예를 들어 파일을 클래스 경로에 넣으면 src/main/resources적용됩니다. 또는 교체 classpath:file:하고 파일에 대한 절대 경로를 사용


답변

다음과 같은 것을 사용할 수 있습니다.

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


답변

Spring Boot를 사용하면 간단한 스크립트를 사용하여 Spring Batch를 사용하여 데이터베이스를 초기화 할 수 있습니다 .

그럼에도 불구하고 DB 버전 등을 관리하기 위해 좀 더 정교한 것을 사용하려는 경우 Spring Boot는 Flyway 와 잘 통합 됩니다.

또한보십시오:


답변

Spring Boot 2에서 data.sql은 spring boot 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