如何为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
相关产品推荐
相关产品推荐

