下载工作台
Java 数据库实战

Flyway 迁移与种子数据

试读上半部分 · 解锁后可读全文

第 12 章 · Flyway 迁移与种子数据

本章目标:在 shop-db 中集成 Flyway;编写 V1__init.sql 迁移 ch07 完整 DDL;配置 application 或 Maven 插件 执行 migrate;编写 幂等种子数据 Java/SQL 脚本;理解 validate + Flyway 与 JPA 协作;对照 python-database ch11 Alembic 工作流异同。

学时建议:5~6 小时(含 2 小时迁移跟练)

前置:完成 java-database ch07(DDL 基线)与 ch10(JPA validate);了解 python-database ch11(Alembic)。


12.1 场景说明:schema 必须可版本化

痛点手工 SQLFlyway
多人改表冲突难以合并db/migration/V*.sql 可 code review
生产升级手工执行易漏flyway migrate
回滚无标准社区版靠补偿脚本;或 undo(Teams)
与 JPA 同步易漂移Flyway 建表 + JPA validate

shop-db 演进示例:

  1. V1:ch07 六表 + 购物车
  2. V2:ch13 增加 tags / product_tags(练习)
  3. V3products 增加 cover_url(练习)
对照 python-database ch11 Alembic:db-demo 用 autogenerate 对比 ORM metadata;shop-db 用 手写 SQL 迁移(Java 生态常见,与 Spring Boot 默认一致)。

12.2 Flyway 与 Alembic 概念对照

概念Flyway (Java)Alembic (Python)
版本表flyway_schema_historyalembic_version
脚本位置db/migration/V1__xxx.sqlalembic/versions/*.py
执行命令flyway migratealembic upgrade head
回滚手写 V{n+1} 补偿downgrade -1
自动生成无(手写 SQL)revision --autogenerate
Spring 集成spring.flyway.*需手动/FastAPI 启动钩子

共同点:版本链单调递增;禁止修改已发布到 main 的历史脚本


12.3 Maven 集成 Flyway

pom.xml

<properties>
    <flyway.version>10.10.0</flyway.version>
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-maven-plugin</artifactId>
            <version>${flyway.version}</version>
            <configuration>
                <url>jdbc:mysql://127.0.0.1:3306/shop_db?useSSL=false&amp;serverTimezone=Asia/Shanghai</url>
                <user>shop_user</user>
                <password>shop_pass</password>
                <locations>
                    <location>classpath:db/migration</location>
                </locations>
            </configuration>
        </plugin>
    </plugins>
</build>

目录结构

~/learn-java/shop-db/
├── src/main/resources/db/migration/
│   ├── V1__init.sql
│   └── V2__add_tags.sql          # 练习,可选
├── src/main/resources/db/seed/
│   └── R__seed_shop.sql          # Repeatable 种子(可选)
└── pom.xml
前缀含义
V{version}__{description}.sql版本化迁移,只执行一次
R__{description}.sql可重复执行(checksum 变则重跑)
U{version}__Undo(Flyway Teams)

12.4 V1__init.sql 完整 DDL

将 ch07 §7.4~§7.8 合并为 V1__init.sql

-- V1__init.sql
-- shop-db baseline schema (java-database ch07/ch12)
-- charset: utf8mb4, engine: InnoDB

CREATE TABLE IF NOT EXISTS categories (
    id          BIGINT       NOT NULL AUTO_INCREMENT,
    name        VARCHAR(64)  NOT NULL,
    slug        VARCHAR(64)  NOT NULL,
    sort_order  INT          NOT NULL DEFAULT 0,
    created_at  DATETIME(3)  NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
    updated_at  DATETIME(3)  NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
                    ON UPDATE CURRENT_TIMESTAMP(3),
    PRIMARY KEY (id),
    UNIQUE KEY uk_categories_slug (slug),
    KEY idx_categories_sort (sort_order, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS products (
    id            BIGINT        NOT NULL AUTO_INCREMENT,
    category_id   BIGINT        NOT NULL,
    title         VARCHAR(128)  NOT NULL,
    slug          VARCHAR(128)  NOT NULL,
    description   TEXT          NULL,
    price         BIGINT        NOT NULL COMMENT '单价,单位:分',
    stock         INT           NOT NULL DEFAULT 0,
    is_published  TINYINT(1)    NOT NULL DEFAULT 0,
    created_at    DATETIME(3)   NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
    updated_at    DATETIME(3)   NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
                      ON UPDATE CURRENT_TIMESTAMP(3),
    PRIMARY KEY (id),
    UNIQUE KEY uk_products_slug (slug),
    KEY idx_products_category_published (category_id, is_published, created_at DESC),
    KEY idx_products_published_price (is_published, price),
    CONSTRAINT fk_products_category
        FOREIGN KEY (category_id) REFERENCES categories(id)
        ON DELETE RESTRICT ON UPDATE CASCADE,
    CONSTRAINT chk_products_price CHECK (price >= 0),
    CONSTRAINT chk_products_stock CHECK (stock >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- users, orders, order_lines, carts, cart_items 同 ch07,此处省略以节省篇幅
-- 跟练时必须写全 7 张表
跟练要求V1__init.sql 必须包含 ch07 全部 7 表,不得省略 users/orders/order_lines/carts/cart_items

与 ch07 shop_db.sql 关系

文件用途
ch07 schema/shop_db.sql学习 DDL、手动执行
ch12 V1__init.sql版本化权威来源,Flyway 执行

内容应一致;后续只改 V2__ 增量,不改 V1__(已发布则禁止改)。


12.5 执行迁移

cd ~/learn-java/shop-db

# 确保空库或仅 flyway 表
mysql -h 127.0.0.1 -u shop_user -pshop_pass -e "CREATE DATABASE IF NOT EXISTS shop_db;"

# Maven 插件
mvn -q flyway:migrate

# 验证
mysql -h 127.0.0.1 -u shop_user -pshop_pass shop_db -e "SHOW TABLES;"
mysql -h 127.0.0.1 -u shop_user -pshop_pass shop_db \
  -e "SELECT installed_rank, version, description, success FROM flyway_schema_history;"
命令作用
flyway:migrate应用未执行版本
flyway:info查看 pending/applied
flyway:validate校验 checksum
flyway:clean删库全部对象,仅 dev!

12.6 纯 Java 启动 Flyway(无 Maven 插件)

package com.example.shopdb.flyway;

import org.flywaydb.core.Flyway;
import javax.sql.DataSource;
import com.example.shopdb.pool.HikariDataSourceFactory;

public class FlywayMigrator {

    public static void migrate() {
        DataSource ds = HikariDataSourceFactory.create();
        Flyway flyway = Flyway.configure()
            .dataSource(ds)
            .locations("classpath:db/migration")
            .load();
        flyway.migrate();
    }

    public static void main(String[] args) {
        migrate();
        System.out.println("Flyway migrate 完成");
    }
}

Maven 依赖:

<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
    <version>10.10.0</version>
</dependency>
<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-mysql</artifactId>
    <version>10.10.0</version>
</dependency>

启动顺序(shop-db 应用):

1. Flyway.migrate()     → 表结构最新
2. JPA EMF validate     → 实体与表一致
3. 业务逻辑              → Repository / EntityManager
4. (可选)SeedRunner    → 种子数据

以下内容需解锁后阅读

试读已结束。解锁本章 ¥5.00,或开通年度会员畅读全部教程。
年度会员 ¥199.00/年; 小紫 AI 工作台有效会员 ¥99.00/年

正文仅在服务端鉴权后下发,未付费无法获取下半部分内容。