Flyway is an Opensource Database migration tool, well known for its simplicity and effectiveness. This can be used from command-line, in Java projects, Maven plug-in, and Gradle plug-in. It is based on only 7 commands 7 basic commands: Migrate, Clean, Info, Validate, Undo, Baseline, and Repair. For more information one can check the official documentation here Documentation – Flyway by Redgate • Database Migrations Made Easy. (flywaydb.org)
Spring Boot and Flyway
Spring Boot comes with out-of-the-box integration for Flyway. To integrate and run flyway integration in spring boot you just need to add the following dependency in your spring boot project using Gradle or you can include this using your project build platform.
Important note for Mysql 8 and Maria DB support you need to add an additional dependency otherwise you will get the following exception
Caused by: org.flywaydb.core.api.FlywayException: Unsupported Database: MySQL 8.0
Addition dependencies can be found here and added as given below
Spring Boot will then automatically autowire Flyway with its default DataSource and invoke it on startup. It will automatically look for migration SQL scripts on the default location using the default versioning naming convention. You can also change Flyway DB migration properties using the
The default directory of the Flyway migration script in the spring boot project is
classpath:db/migration but one can change using property files or configuration using Springboot Java configuration. You can also user classpath or filesystem path as script location property as given below.
The above property will tell the Flyway migration tool to lookup scripts first in classpath then system path /opt/migration.
Script files name Typically, migrations are scripts in the form
<VERSION> an underscore-separated version, such as ‘1’ or ‘2_1’).version and name should be separated with a double underscore. eg V1__intitial.sql or V1_2__secondrev.sql.
Spring Boot Flyway Simple Example
For example, I added the following dependencies in my Spring Boot project in
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' runtimeOnly 'mysql:mysql-connector-java' implementation 'org.flywaydb:flyway-core:8.4.4' implementation 'org.flywaydb:flyway-mysql:8.4.4'
and added the following connection properties in the
spring.datasource.url=jdbc:mysql://192.168.1.30:3306/authdb?createDatabaseIfNotExist=true spring.datasource.username=user1 spring.datasource.password=password spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect spring.flyway.enabled=true spring.flyway.url = jdbc:mysql://localhost:3307/userdb spring.flyway.schemas=userdb spring.flyway.defaultSchema=userdb // default schema is importent spring.flyway.user = app-user spring.flyway.password = pwd spring.flyway.baseline-on-migrate=true
Note: For latest version you can get following exception
Unable to determine schema for the schema history table. Set a default schema for the connection or specify one using the ‘defaultSchema’ property. In this case you need to provide defaultSchema property as given above
In Spring properties use spring.flyway.defaultSchema=userdb normal Java project use flyway.defaultSchema=userdb
Now created migration directory
db/migrations inside resources directory and create
V1__intial.sql file as shown below
Now run your spring boot project. you can see the following logs of spring boot in the console
2022-02-13 10:22:49.621 INFO 15180 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2022-02-13 10:22:49.654 INFO 15180 --- [ main] o.f.c.internal.license.VersionPrinter : Flyway Community Edition 8.4.4 by Redgate 2022-02-13 10:22:49.654 INFO 15180 --- [ main] o.f.c.i.database.base.BaseDatabaseType : Database: jdbc:mysql://192.168.1.30:3306/authdb (MySQL 8.0) 2022-02-13 10:22:49.693 INFO 15180 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 1 migration (execution time 00:00.015s) 2022-02-13 10:22:49.707 INFO 15180 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table `authdb`.`flyway_schema_history` ... 2022-02-13 10:22:49.795 INFO 15180 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema `authdb`: << Empty Schema >> 2022-02-13 10:22:49.803 INFO 15180 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema `authdb` to version "1 - Initial" 2022-02-13 10:22:49.927 INFO 15180 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema `authdb`, now at version v1 (execution time 00:00.140s) 2022-02-13 10:22:50.059 INFO 15180 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
It created 2 tables and one index by executing 3 scripts in the database and it will also create one schema history table name
flyway_schema_history in the database for tracking of version.
It tracks changes by migration scripts name and their checksum if any file will modify after its execution it will throw an exception, this is the basic working of the flyway. for any change in schema and DB create another higher version.
The exception will look as given below
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.exception.FlywayValidateException: Validate failed: Migrations have failed validation Migration checksum mismatch for migration version 1 -> Applied to database : -419208586 -> Resolved locally : -1090537089. Either revert the changes to the migration, or run repair to update the schema history.
For the migration test, I create another version V1_2__Intial.sql with another table creation statement.
2022-02-13 10:31:51.543 INFO 10176 --- [ main] o.f.c.internal.license.VersionPrinter : Flyway Community Edition 8.4.4 by Redgate 2022-02-13 10:31:51.543 INFO 10176 --- [ main] o.f.c.i.database.base.BaseDatabaseType : Database: jdbc:mysql://192.168.1.30:3306/authdb (MySQL 8.0) 2022-02-13 10:31:51.589 INFO 10176 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 2 migrations (execution time 00:00.023s) 2022-02-13 10:31:51.600 INFO 10176 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema `authdb`: 1 2022-02-13 10:31:51.608 INFO 10176 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema `authdb` to version "1.2 - Intial" 2022-02-13 10:31:51.680 INFO 10176 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema `authdb`, now at version v1.2 (execution time 00:00.086s)
Now it created another table and the database is migrated successfully
If your sqlfile checksum is not matching and you are sure nothing is changed then update the checksum in DB with resolve locally checksum value.