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

如何为DEFAULT ON NULL创建自定义LiquiBase ChangeType?

在LiquiBase中实现Oracle的DEFAULT ON NULL功能

Oracle的DEFAULT ON NULL特性可以在显式插入NULL值时自动为列应用预设默认值,而LiquiBase原生并未提供对应的ChangeType——原生默认值仅在插入语句省略该列时生效,无法覆盖显式传入NULL的场景(比如Hibernate持久化设为null的实体时,会生成带NULL的插入语句)。

下面是实现自定义ChangeType的完整步骤,包含代码示例和注册方法:

1. 编写自定义Change类

继承LiquiBase的AbstractChange,实现生成Oracle专属SQL的逻辑:

import liquibase.change.AbstractChange;
import liquibase.change.ChangeMetaData;
import liquibase.change.DatabaseChange;
import liquibase.database.Database;
import liquibase.statement.SqlStatement;
import liquibase.statement.core.RawSqlStatement;

@DatabaseChange(
    name = "modifyColumnDefaultOnNull",
    description = "为Oracle列设置DEFAULT ON NULL属性",
    priority = ChangeMetaData.PRIORITY_DEFAULT
)
public class OracleDefaultOnNullChange extends AbstractChange {

    private String tableName;
    private String columnName;
    private String defaultValue;

    @Override
    public SqlStatement[] generateStatements(Database database) {
        // 仅针对Oracle数据库执行
        if (!"Oracle".equalsIgnoreCase(database.getDatabaseProductName())) {
            return new SqlStatement[0];
        }
        // 生成带转义的SQL,避免表名/列名含特殊字符
        String sql = String.format(
            "ALTER TABLE %s MODIFY %s DEFAULT ON NULL %s",
            database.escapeTableName(null, null, tableName),
            database.escapeColumnName(null, null, tableName, columnName),
            defaultValue
        );
        return new SqlStatement[]{new RawSqlStatement(sql)};
    }

    @Override
    public String getConfirmationMessage() {
        return String.format("已为列 %s.%s 设置DEFAULT ON NULL", tableName, columnName);
    }

    // 以下为属性的getter/setter
    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public String getColumnName() {
        return columnName;
    }

    public void setColumnName(String columnName) {
        this.columnName = columnName;
    }

    public String getDefaultValue() {
        return defaultValue;
    }

    public void setDefaultValue(String defaultValue) {
        this.defaultValue = defaultValue;
    }
}

2. 注册自定义ChangeType(可选,用于XML/YAML直接调用)

如果希望在changelog中像原生ChangeType一样直接使用标签,需要编写并注册ChangeParser:

编写ChangeParser类

import liquibase.change.Change;
import liquibase.change.parser.ChangeParser;
import liquibase.parser.core.xml.XMLChangeParser;
import org.xml.sax.Attributes;

public class OracleDefaultOnNullChangeParser extends XMLChangeParser {

    @Override
    protected Change createChange(Attributes attributes) {
        OracleDefaultOnNullChange change = new OracleDefaultOnNullChange();
        change.setTableName(attributes.getValue("tableName"));
        change.setColumnName(attributes.getValue("columnName"));
        change.setDefaultValue(attributes.getValue("defaultValue"));
        return change;
    }

    @Override
    public String getChangeName() {
        return "modifyColumnDefaultOnNull";
    }

    @Override
    public Class<? extends Change> getChangeClass() {
        return OracleDefaultOnNullChange.class;
    }
}

注册Parser

在项目的META-INF/services/liquibase.change.ChangeParser文件中添加一行:

com.your.package.OracleDefaultOnNullChangeParser

(替换为你实际的包路径)

3. 在Changelog中使用

方式一:使用自定义标签(需注册Parser)

<changeSet id="set_default_on_null" author="your-name">
    <modifyColumnDefaultOnNull 
        tableName="user_info" 
        columnName="status" 
        defaultValue="'ACTIVE'"/>
</changeSet>

方式二:使用customChange标签(无需注册Parser)

如果不想编写Parser,可以直接通过customChange调用自定义类:

<changeSet id="set_default_on_null" author="your-name">
    <customChange class="com.your.package.OracleDefaultOnNullChange">
        <param name="tableName" value="user_info"/>
        <param name="columnName" value="status"/>
        <param name="defaultValue" value="'ACTIVE'"/>
    </customChange>
</changeSet>

注意事项

  • defaultValue需要符合Oracle语法:字符串值加单引号,数字直接写,日期用TO_DATE('2024-01-01', 'YYYY-MM-DD')格式
  • 自定义Change会自动跳过非Oracle数据库的执行
  • 确保自定义类在LiquiBase的类路径中(比如Maven/Gradle中正确打包)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 16:22:42