关于 liquibase-migration
面向 FOLIO 模块开发者的 Liquibase 迁移技能,涵盖变更日志布局、变更集命名、架构约定和常见迁移模式。
主要功能
- 01版本化变更日志布局指南
- 02变更集 ID 命名规则
- 03变更集注释要求
- 04FOLIO 列类型约定
- 05常见架构与数据变更模式
- 06迁移反模式说明
适用场景
- 01为 FOLIO 模块添加架构变更
- 02为新的 Liquibase 变更集命名
- 03为数据库列选择标准类型
- 04检查迁移结构和变更集范围
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ folio-org/ folio-eureka-ai-dev --skill liquibase-migration安装后在 Claude Code 中输入/liquibase-migration确认已加载。
详细介绍
FOLIO Liquibase 迁移指南
1. 文件夹结构
首选布局
首选结构采用版本化布局——每个发行版本都有自己的文件夹和聚合文件:
src/main/resources/db/changelog/
├── changelog-master.xml
└── changes/
├── changelog-v1.0.xml
├── v1.0/
│ ├── create-table-foo.xml
│ └── add-index-foo-bar.xml
├── changelog-v2.0.xml
└── v2.0/
└── alter-table-foo-add-column-baz.xml
首选结构规则:
changelog-master.xml仅包含版本聚合文件(changes/changelog-vX.Y.xml)- 每个
changelog-vX.Y.xml仅包含changes/vX.Y/中的文件 - 每次模块发行都创建新的
vX.Y/目录和changelog-vX.Y.xml - 所有
<include>元素都使用relativeToChangelogFile="true"
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
https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
<include file="/changes/changelog-v1.0.xml" relativeToChangelogFile="true"/>
<include file="/changes/changelog-v2.0.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
changes/changelog-v2.0.xml 示例:
<databaseChangeLog ...>
<include file="/changes/v2.0/create-table-foo.xml" relativeToChangelogFile="true"/>
<include file="/changes/v2.0/alter-table-foo-add-column-bar.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
使用现有模块
创建新文件前,请检查模块中现有的变更日志结构。始终遵循当前使用的布局——不要在项目中途重新组织结构或引入不同的结构。
- 如果模块使用带有按版本划分的聚合文件的
changelog-master.xml,则遵循该模式 - 如果模块使用带有直接
<include>条目的扁平changelog-master.xml,则继续直接在其中添加条目 - 如果模块使用不同的命名或嵌套方式,则与现有结构保持一致
对于没有现有迁移记录的全新模块,请使用上述首选结构。
2. Changeset ID 命名约定
格式
<JIRA-TICKET>@@<scope>-<action>-<target>[-<detail>]
允许的值
| 部分 | 值 |
|---|---|
| scope | schema、data、refactor、fix |
| action | create、alter、drop、rename、migrate、backfill、seed、cleanup、enforce |
| target | table-<name>、column-<table>-<col>、index-<name>、fk-<from>-to-<to>、type-<name> |
| detail | (可选) 具体意图,例如 add-not-null、add-metadata-fields |
风格规则
- 仅使用小写字母
- 仅使用 kebab-case(不使用下划线或空格)
- 仅使用 ASCII 字符——不使用
:字符 - 使用祈使动词(不要使用动名词或过去时)
- 发行后 ID 不可更改——绝不要重命名已发行的 changeset ID
✅ 正确示例
MYMOD-101@@schema-create-table-item
MYMOD-102@@schema-alter-table-item-add-column-status
MYMOD-103@@schema-create-index-item-status
MYMOD-104@@schema-create-fk-item-to-location
MYMOD-105@@data-seed-item-default-status
MYMOD-106@@data-migrate-rule-to-specification-rule-metadata-fields
MYMOD-107@@schema-enforce-column-item-id-not-null
MYMOD-108@@schema-create-type-status-enum
❌ 错误示例
MYMOD-101@@CreateItemTable # PascalCase, no scope/action
MYMOD-101@@schema:create:table # colons not allowed
MYMOD-101@@schema-creating-table # gerund
MYMOD-101@@schema-created-table # past tense
item-table # missing JIRA ticket and @@
3. Changeset 结构
每个 changeset 必须包含:
<comment>— 描述该 changeset 的作用及原因
<changeSet id="MYMOD-42@@schema-create-table-item" author="john_doe">
<comment>Create item table for inventory storage</comment>
<createTable tableName="item">
...
</createTable>
</changeSet>
4. FOLIO 标准列类型
在所有 FOLIO 模块中统一使用以下类型:
| 用途 | 类型 |
|---|---|
| 主键 / 外键(UUID) | uuid |
| 短字符串 | varchar(36) – varchar(250) |
| 长字符串 | varchar(2500) 或 text |
| JSON 数据块 | jsonb |
| 时间戳 | datetime |
| 布尔标记 | bool |
| 版本计数器(乐观锁) | integer |
| 单字符代码 | char |
元数据列
向新表添加元数据列之前,请询问用户是否需要这些列。并非所有表都需要审计跟踪。
如果用户确认,请包含:
<column name="created_date" type="DATETIME">
<constraints nullable="false"/>
</column>
<column name="updated_date" type="DATETIME">
<constraints nullable="false"/>
</column>
<column name="created_by_user_id" type="uuid">
<constraints nullable="false"/>
</column>
<column name="updated_by_user_id" type="uuid">
<constraints nullable="false"/>
</column>
5. 常见变更模式
创建表
<changeSet id="MYMOD-10@@schema-create-table-item" author="jane_doe">
<comment>Create item table</comment>
<createTable tableName="item">
<column name="id" type="UUID">
<constraints nullable="false" primaryKey="true" primaryKeyName="pk_item"/>
</column>
<column name="barcode" type="varchar(250)"/>
<column name="status" type="varchar(36)">
<constraints nullable="false"/>
</column>
<column name="data" type="jsonb"/>
<column name="_version" type="integer"/>
<column name="created_date" type="DATETIME"><constraints nullable="false"/></column>
<column name="updated_date" type="DATETIME"><constraints nullable="false"/></column>
<column name="created_by_user_id" type="uuid"><constraints nullable="false"/></column>
<column name="updated_by_user_id" type="uuid"><constraints nullable="false"/></column>
</createTable>
</changeSet>
添加外键
<changeSet id="MYMOD-10@@schema-create-fk-item-to-location" author="jane_doe">
<comment>Add FK from item to location</comment>
<addForeignKeyConstraint
baseTableName="item"
baseColumnNames="location_id"
referencedTableName="location"
referencedColumnNames="id"
constraintName="fk_item_location_id"/>
</changeSet>
创建索引
<changeSet id="MYMOD-11@@schema-create-index-item-status" author="jane_doe">
<comment>Create B-tree index on item.status for lookup performance</comment>
<createIndex tableName="item" indexName="idx_item_status">
<column name="status"/>
</createIndex>
</changeSet>
添加列
<changeSet id="MYMOD-15@@schema-alter-table-item-add-column-effective-location-id" author="jane_doe">
<comment>Add effective_location_id column to item table</comment>
<addColumn tableName="item">
<column name="effective_location_id" type="UUID"/>
</addColumn>
</changeSet>
数据迁移 / 种子数据
<changeSet id="MYMOD-20@@data-seed-item-default-status" author="jane_doe">
<comment>Set default status 'Available' for items with null status</comment>
<sql>
UPDATE item
SET status = 'Available'
WHERE status IS NULL;
</sql>
</changeSet>
6. 应避免的反模式
❌ 缺少注释 — 审阅者或未来的开发者无法了解上下文
<changeSet id="MYMOD-2@@schema-alter-table-item-add-column-bar" author="foo">
<addColumn tableName="item">...</addColumn>
</changeSet>
❌ 重命名已发布的 changeset ID — 会导致所有已部署环境中的 Liquibase 校验和验证失败
❌ 在一个 changeset 中包含多个不相关的更改 — 会增加回滚和调试的难度;每个 changeset 只包含一项逻辑更改
❌ 在架构 changeset 中使用 runOnChange="true" — 仅适用于存储过程/视图,绝不适用于 DDL
评论
支持 Markdown