You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用mvn liquibase:diff时禁用表列删除及实现数据迁移的方案咨询

当然可行!而且这是用Liquibase管理生产环境数据库变更时的标准最佳实践——先迁移数据,再清理旧结构。针对你的场景,我给你梳理几个具体的实现技巧,同时纠正下你之前可能踩的使用误区:

1. 先让Liquibase别自动生成删除语句

你的核心痛点是liquibase:diff会直接生成删列的changeSet,所以第一步要修改插件配置,禁用自动删除的diff类型。在pom.xml的Liquibase插件配置里加这些参数:

<plugin>
  <groupId>org.liquibase</groupId>
  <artifactId>liquibase-maven-plugin</artifactId>
  <version>3.4.1</version>
  <configuration>
    <!-- 你的数据库连接、changelog路径等原有配置 -->
    <diffChangeLogFile>src/main/resources/db/changelog/changelog-diff.xml</diffChangeLogFile>
    <!-- 直接排除删除类的变更生成 -->
    <diffExcludeObjects>dropTable,dropColumn</diffExcludeObjects>
    <!-- 或者更严格:只允许生成新增/修改类的变更 -->
    <diffTypes>createTable,addColumn,modifyDataType,addForeignKeyConstraint</diffTypes>
  </configuration>
</plugin>

这样再跑mvn liquibase:diff,只会生成创建phone表、给person加phone_id外键这些新增结构的变更,不会碰旧的phoneNumber列。

2. 把变更拆成三个明确的阶段执行

你之前想拆分changeLog的思路完全正确,只是要按执行顺序来组织:

  • 阶段1:搭好新结构:先运行上面生成的diff changeLog,创建phone表和person的关联字段。这一步只做结构新增,不碰旧数据和旧列。
  • 阶段2:手动写数据迁移的changeSet:这一步是核心,你需要自己编写SQL把person.phoneNumber的数据迁移到phone表,同时关联person和phone的关系。比如:
<changeSet id="migrate-person-phone-data" author="your-team">
  <!-- 用原生SQL更灵活,适合复杂迁移场景 -->
  <sql>
    -- 先给每个有手机号的Person插入对应的Phone记录
    INSERT INTO phone (phone_number)
    SELECT phone_number FROM person WHERE phone_number IS NOT NULL;
    
    -- 关联Person和Phone(这里假设Phone的id是自增主键,根据你的实际情况调整)
    UPDATE person p
    JOIN phone ph ON p.phone_number = ph.phone_number
    SET p.phone_id = ph.id;
  </sql>
</changeSet>
  • 阶段3:清理旧结构:等数据迁移验证无误后,再手动写删除person.phoneNumber列的changeSet,或者临时放开diff的删除限制生成语句,执行清理。

3. 结合Spring Boot的自动执行逻辑

Spring Boot会自动执行db/changelog/db.changelog-master.xml里的所有changeSet,所以你可以把三个阶段的文件按顺序引入:

<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-3.4.xsd">
  <!-- 先跑新增结构的变更 -->
  <include file="changelog-diff.xml"/>
  <!-- 再跑数据迁移 -->
  <include file="changelog-migrate-phone-data.xml"/>
  <!-- 最后清理旧列(先注释,验证没问题再打开) -->
  <!-- <include file="changelog-clean-old-phone-column.xml"/> -->
</databaseChangeLog>

这样启动Spring Boot应用时,Liquibase会按顺序执行前两个阶段,等你确认数据没问题后,再把第三阶段的注释去掉,重新启动执行清理。

4. 纠正你的使用误区

liquibase:diff是辅助工具,不是万能的自动生成器——它只能帮你生成结构变更,但涉及数据迁移的场景,必须手动编写对应的changeSet。你之前想拆分创建和删除到不同文件的思路是对的,但核心是要控制执行顺序:先搭新结构,再迁数据,最后删旧结构,而不是单纯按变更类型拆分文件。

最后给你梳理下针对示例场景的完整流程:

  1. 写完v2的Person和Phone实体;
  2. 跑mvn liquibase:diff生成新增结构的changeLog;
  3. 手动编写数据迁移的changeSet;
  4. 启动Spring Boot,Liquibase自动执行前两个阶段;
  5. 验证数据迁移正确后,添加删除旧列的changeSet,再次启动完成清理。

这样就能完美实现你想要的“先迁数据再删旧列”的需求了!

内容的提问来源于stack exchange,提问作者MatthieuBlm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:28:06