Вопрос или проблема
В базе данных Oracle есть опция DEFAULT ON NULL, но в LiquiBase нет типа изменения для этого. LiquiBase позволяет задать значение по умолчанию для столбца, но это значение используется только в том случае, если оно пропущено в операторе вставки. Если вы сохраняете сущность Hibernate, у которой свойство установлено в null, генерируется оператор вставки, который явно устанавливает поле в null, и значение по умолчанию не применяется. Значения DEFAULT ON NULL используются всякий раз, когда в этот столбец сохраняется null, даже если оно явно задано оператором вставки.
Вы можете установить столбец Oracle на DEFAULT ON NULL с помощью SQL, как в следующем примере:
ALTER TABLE tableName
MODIFY columnName DEFAULT ON NULL ‘someString’;
Но мне нужно сделать так, чтобы это работало с LiquiBase. Поэтому я рассматриваю классы, которые расширяют AbstractChange и реализуют SqlStatement, а также JavaDoc для CustomSqlChange и связанных классов. Но в JavaDoc в основном просто перечислены названия методов и типы параметров/возвращаемых значений. Я ищу информацию и примеры о том, как зарегистрировать тип изменения и корректно выполнить необходимый SQL.
Ответ или решение
Создание собственного типа изменений в LiquiBase для установки DEFAULT ON NULL в Oracle может быть выполнено следующим образом. Мы будем настраивать класс, который будет расширять AbstractChange
и реализовать интерфейс SqlStatement
. Вот подробная инструкция:
Шаг 1: Создание класса изменения
- Создайте новый класс, расширяющий
AbstractChange
:
import liquibase.change.AbstractChange;
import liquibase.change.ChangeMetaData;
import liquibase.change.CustomSqlChange;
import liquibase.database.Database;
import liquibase.exception.DatabaseException;
import liquibase.exception.ValidationErrors;
import liquibase.statement.SqlStatement;
public class DefaultOnNullChange extends AbstractChange {
private String tableName;
private String columnName;
private String defaultValue;
public DefaultOnNullChange() {
super("DEFAULT_ON_NULL", "Set DEFAULT ON NULL");
this.setChangeMetaData(new ChangeMetaData("your_label_name"));
}
@Override
public SqlStatement[] generateStatements(Database database) {
String sql = String.format("ALTER TABLE %s MODIFY %s DEFAULT ON NULL '%s'",
tableName, columnName, defaultValue);
return new SqlStatement[]{new CustomSqlStatement(sql)};
}
@Override
public ValidationErrors validate(Database database) {
ValidationErrors errors = new ValidationErrors();
if (tableName == null || tableName.isEmpty()) {
errors.addError("tableName is required");
}
if (columnName == null || columnName.isEmpty()) {
errors.addError("columnName is required");
}
if (defaultValue == null) {
errors.addError("defaultValue is required");
}
return errors;
}
// Геттеры и сеттеры для tableName, columnName и defaultValue
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: Регистрация типа изменения
- Зарегистрируйте свой класс изменения в
liquibase.change.ChangeFactory
:
import liquibase.change.Change;
import liquibase.change.ChangeFactory;
public class CustomLiquibaseChange {
public static void registerChange() {
ChangeFactory.getInstance().addChangeType("defaultOnNull", DefaultOnNullChange.class);
}
}
Шаг 3: Использование вашего типа изменений в XML
- Используйте ваш новый тип изменений в файле изменений LiquiBase:
<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.8.xsd">
<changeSet id="1" author="ваш_имя">
<defaultOnNull tableName="tableName" columnName="columnName" defaultValue="someString"/>
</changeSet>
</databaseChangeLog>
Шаг 4: Компиляция и запуск
- Скомпилируйте свой класс и убедитесь, что он находится в пути классов приложения. Запустите вашу миграцию LiquiBase, и ваша команда должна выполниться, установив
DEFAULT ON NULL
для указанного столбца.
Заключение
Теперь у вас есть полноценное изменение в LiquiBase, которое позволяет установить DEFAULT ON NULL
для столбца в Oracle. Убедитесь, что вы протестировали это в безопасной среде перед развертыванием в продуктивную.