3. Flyway快速入门:Spring Boot集成Flyway配置、基础迁移脚本编写(V1__init.sql)、首次启动验证
本章是Flyway实战的起点。我们将从零搭建一个Spring Boot项目,完成Flyway依赖引入、核心参数配置、编写第一条版本化迁移脚本 V1__init.sql,并通过首次启动验证数据库表结构是否按预期创建。掌握本章内容后,你就能在自己的项目中快速落地Flyway,为后续的异步任务与性能调优打下坚实基础。
3.1 整体流程概览
Flyway与Spring Boot集成的核心流程分为四个步骤:引入依赖 → 配置数据源与Flyway参数 → 编写迁移脚本 → 启动验证。下图展示了从项目初始化到数据库表创建完成的完整链路。
3.2 第一步:引入Flyway依赖
在Spring Boot项目中,引入Flyway只需在构建文件中添加一个starter依赖。Spring Boot的自动配置机制会检测到该依赖,并自动启用Flyway。
Maven (pom.xml)
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
<!-- 如果使用MySQL,需要此扩展 -->
</dependency>
Gradle (build.gradle)
implementation 'org.flywaydb:flyway-core'
implementation 'org.flywaydb:flyway-mysql' // MySQL专用
版本兼容提示: Spring Boot 3.x 默认使用 Flyway 9.x,无需手动指定版本。如果使用 MySQL 8.0+,请确保
flyway-mysql 扩展已添加,否则 Flyway 无法识别 MySQL 方言。
3.3 第二步:配置数据源与Flyway参数
在 application.yml 中配置数据库连接信息以及Flyway的行为参数。以下是最小化配置示例:
spring:
datasource:
url: jdbc:mysql://localhost:3306/demo_db?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
username: root
password: root123
driver-class-name: com.mysql.cj.jdbc.Driver
flyway:
enabled: true # 启用Flyway(默认true)
locations: classpath:db/migration # 迁移脚本存放路径(默认值)
baseline-on-migrate: true # 对非空数据库执行基线迁移
validate-on-migrate: true # 迁移时校验已执行脚本是否被修改
下表列出了最常用的Flyway配置项及其说明:
| 配置项 | 默认值 | 说明 |
|---|---|---|
spring.flyway.enabled |
true | 是否启用Flyway自动迁移 |
spring.flyway.locations |
classpath:db/migration | 迁移脚本所在路径,支持多个路径用逗号分隔 |
spring.flyway.baseline-on-migrate |
false | 当目标数据库非空且无flyway_schema_history表时,是否自动执行基线迁移 |
spring.flyway.validate-on-migrate |
true | 迁移时校验已执行脚本的校验和是否与当前文件一致 |
spring.flyway.table |
flyway_schema_history | Flyway元数据表名,可自定义 |
spring.flyway.out-of-order |
false | 是否允许乱序执行迁移脚本(生产环境慎用) |
3.4 第三步:编写基础迁移脚本 V1__init.sql
在 src/main/resources/db/migration 目录下创建第一个迁移文件。文件名必须严格遵循 V{版本号}__{描述}.sql 格式,版本号从1开始递增。
以下是一个典型的初始化脚本,创建用户表和角色表:
-- ============================================
-- V1__init.sql
-- 描述:初始化用户表和角色表
-- 版本:1
-- ============================================
CREATE TABLE IF NOT EXISTS `sys_user` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`username` VARCHAR(50) NOT NULL COMMENT '用户名',
`password` VARCHAR(255) NOT NULL COMMENT '密码',
`email` VARCHAR(100) DEFAULT NULL COMMENT '邮箱',
`status` TINYINT DEFAULT 1 COMMENT '状态:1-启用 0-禁用',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
CREATE TABLE IF NOT EXISTS `sys_role` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`role_name` VARCHAR(50) NOT NULL COMMENT '角色名称',
`role_code` VARCHAR(50) NOT NULL COMMENT '角色编码',
`description` VARCHAR(255) DEFAULT NULL COMMENT '角色描述',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_role_code` (`role_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
-- 插入初始数据
INSERT INTO `sys_role` (`role_name`, `role_code`, `description`) VALUES
('管理员', 'ADMIN', '系统管理员,拥有所有权限'),
('普通用户', 'USER', '普通用户,拥有基础权限');
⚠️ 脚本编写注意事项:
- 每个迁移脚本只做一件事,保持原子性。
- 尽量使用
IF NOT EXISTS或CREATE OR REPLACE保证幂等性。 - 不要修改已执行过的脚本内容,否则
validate-on-migrate会报校验和错误。 - DDL 和 DML 可以放在同一个脚本中,但建议将数据初始化单独拆分为 V2__seed_data.sql。
3.5 第四步:首次启动验证
完成以上配置后,启动Spring Boot应用。观察控制台日志,你会看到类似以下的输出:
2025-01-15 10:23:45.123 INFO 12345 --- [main] o.f.c.internal.license.VersionPrinter : Flyway Community Edition 9.22.3 by Redgate
2025-01-15 10:23:45.456 INFO 12345 --- [main] o.f.c.internal.database.base.DatabaseType: Database: jdbc:mysql://localhost:3306/demo_db (MySQL 8.0)
2025-01-15 10:23:45.789 INFO 12345 --- [main] o.f.core.internal.command.DbMigrate : Current version of schema `demo_db`: << Empty Schema >>
2025-01-15 10:23:46.012 INFO 12345 --- [main] o.f.core.internal.command.DbMigrate : Migrating schema `demo_db` to version "1 - init"
2025-01-15 10:23:46.345 INFO 12345 --- [main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema `demo_db` (execution time 00:00.533s)
验证成功的三个标志:
- 日志无ERROR:Flyway成功执行了迁移,并打印了
Successfully applied信息。 - 数据库表已创建:登录MySQL客户端,执行
SHOW TABLES;,可以看到sys_user、sys_role以及flyway_schema_history三张表。 - flyway_schema_history 表有记录:查询该表,可以看到版本1的执行记录。
验证SQL示例
-- 查看所有表
SHOW TABLES FROM demo_db;
-- 查看Flyway迁移历史
SELECT version, description, script, installed_on, success
FROM flyway_schema_history
ORDER BY installed_rank;
查询结果应类似:
| version | description | script | installed_on | success |
|---|---|---|---|---|
| 1 | init | V1__init.sql | 2025-01-15 10:23:46 | 1 |
3.6 常见问题与排查
🔍 首次启动常见错误及解决方案:
- 错误:
FlywayException: Found non-empty schema(s) but no schema history table.
解决: 设置spring.flyway.baseline-on-migrate: true,或在已有数据库上手动执行flyway baseline。 - 错误:
FlywayException: Validate failed: Migration checksum mismatch for migration version 1
解决: 不要修改已执行过的脚本。如果确实需要修改,请创建新的迁移脚本(如 V2__fix_init.sql)来修正。 - 错误:
Table 'flyway_schema_history' doesn't exist且应用启动失败
解决: 检查数据库连接权限,确保应用账号有CREATE TABLE权限。
3.7 本章小结
通过本章的四个步骤,你已经成功在Spring Boot项目中集成了Flyway,并完成了第一次数据库版本化迁移。核心要点回顾:
- Flyway通过
flyway-core和数据库专用扩展(如flyway-mysql)实现自动迁移。 - 迁移脚本必须放置在
classpath:db/migration目录下,命名格式为V{版本}__{描述}.sql。 - 首次启动时,Flyway会自动创建
flyway_schema_history元数据表,并执行所有未执行的迁移脚本。 - 通过日志、数据库表结构和元数据表记录三个维度可以验证迁移是否成功。