アプリケーションが起動する前に初期データベースデータをロードするための最良の方法は何だろうか。私が探しているものは私のH2データベースをデータで満たすものです。
たとえば、 "user"というドメインモデルがあり、/ usersにアクセスしてユーザーにアクセスできますが、最初はデータベースにユーザーがいないため、作成する必要があります。データベースにデータを自動的に埋める方法はありますか。
現時点では、コンテナによってインスタンス化され、ユーザーを作成する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 ファイル(またはH2がデータベースの場合にのみ適用する場合はdata-h2.sql)を作成できます。フォルダとそれは起動時に自動的に実行されます。このファイルにいくつかのinsertステートメントを追加するだけです。
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
単純なテストデータを挿入したいだけの場合は、 ApplicationRunner
を実装することがよくあります。このインタフェースの実装はアプリケーションの起動時に実行され、たとえば次のものを使用できます。テストデータを挿入するためのautowiredリポジトリ.
私は、そのような実装はあなたのものよりわずかに明白であると思います。なぜならインターフェースはあなたの実装があなたがあなたのアプリケーションの準備ができた直後にあなたがやりたい何かを含んでいることを意味します。
あなたの実装は気が遠くなるでしょう。このような:
@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
(それ以外の場合、スクリプトはHibernateによって無視され、@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)
誰かに役立つことを願っています
実行したいSQLファイルをリストするspring.datasource.data
プロパティをapplication.properties
に追加することができます。このような:
spring.datasource.data=classpath:accounts.sql, classpath:books.sql, classpath:reviews.sql
これらの各ファイルのsql insertステートメントが実行されるので、物事を整理することができます。
あなたはこのようなものを使うことができます:
@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
これが私のやり方です。
@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/ /
import.sql
にsrc/main/resources
ファイルを作成するだけで、スキーマの作成時にHibernateがそれを実行します。
私はこのようにして同様の問題を解決しました:
@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();
}
}
あなたは以下のようにそれを達成するために登録してイベントリスナーを作ることができます:
@EventListener
public void seed(ContextRefreshedEvent event) {
userRepository.save(new User("lala", "lala", "lala"));
}
ContextRefreshEventが起動されると、モデルとリポジトリを含む、アプリケーション内のすべての自動生成されたBeanにアクセスできます。
誰かが 受け入れられた答え に従ってもこれを動作させることに苦労しているなら、私のためだけに私のsrc/test/resources/application.yml
にH2 datasource
詳細を追加する仕事:
spring:
datasource:
platform: h2
url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
driver-class-name: org.h2.Driver
username: sa
password:
これもうまくいきます。
@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)));
};
}
最もコンパクトな(動的データ用)の@ mathias-dpunktソリューションを(Lombok @AllArgsConstructor
を使って)MainAppに入れます。
@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()));
}
}