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 到执行迁移、验证结果的完整工作流:
4.8 关键概念总结
| 概念 | 说明 | 本章示例 |
|---|---|---|
| ChangeLog | 数据库变更的清单文件,定义变更的顺序和分组 | db.changelog-master.xml |
| ChangeSet | 一个原子性的数据库变更,由 id + author 唯一标识 |
id="001" author="zhangsan" |
| 迁移命令 | liquibase update 将未应用的 ChangeSet 应用到数据库 |
创建 department 表 |
| 内部管理表 | Liquibase 自动维护 DATABASECHANGELOG 和 DATABASECHANGELOGLOCK |
记录变更历史,防止重复执行 |
💡 最佳实践:每个 ChangeSet 只包含一个逻辑变更(例如只创建一张表,或只添加一个字段),这样便于回滚、排查问题以及后续的版本差异分析。避免在一个 ChangeSet 中混合多个不相关的 DDL 操作。