概要
Springでflywayを使用したマイグレーション方法について説明します。
準備
pom.xmlにflywayを追加
下記を追加する
/{プロジェクト名}/pom.xml
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
DB接続情報を追加
/{プロジェクト名}/src/main/resources/application.properties
spring.datasource.url=jdbc:mysql://localhost/{接続DB名}
spring.datasource.username={接続ユーザ名}
spring.datasource.password={接続ユーザのパスワード}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
実行SQL文用意
/{プロジェクト名}/src/main/resources/db/migration/V1__test.sql
CREATE TABLE `test_1` (
`id` int NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
補足
SQLファイルのファイル名について下記の要領で指定する。
V{バージョン番号}__{任意の文字列}.sql
実行
通常プロジェクト起動と同様に実行する。
コンソールに下記のような出力がされればOK。
o.f.c.i.database.base.BaseDatabaseType : Database: jdbc:mysql://localhost/test (MySQL 8.0)
o.f.core.internal.command.DbValidate : Successfully validated 1 migration (execution time 00:00.021s)
o.f.core.internal.command.DbMigrate : Current version of schema `test`: << Empty Schema >>
o.f.core.internal.command.DbMigrate : Migrating schema `test` to version "1 - test"
o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema `test`, now at version v1 (execution time 00:00.100s)
下記の通り
SQL文により作成されたテーブル「test_1」と
履歴を管理するテーブル「flyway_schema_history」が追加されます。
補足
対象DBに対してすでにテーブルが作成済みの場合、
下記の通りエラーになります。
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.api.FlywayException: Found non-empty schema(s) `test` but no schema history table. Use baseline() or set baselineOnMigrate to true to initialize the schema history table.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804) ~[spring-beans-5.3.18.jar:5.3.18]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.18.jar:5.3.18]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.18.jar:5.3.18]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.18.jar:5.3.18]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.18.jar:5.3.18]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.18.jar:5.3.18]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.18.jar:5.3.18]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.3.18.jar:5.3.18]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.18.jar:5.3.18]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:953) ~[spring-beans-5.3.18.jar:5.3.18]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.18.jar:5.3.18]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.18.jar:5.3.18]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740) [spring-boot-2.6.6.jar:2.6.6]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415) [spring-boot-2.6.6.jar:2.6.6]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-2.6.6.jar:2.6.6]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) [spring-boot-2.6.6.jar:2.6.6]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) [spring-boot-2.6.6.jar:2.6.6]
at com.example.demo.TestApplication.main(TestApplication.java:10) [classes/:na]
Caused by: org.flywaydb.core.api.FlywayException: Found non-empty schema(s) `test` but no schema history table. Use baseline() or set baselineOnMigrate to true to initialize the schema history table.
at org.flywaydb.core.Flyway$1.execute(Flyway.java:154) ~[flyway-core-8.0.5.jar:na]
at org.flywaydb.core.Flyway$1.execute(Flyway.java:124) ~[flyway-core-8.0.5.jar:na]
at org.flywaydb.core.FlywayExecutor.execute(FlywayExecutor.java:214) ~[flyway-core-8.0.5.jar:na]
at org.flywaydb.core.Flyway.migrate(Flyway.java:124) ~[flyway-core-8.0.5.jar:na]
at org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializer.afterPropertiesSet(FlywayMigrationInitializer.java:66) ~[spring-boot-autoconfigure-2.6.6.jar:2.6.6]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) ~[spring-beans-5.3.18.jar:5.3.18]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ~[spring-beans-5.3.18.jar:5.3.18]
... 17 common frames omitted