数据库

Flyway

Flyway 是一款优秀的数据库版本控制工具,核心用于解决 Java 项目中数据库脚本的统一管理、版本追溯、自动执行等问题,避免手动执行 SQL 脚本带来的遗漏、顺序混乱、环境不一致等问题。

一、Flyway 核心前置知识

1. 核心价值 

  • 自动化执行数据库迁移脚本,项目启动时自动完成数据库结构 / 数据的更新;
  • 记录数据库迁移历史,形成可追溯的版本链,避免重复执行脚本;
  • 支持多环境(开发、测试、生产)数据库同步,保证环境一致性;
  • 支持版本回滚(部分功能需商业版)、脚本冲突检测。

2. 核心概念

  • 迁移脚本(Migration Scripts):Flyway 执行的数据库 SQL 脚本(或 Java 代码),分为两种类型:
    • 「版本化迁移(Versioned Migrations)」:核心脚本,文件名格式为 V<版本号>__<描述>.sql双下划线分隔),例如 V1__Create_user_table.sqlV2__Add_user_age_column.sql,版本号唯一且递增,执行后不可修改(修改会导致项目启动报错)。
    • 「重复执行迁移(Repeatable Migrations)」:可选脚本,文件名格式为 R__<描述>.sql,例如 R__Init_system_config.sql,无版本号,每次项目启动都会重新执行(适合数据初始化、配置更新等场景)。
  • flyway_schema_history 表:Flyway 自动创建的历史记录表,用于存储已执行的迁移脚本信息(版本号、执行时间、是否成功、脚本内容摘要等),无需手动创建和维护。
  • 基线(Baseline):针对已有数据的数据库,可设置基线版本,Flyway 会忽略基线之前的脚本,仅执行基线之后的迁移脚本。

二、Java 项目(Spring Boot)整合 Flyway(核心实操)

Spring Boot 对 Flyway 提供了原生自动配置支持,整合步骤简洁,以下以「Maven + MySQL」为例(Gradle 类似)。

步骤 1:引入 Flyway 依赖

pom.xml中添加 Flyway 核心依赖和数据库驱动依赖(已存在数据库驱动可忽略):
<!-- Spring Boot Flyway 自动配置依赖(核心) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-flyway</artifactId>
    <!-- 版本可由Spring Boot父工程统一管理,如需指定可添加version标签,推荐与Spring Boot版本适配 -->
</dependency>

<!-- MySQL 驱动(需与你的MySQL版本适配,用户之前使用mysql-connector-java 8.0.28) -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
    <scope>runtime</scope>
</dependency>

步骤 2:配置 Flyway(application.yml/application.properties)

在 Spring Boot 配置文件中添加数据库连接和 Flyway 相关配置,Flyway 大部分配置有默认值,核心配置如下:
spring:
  # 1. 数据库连接配置(必须正确,Flyway依赖此连接操作数据库)
  datasource:
    url: jdbc:mysql://mysql-container:3306/your-database?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
    username: SecurityManager
    password: your-db-password
    driver-class-name: com.mysql.cj.jdbc.Driver
  # 2. Flyway 配置
  flyway:
    enabled: true # 开启Flyway(默认true,可省略)
    locations: classpath:db/migration # 迁移脚本存放路径(默认值,可省略,自定义路径需修改此处)
    baseline-on-migrate: false # 针对已有数据库,是否自动创建基线(后续详解)
    baseline-version: 1 # 基线版本号(默认1)
    encoding: UTF-8 # 脚本文件编码(默认UTF-8,推荐显式指定,避免中文注释乱码)
    out-of-order: false # 是否允许无序执行迁移脚本(默认false,推荐保持,保证版本递增顺序)
    validate-on-migrate: true # 项目启动时是否验证迁移脚本(默认true,检测脚本是否被修改、版本是否冲突)

步骤 3:创建迁移脚本目录并编写 SQL 脚本

  1. 创建默认脚本目录:在src/main/resources下,创建目录结构 db/migration(与配置中的locations对应),Flyway 会自动扫描该目录下的符合命名规范的 SQL 脚本。
  2. 编写版本化迁移脚本:

第一个脚本(版本 1):创建用户表,文件名 V1__Create_sys_user_table.sql

-- 注意:脚本编码为UTF-8,避免中文注释乱码
CREATE TABLE IF NOT EXISTS `sys_user` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `username` VARCHAR(50) NOT NULL COMMENT '用户名',
  `password` VARCHAR(100) NOT NULL COMMENT '加密密码',
  `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统用户表';

第二个脚本(版本 2):添加用户年龄字段,文件名 V2__Add_age_column_to_sys_user.sql

-- 给sys_user表添加age字段
ALTER TABLE `sys_user` 
ADD COLUMN `age` TINYINT(3) NULL DEFAULT 0 COMMENT '用户年龄' AFTER `password`;

(可选)编写重复执行迁移脚本:初始化默认用户,文件名 R__Init_default_admin_user.sql

-- 先删除已有默认管理员(避免重复插入),再插入
DELETE FROM `sys_user` WHERE `username` = 'admin';
INSERT INTO `sys_user` (`username`, `password`, `age`) 
VALUES ('admin', '$2a$10$7eS5l5y5e8GzLzWz9X8Y7U6V5T4R3E2W1Q0', 30);
关键注意点:
  • 版本号必须递增(可使用「1、2、3」或「1.0、1.1、2.0」格式,不可重复、不可跳跃);
  • 文件名分隔符:版本号与描述之间是双下划线__,描述中可使用单下划线_或连字符 - 分隔单词;
  • 版本化脚本执行成功后,不可修改(Flyway 会校验脚本摘要,修改后项目启动会报错)。

步骤 4:启动 Spring Boot 项目,验证 Flyway 执行结果

  1. 启动项目,观察控制台日志,会看到 Flyway 的执行日志,包含:
    • 连接数据库成功信息;
    • 创建flyway_schema_history表的信息;
    • 执行未执行的迁移脚本(V1、V2、R 脚本)的日志;
    • 迁移成功的提示(Successfully applied X migrations)。
  2. 登录 MySQL 数据库,验证结果:
    • 查看是否自动创建了flyway_schema_history表,查询该表可看到已执行的脚本记录(版本、脚本名、执行时间、状态等);
    • 查看sys_user表,确认表结构是否创建成功(包含 id、username、password、create_time、age 字段);
    • 查看sys_user表数据,确认默认管理员是否插入成功。

 

 

 

 

 

 

 

 

 

 

参考

豆包