Spring Boot整合Flyway

一、前言

一般在我们开发项目的时候经常会更新数据库表的字段,如果同事 a 添加了表字段,没有及时给同事 b sql 脚本,可能同事 b 的代码运行就会报错,而且随着时间的推移,sql 脚本越来越多,项目上线的时候整理起来就很费时间,所以就有大佬级别的人物创造了 Flyway 这个数据库版本管理工具。Flyway 是一款开源的数据库版本管理工具,它更倾向于规约优于配置的方式。Flyway 可以独立于应用实现管理并跟踪数据库变更,支持数据库版本自动升级,并且有一套默认的规约,不需要复杂的配置,Migrations 可以写成 SQL 脚本,也可以写在 Java 代码中,不仅支持 Command Line 和 Java API,还支持 Build 构建工具和 Spring Boot 等,同时在分布式环境下能够安全可靠地升级数据库,同时也支持失败恢复等。

二、Flyway介绍

2.1 主要特性

1.普通 SQL:纯 SQL 脚本(包括占位符替换)没有专有的XML格式,没有锁定

2.无限制:使用 Java 代码来进行一些高级数据操作

3.零依赖:只需运行在 Java6(及以上)和数据库所需的 JDBC 驱动

4.约定优于配置:迁移时,自动查找系统文件和类路径中的 SQL 文件或 Java 类

5.高可靠性:在集群环境下进行数据库升级是安全可靠的

6.云支持:完全支持 Microsoft SQL Azure, Google Cloud SQL & App Engine、Heroku Postgres 和 Amazon RDS

7.自动迁移:使用 Flyway 提供的 API,让应用启动和迁移同时工作

8.快速失败:损坏的数据库或失败的迁移可以防止应用程序启动

9.数据库清理:在一个数据库中删除所有的表、视图、触发器,而不是删除数据库本身

2.2 运行原理

当 Flyway 连接数据库中的 schema 后,会先检查是否已存在 flyway_schema_history 表,如果没有则创建。该表用于跟踪数据库的状态,如数据迁移的版本,迁移成功状态等信息。

当 flyway_schema_history 存在后,Flyway 会扫描文件系统或应用中的 classpath 目录的数据迁移文件,然后根据它们的版本号进行按序迁移,如下图:

由于 flyway_schema_history 表中记录了迁移的版本号,如果文件的版本号小于或等于标记为当前版本的版本号,则忽略它们不执行。

在实际使用中,flyway有两种方式执行,一种是构建项目的时候执行,一种是项目启动的时候执行。

上边描述的内容或许对读者来说还不够直观,那么下面我们就开始进行实战演练。

三、构建实战

环境:

mysql-5.7.30

springboot 2.3.5.RELEASE

新建一个 Maven 项目。

3.1 添加依赖

xml 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-core</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

注意:如果构件项目的时候执行Flyway,那么就必须引入spring-boot-starter-jdbc依赖。

3.2 配置数据迁移文件

在项目的 src/main/resources 下创建 db/migration 目录,该目录下放置需要数据迁移的文件。

数据迁移文件默认名称格式为:Vversion__name.sql。

注意:名称中version和name之间是两个下划线!

本次测试新建名为 V0.1.0__init_table.sql 的文件,内容如下:

sql 复制代码
USE FLYWAYDB;
DROP TABLE IF EXISTS user;

CREATE TABLE user
(
    id BIGINT(20) NOT NULL COMMENT '主键ID',
    name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
    age INT(11) NULL DEFAULT NULL COMMENT '年龄',
    email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
    PRIMARY KEY (id)
);

我们再新建一个名为 V0.1.1__init_data.sql 文件,内容如下:

sql 复制代码
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

版本 1 数据迁移的内容是创建一张 user 表。

3.3 配置application.yml

yml 复制代码
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/flywaydb?createDatabaseIfNotExist=true&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
    username: root
    password: 123456
  flyway:
    enabled: true  # 禁止清理数据库表
    table: flywayinit #修改原数据表名,默认为schema_version

编译项目结果如下图:

图中,数据库 flywaydb 中创建了 flywayinit 表和 user 表,数据成功迁移到指定数据库中。

当系统升级时又需要做数据迁移,我们只需在 db/migration 目录下再放置新版本的 sql 文件即可。

版本 0.1.1 的数据迁移内容是往 user 表中插入 3 条数据。

上面我们在application.yml配置了flyway初始化的数据库,其实也可以配置好多相关参数,具体如下:

配置项 含义
flyway.baseline-description 对执行迁移时基准版本的描述.
flyway.baseline-on-migrate 当迁移时发现目标schema非空,而且带有没有元数据的表时,是否自动执行基准迁移,默认false.
flyway.baseline-version 开始执行基准迁移时对现有的schema的版本打标签,默认值为1.
flyway.check-location 检查迁移脚本的位置是否存在,默认false.
flyway.clean-on-validation-error 当发现校验错误时是否自动调用clean,默认false.
flyway.enabled 是否开启flywary,默认true.
flyway.encoding 设置迁移时的编码,默认UTF-8.
flyway.ignore-failed-future-migration 当读取元数据表时是否忽略错误的迁移,默认false.
flyway.init-sqls 当初始化好连接时要执行的SQL.
flyway.locations 迁移脚本的位置,默认db/migration.
flyway.out-of-order 是否允许无序的迁移,默认false.
flyway.password 目标数据库的密码.
flyway.placeholder-prefix 设置每个placeholder的前缀,默认${.
flyway.placeholder-replacementplaceholders 是否要被替换,默认true.
flyway.placeholder-suffix 设置每个placeholder的后缀,默认}.
flyway.placeholders.placeholder name 设置placeholder的value
flyway.schemas 设定需要flywary迁移的schema,大小写敏感,默认为连接默认的schema.
flyway.sql-migration-prefix 迁移文件的前缀,默认为V.
flyway.sql-migration-separator 迁移脚本的文件名分隔符,默认__
flyway.sql-migration-suffix 迁移脚本的后缀,默认为.sql
flyway.table flyway使用的元数据表名,默认为schema_version
flyway.target 迁移时使用的目标版本,默认为latest version
flyway.url 迁移时使用的JDBC URL,如果没有指定的话,将使用配置的主数据源
flyway.user 迁移数据库的用户名
flyway.validate-on-migrate 迁移时是否校验,默认为true.

四、启动方式实践

4.1 引入依赖

xml 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-core</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

4.2 修改application.yml

yml 复制代码
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/flywaydb?createDatabaseIfNotExist=true&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
    username: root
    password: 123456

4.3 编码

创建配置类FlywayConfig.java

java 复制代码
@Configuration
public class FlywayConfig {

    @Value("${spring.datasource.url}")
    private String url;

    @Value("${spring.datasource.username}")
    private String username;

    @Value("${spring.datasource.password}")
    private String password;

    @PostConstruct
    public void migrate() {
        Flyway flyway = Flyway.configure().dataSource(url, username, password).table("flyway_init_table").load();

        // 创建 flyway_schema_history 表
        //flyway.baseline();

        // 删除 flyway_schema_history 表中失败的记录
        //flyway.repair();

        // 检查 sql 文件
        //flyway.validate();

        // 执行数据迁移
        flyway.migrate();

        // 删除当前 schema 下所有表
        //flyway.clean();
    }
}

在构建flyway的时候,构件方法和配置中的配置项类似。

4.4 启动测试

启动项目,结果如下图:

相关推荐
vx_Biye_Design1 小时前
springboot旅游管理系统18006-计算机课程设计、毕业设计
java·spring boot·后端·python·elasticsearch·django·课程设计
Wang's Blog1 小时前
Java 中间件之 RabbitMQ 快速入门: 简单队列模型快速入门
java·中间件·java-rabbitmq
IT_陈寒1 小时前
为什么我的React组件一直在意外重渲染?
前端·人工智能·后端
骇客野人1 小时前
Java 开发组件大全覆盖后端主流技术栈(基础、Web、ORM、中间件、微服务、安全、工具、测试、运维、信创适配常用组件)
java·前端·中间件
EatFan2 小时前
2026 Rust 后端技术栈选型:Axum 0.8 + Tokio + SQLx 全链路怎么搭
开发语言·后端·rust·tokio·serde·axum·sqlx
2401_888859712 小时前
STM32H733 MPU、AXI、FMC学习
java·开发语言·stm32·spring
mldong2 小时前
审批详情页高亮的那个节点,"名字"其实是一串 id:jeeflow 工作流引擎的四块数据来源
后端·架构
高频因子挖掘机2 小时前
股票历史数据缺了一天怎么发现?用 Pandas 检查交易日期连续性
后端·github·api
高频因子挖掘机2 小时前
量化回测最危险的错误,不是程序报错,而是数据错了却正常运行
后端·github·api