SpringBoot - 整合Flyway实现数据库版本管理教程
作者:hangge | 2026-06-16 09:33
在日常开发中,数据库表结构往往会随着业务不断变化:今天新增一个字段,明天改一下索引,后天又要补一张表。如果这些变更靠人工手动执行,不仅麻烦,还很容易出现“脚本执行顺序错乱”“线上线下结构不一致”等问题。
Flyway 就是专门用来解决这类问题的数据库版本管理工具。它可以把数据库变更脚本像代码一样纳入项目管理,随着应用启动自动检查并执行未完成的数据库迁移脚本,让我们的数据库结构始终保持可追踪、可回放、可控。下面我将通过样例演示如何在 Spring Boot 项目中集成并使用 Flyway。
一、基本介绍与安装配置
1,什么是 Flyway?
(1)Flyway 是一款开源的数据库版本迁移工具,支持 MySQL、PostgreSQL、Oracle 等绝大多数主流数据库。它的核心思想是:所有数据库结构变更都以 SQL 脚本的形式存在,按版本号排序,自动执行并记录历史。
(2)Flyway 具有如下优势:
- 版本控制:每次数据库变更都有明确的版本号,便于追溯和管理
- 自动化执行:应用启动时自动执行未运行的迁移脚本
- 环境一致性:确保所有环境使用相同的迁移脚本,保证一致性
- 团队协作:迁移脚本作为代码的一部分,便于团队协作和代码审查
- 回滚支持:虽然社区版不支持自动回滚,但可以通过新迁移实现回滚
- 多种格式:支持 SQL 和 Java 两种迁移脚本格式
2,核心工作原理
(1)Flyway 会在数据库中自动创建一张名为 flyway_schema_history 的元数据表,用于记录所有已经执行过的脚本版本、描述、校验值、执行时间等信息。
(2)应用启动时,Flyway 会执行以下流程:
- 扫描指定目录下的所有 SQL 迁移脚本
- 读取元数据表,对比哪些脚本已经执行、哪些是新增的
- 按照版本号从小到大的顺序,依次执行未执行的脚本
- 执行完成后,将脚本信息写入元数据表
3,常用脚本类型
Flyway 支持三种主要的脚本类型,通过文件名前缀区分:
- V 开头(Versioned):版本化迁移脚本,每个版本只执行一次,版本号唯一
- U 开头(Undo):撤销迁移脚本,用于回滚对应版本的变更(专业版功能)
- R 开头(Repeatable):可重复执行脚本,当脚本内容校验和发生变化时重新执行,适合视图、存储过程、函数等
4,安装配置
(1)编辑项目的 pom.xml 文件,添加 Flyway 依赖。
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<!-- MySQL 8.x 需要添加此依赖 -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
(2)在 application.yml 中添加 Flyway 基础配置:
spring:
application:
name: demo
datasource:
url: jdbc:mysql://192.168.121.128:3306/jeecg-boot?characterEncoding=UTF-8........
username: root
password: Hangge_123
driver-class-name: com.mysql.cj.jdbc.Driver
# Flyway 配置
flyway:
# 是否启用Flyway,默认true
enabled: true
# SQL脚本存放路径,默认classpath:db/migration
locations: classpath:db/migration
# 迁移脚本编码
encoding: UTF-8
# 元数据表名称,默认flyway_schema_history
table: flyway_schema_history
# 当数据库非空且没有元数据表时,是否自动创建基线
baseline-on-migrate: true
# 基线版本号,默认1
baseline-version: 1
(3)在 resources 目录下创建 db/migration 文件夹,后续 SQL 脚本将会存放在该目录下。

二、使用样例
1,版本化迁移脚本(只执行一次)
(1)首先我们在 src/main/resources/db/migration 目录下创建第一个初始化脚本 V1__init_user_table.sql,内容如下:
命名规范: 前缀 + 版本号 + __ + 描述.sql
- 前缀:V 表示版本化脚本
- 版本号:数字,支持小数点,如 1、1.1、2.0.1
- 双下划线 __:分隔符,必须是两个下划线
- 描述:脚本功能说明,单词间可用下划线分隔
-- 创建用户表
CREATE TABLE `user` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
`username` VARCHAR(50) NOT NULL COMMENT '用户名',
`email` VARCHAR(100) NOT NULL COMMENT '邮箱',
`password` VARCHAR(255) NOT 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 '更新时间',
UNIQUE KEY `uk_username` (`username`),
UNIQUE KEY `uk_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
-- 创建索引
CREATE INDEX `idx_status` ON `user` (`status`);
CREATE INDEX `idx_create_time` ON `user` (`create_time`);
(2)接着再创建第二个版本脚本 V1.1__add_user_data.sql,内容如下:
-- 插入默认管理员
INSERT INTO `user` (`username`, `email`, `password`, `status`)
VALUES ('admin', 'admin@example.com', '$2a$10$encrypted_password', 1);
(3)启动 Spring Boot 应用,Flyway 会自动执行如下步骤。
- 检查数据库中是否存在 flyway_schema_history 表(不存在则创建)
- 扫描 db/migration 目录下的迁移脚本
- 比对已执行的迁移记录,执行未运行的脚本
- 记录执行结果到历史表中

(4)待启动完毕,我们访问数据库可以看到相关的表和数据均成功创建完毕。

2,可重复执行脚本
(1)对于视图、存储过程这类可以重复执行的对象,使用 R 开头的脚本。每次启动时 Flyway 会对比校验和,如果脚本内容有变化就重新执行。这里创建第一个可重复执行脚本 R__create_user_view.sql,内容如下:
CREATE OR REPLACE VIEW `v_user_info` AS SELECT id, username, email, status FROM user WHERE status = 1;
(2)启动项目可以看到视图已经成功创建。

(3)接着我对 R__create_user_view.sql 稍作修改:
CREATE OR REPLACE VIEW `v_user_info` AS SELECT id, username FROM user WHERE status = 1;
(4)重启项目,可以看到视图也发生了变化,说明该脚本由于内容变化重新又执行了。

附:进阶用法
1,占位符替换
(1)Flyway 支持在 SQL 脚本中使用占位符,通过配置动态替换。这里我们在 application.yml 的 Flyway 配置中添加两个占位符变量:
- table_prefix 用于表示表名前缀。
- default_status 用于表示默认状态值。
# Flyway 配置
flyway:
# 是否启用Flyway,默认true
enabled: true
# SQL脚本存放路径,默认classpath:db/migration
locations: classpath:db/migration
# 迁移脚本编码
encoding: UTF-8
# 元数据表名称,默认flyway_schema_history
table: flyway_schema_history
# 当数据库非空且没有元数据表时,是否自动创建基线
baseline-on-migrate: true
# 基线版本号,默认1
baseline-version: 1
# 占位符变量
placeholders:
table_prefix: hangge_
default_status: 1
(2)接着我们的 SQL 脚本中就可以使用这两个占位符了。
CREATE TABLE `${table_prefix}role` (
`id` bigint NOT NULL AUTO_INCREMENT,
`role_name` varchar(50) NOT NULL,
`status` tinyint DEFAULT ${default_status},
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
(3)启动项目执行脚本,查看数据可以可以发现占位符已经成功生效。

2,生产环境关键配置
spring:
flyway:
# 禁用clean命令,防止误操作清空数据库!生产环境必须设为true
clean-disabled: true
# 迁移失败时是否自动清理,生产环境关闭
clean-on-validation-error: false
# 校验不通过时是否终止启动,建议开启
validate-on-migrate: true
# 禁止乱序执行,保证版本顺序
out-of-order: false
全部评论(0)