4. 第一个迁移脚本:创建 ChangeLog 文件、编写第一个 ChangeSet(创建表)、执行迁移命令

本章是 Liquibase 实战的起点。我们将从零开始,创建一个数据库迁移项目,编写第一个 ChangeLog 文件,在其中定义第一个 ChangeSet(创建一张简单的表),然后通过命令行执行迁移,将变更应用到目标数据库。完成本章后,你将掌握 Liquibase 迁移的最小可行工作流。

4.1 准备工作:项目结构与 Liquibase 安装确认

在编写第一个迁移脚本之前,请确保你的环境中已安装 Liquibase 4.x 或更高版本,并且能够访问目标数据库(本文以 PostgreSQL 为例,但流程适用于 MySQL、Oracle、SQL Server 等)。

✅ 环境检查清单

  • Liquibase 已安装并可执行:liquibase --version
  • 数据库服务运行中,且存在可用的空数据库(例如 liquibase_demo)
  • 数据库 JDBC 驱动 JAR 文件已放置在 Liquibase 的 lib/ 目录或通过 --classpath 指定
  • 拥有数据库的写权限(CREATE TABLE、CREATE SEQUENCE 等)

推荐的项目目录结构如下:

liquibase-demo/
├── changelog/
│   └── db.changelog-master.xml    # 主 ChangeLog 文件
├── lib/
│   └── postgresql-42.7.1.jar      # JDBC 驱动
├── liquibase.properties           # 数据库连接配置(可选)
└── sql/                           # 后续可存放 SQL 格式的 ChangeSet

4.2 创建第一个 ChangeLog 文件

ChangeLog 是 Liquibase 迁移的入口文件,它使用 XML、YAML、JSON 或 SQL 格式描述所有数据库变更的顺序。我们选择最通用的 XML 格式,因为它支持最完整的 Liquibase 功能。

在 changelog/ 目录下创建 db.changelog-master.xml,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
    xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
                        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.23.xsd">

    <!-- 后续的 ChangeSet 将写在此处 -->

</databaseChangeLog>

💡 命名规范建议:主 ChangeLog 文件通常命名为 db.changelog-master.xml,后续的增量文件建议按时间或版本命名,例如 v1.0.0-changelog.xml、v1.1.0-changelog.xml,并通过 <include> 标签引入主文件。

4.3 编写第一个 ChangeSet:创建表

ChangeSet 是 ChangeLog 中的最小变更单元,每个 ChangeSet 包含一个原子性的数据库变更(如创建表、添加列、创建索引等),并且必须具有唯一的 id 和 author 属性。

我们在主 ChangeLog 中添加第一个 ChangeSet,用于创建一张 department(部门)表:

<databaseChangeLog ...>

    <changeSet id="001" author="zhangsan">
        <comment>创建部门表,用于存储组织架构信息</comment>
        <createTable tableName="department">
            <column name="id" type="BIGINT" autoIncrement="true">
                <constraints primaryKey="true" nullable="false"/>
            </column>
            <column name="name" type="VARCHAR(100)">
                <constraints nullable="false" unique="true"/>
            </column>
            <column name="code" type="VARCHAR(20)">
                <constraints nullable="false" unique="true"/>
            </column>
            <column name="parent_id" type="BIGINT">
                <constraints nullable="true"/>
            </column>
            <column name="status" type="SMALLINT" defaultValueNumeric="1">
                <constraints nullable="false"/>
            </column>
            <column name="created_at" type="TIMESTAMP" defaultValueComputed="CURRENT_TIMESTAMP">
                <constraints nullable="false"/>
            </column>
        </createTable>
    </changeSet>

</databaseChangeLog>

上述 ChangeSet 定义了一张包含 6 个字段的部门表,其中 id 为主键且自增,name 和 code 为唯一非空字段,parent_id 用于支持部门层级关系,status 默认值为 1,created_at 自动填充当前时间戳。

4.4 配置数据库连接

执行迁移前,需要告诉 Liquibase 连接哪个数据库。有两种常用方式:

方式 说明 示例
命令行参数 每次执行时通过 --url、--username、--password 指定 liquibase --url="jdbc:postgresql://localhost:5432/liquibase_demo" --username=postgres --password=secret update
属性文件 在项目根目录创建 liquibase.properties,持久化配置 见下方示例

推荐使用属性文件,避免每次输入冗长的参数。创建 liquibase.properties:

# 数据库连接
url: jdbc:postgresql://localhost:5432/liquibase_demo
username: postgres
password: secret

# ChangeLog 路径(相对于项目根目录)
changeLogFile: changelog/db.changelog-master.xml

# 数据库驱动类(通常可自动检测,但显式指定更可靠)
driver: org.postgresql.Driver

# Liquibase 内部使用的 schema(可选,默认与用户同名)
# liquibaseSchemaName: public

4.5 执行迁移命令

打开终端,进入项目根目录,执行以下命令:

liquibase update

如果一切配置正确,你将看到类似如下的输出:

Liquibase Community 4.23.0 by Liquibase
Starting Liquibase at 10:15:30 (version 4.23.0 #1234 built at 2024-01-15 12:00+0000)
Liquibase: Update has been successful. Applied 1 change(s) to database.

此时,数据库中已经创建了 department 表,同时 Liquibase 自动创建了两张内部管理表:DATABASECHANGELOG 和 DATABASECHANGELOGLOCK。

⚠️ 常见错误排查

  • 驱动未找到:确保 JDBC JAR 文件在 lib/ 目录或通过 --classpath 指定。
  • 连接超时:检查数据库服务是否启动、端口是否正确、防火墙是否放行。
  • 权限不足:确认数据库用户拥有 CREATE TABLE 和 CREATE SEQUENCE 权限。
  • ChangeLog 路径错误:检查 changeLogFile 相对于项目根目录的路径是否正确。

4.6 验证迁移结果

迁移成功后,可以通过数据库客户端或命令行验证表结构:

-- 查看 department 表结构
\d department

-- 查看 Liquibase 变更记录
SELECT id, author, filename, dateexecuted, orderexecuted, tag
FROM databasechangelog
ORDER BY dateexecuted;

查询 DATABASECHANGELOG 表将看到一条记录,记录了刚才执行的 ChangeSet 的 ID、作者、文件名、执行时间等信息。这为后续的版本回滚和差异分析提供了基础。

4.7 第一个迁移的完整流程示意图

下图展示了从编写 ChangeLog 到执行迁移、验证结果的完整工作流:

第一个 Liquibase 迁移工作流 1. 编写 ChangeLog db.changelog-master.xml 2. 定义 ChangeSet createTable department 3. 配置数据库连接 liquibase.properties 4. 执行迁移命令 liquibase update 5. 数据库变更 department 表创建 6. 记录元数据 DATABASECHANGELOG 表 ✅ 验证:\d department

4.8 关键概念总结

概念 说明 本章示例
ChangeLog 数据库变更的清单文件,定义变更的顺序和分组 db.changelog-master.xml
ChangeSet 一个原子性的数据库变更,由 id + author 唯一标识 id="001" author="zhangsan"
迁移命令 liquibase update 将未应用的 ChangeSet 应用到数据库 创建 department 表
内部管理表 Liquibase 自动维护 DATABASECHANGELOG 和 DATABASECHANGELOGLOCK 记录变更历史,防止重复执行

💡 最佳实践:每个 ChangeSet 只包含一个逻辑变更(例如只创建一张表,或只添加一个字段),这样便于回滚、排查问题以及后续的版本差异分析。避免在一个 ChangeSet 中混合多个不相关的 DDL 操作。