Xml 重新定义在包含的文件中仍然可见的本地液化属性

Xml 重新定义在包含的文件中仍然可见的本地液化属性,xml,liquibase,Xml,Liquibase,我的一些表实现了需要特定列的概念。我希望避免将这些列的变更集复制到所有相关表中,而是希望重用模板来创建实际的变更集 基于我在网上找到的不同想法,我尝试了以下方法: db/templates/0004创建有效期数据模板.xml <?xml version="1.1" encoding="UTF-8" standalone="no"?> <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchang

我的一些表实现了需要特定列的概念。我希望避免将这些列的变更集复制到所有相关表中,而是希望重用模板来创建实际的变更集

基于我在网上找到的不同想法,我尝试了以下方法:

db/templates/0004创建有效期数据模板.xml

<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<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.5.xsd">

    <include file="../templates/0002-create-versioned-data-template.xml" relativeToChangelogFile="true" />

    <changeSet author="${table.author}" id="Create ValidityPeriodData for ${table.name}" >
        <comment>Create columns of super class ValidityPeriodData for table ${table.name}</comment>
        <addColumn tableName="${table.name}" >
            <column name="valid_from" type="date" remarks="the earliest point in time when this entry is valid" />
            <column name="valid_until" type="date" remarks="the last point in time when this entry is valid" />
        </addColumn>
    </changeSet>

</databaseChangeLog>
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<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.5.xsd">

    <property name="table.name" value="login" />
    <property name="table.author" value="guess ;-)" />

    <include file="../templates/0004-create-validity-period-data-template.xml" relativeToChangelogFile="true" />

    <changeSet author="${table.author}" id="Create Credential table">
        <addColumn tableName="${table.name}">
            <column name="login_id" type="${uuid_type}"/>
            <column name="password" type="VARCHAR(255)">
                <constraints nullable="false"/>
            </column>
            <column name="salt" type="VARCHAR(128)"/>
        </addColumn>
        <addForeignKeyConstraint baseColumnNames="login_id"
                                 baseTableName="${table.name}"
                                 constraintName="fk_credential_of_login"
                                 onDelete="RESTRICT"
                                 onUpdate="RESTRICT"
                                 referencedColumnNames="id"
                                 referencedTableName="login"/>
    </changeSet>

</databaseChangeLog>

为表${table.name}创建超级类ValidityPeriodData的列
db/changelog/0017创建凭证表.xml

<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<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.5.xsd">

    <include file="../templates/0002-create-versioned-data-template.xml" relativeToChangelogFile="true" />

    <changeSet author="${table.author}" id="Create ValidityPeriodData for ${table.name}" >
        <comment>Create columns of super class ValidityPeriodData for table ${table.name}</comment>
        <addColumn tableName="${table.name}" >
            <column name="valid_from" type="date" remarks="the earliest point in time when this entry is valid" />
            <column name="valid_until" type="date" remarks="the last point in time when this entry is valid" />
        </addColumn>
    </changeSet>

</databaseChangeLog>
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<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.5.xsd">

    <property name="table.name" value="login" />
    <property name="table.author" value="guess ;-)" />

    <include file="../templates/0004-create-validity-period-data-template.xml" relativeToChangelogFile="true" />

    <changeSet author="${table.author}" id="Create Credential table">
        <addColumn tableName="${table.name}">
            <column name="login_id" type="${uuid_type}"/>
            <column name="password" type="VARCHAR(255)">
                <constraints nullable="false"/>
            </column>
            <column name="salt" type="VARCHAR(128)"/>
        </addColumn>
        <addForeignKeyConstraint baseColumnNames="login_id"
                                 baseTableName="${table.name}"
                                 constraintName="fk_credential_of_login"
                                 onDelete="RESTRICT"
                                 onUpdate="RESTRICT"
                                 referencedColumnNames="id"
                                 referencedTableName="login"/>
    </changeSet>

</databaseChangeLog>

问题

默认情况下,属性(table.name、table.author)是
global=“true”
,这意味着它们在所有变更集文件中都可见,但不能被覆盖/重新定义。因此,这只适用于单个表,这违背了目的。 如果我将它们声明为
global=“false”
,我可以为每个需要这些列的表重新定义它们,但是现在包含的文件看不到这些属性

问题


是否有一种方法可以重新定义或覆盖不同变更集文件的属性(如
global=“false”
所做的),但在包含的文件中,即使是递归的,它们的行为仍然像
global=“true”

我认为您对分解变更集的用法有误解

变更集应该是原子的,并且遵循“一个动作-一个变更集”的概念。它不应该是某种“可重用功能”。这种方法可能会损坏数据库模式。因此,不能删除旧的变更集

因此,我建议您为每个需要添加列的表编写变更集


另外,看看这篇文章:

背景

我看了一下liquibase的源代码。结果表明,当前的实现(在版本3.6.2、3.6.3、3.8.0中)工作起来有点奇怪

private ChangeLogParameter findParameter(String key, DatabaseChangeLog changeLog) {
    ChangeLogParameter result = null;

    List<ChangeLogParameter> found = new ArrayList<>();
    for (ChangeLogParameter param : changeLogParameters) {
        if (param.getKey().equalsIgnoreCase(key) && param.isValid()) {
            found.add(param);
        }
    }
    
    if (found.size() == 1) {
        // this case is typically a global param, but could also be a unique non-global param in one specific
        // changelog
        result = found.get(0);
    } else if (found.size() > 1) {
        for (ChangeLogParameter changeLogParameter : found) {
            if (changeLogParameter.getChangeLog().equals(changeLog)) {
                result = changeLogParameter;
            }
        }
    }
    
    return result;
}
private ChangeLogParameter findParameter(字符串键、数据库changeLog changeLog){
ChangeLogParameter结果=null;
找到的列表=新的ArrayList();
for(ChangeLogParameter参数:changeLogParameters){
if(param.getKey().equalsIgnoreCase(key)和¶m.isValid()){
找到。添加(参数);
}
}
if(find.size()==1){
//这种情况通常是一个全局参数,但也可能是一个特定环境中唯一的非全局参数
//变更日志
结果=找到。获取(0);
}else if(find.size()>1){
for(ChangeLogParameter ChangeLogParameter:已找到){
if(changeLogParameter.getChangeLog().equals(changeLog)){
结果=changeLogParameter;
}
}
}
返回结果;
}
您还需要知道,一旦解析了变更集,表达式就会展开。尚未读取的变更集中定义的参数无法考虑

因此,在第一次遇到参数时,它实际上会被处理,就像它是
global=true
一样,不管情况是否如此

将不会记录具有相同名称的第二个全局参数。但是,将记录第二个本地参数

一旦参数列表包含具有相同名称的第二个ChangeLogParameter,这些参数将以不同的方式展开。现在,它将查找在同一变更集文件中定义的该参数的上一个定义版本,但不管它是全局的还是本地的


回答

所以来回答我自己的问题。liquibase的当前实现不支持这种事情。除此之外,它在扩展表达式方面的行为有些不一致


解决方案?

我向liquibase提交了一份bug报告,并在GitHub上提供了一个可能的漏洞

编辑:
此更改已包含在3.10.2版中。然而,请注意,我无意中引入了一个突破性的变化。这对于新项目并不重要,但如果已经使用了变量,则可能会破坏现有项目。本期中建议了一种解决方法。

我正在为每个表编写变更集(如果你真的看我的示例,你会看到),但正如我在JAVA中将公共内容放入抽象超类中一样,我想将表的公共部分的创建放在“超级变更集”中,复制相同的代码,在我的书中,反复使用相同的变更集更容易出错模板确实为它所使用的每个表创建了一个原子变更集,每个表都有其基于表的ID。name属性值,我看不到任何东西会打破Liquibaseies的基本概念,我明白你的想法,但我认为使用liquibase是不可行的。至少,这超出了我的专业范围。