How can I populate Liquibase parameter values from

2020-07-18 05:25发布

问题:

Is there any way that I can populate parameters in a Liquibase changelog file based on the contents of an external property file?

As in, I would like to be able to say:

<createTable tableName="${table.name}">
     <column name="id" type="int"/>
     <column name="${column1.name}" type="varchar(${column1.length})"/>
     <column name="${column2.name}" type="int"/>
</createTable>

And keep the value of table.name and the other parameters in an external file db.properties, and reference this file either from within the changelog, or from the Liquibase command line, or as an option of the Maven plugin that runs liquibase.

I can't seem to find any way to do this, is it possible?

回答1:

Do that at compile time: sounds like job for maven filters and/or profiles

NOTE: be carefull with liquibase and any "marker" replacements... liquibase stores CRC of applied changessets

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>test</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <build>
        <filters>
            <filter>src/main/filters/liquibase.properties</filter>
        </filters>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
                <includes>
                    <include>liquibase.xml</include>
                </includes>
            </resource>
        </resources>
    </build>
</project>

/src/main/filters/liquibase.properties

table.name=TABLE_NAME
column1.name=COLUMN1_NAME
column1.length=10
column2.name=COLUMN2_NAME

/src/main/resources/liquibase.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog logicalFilePath="liquibase.xml" 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-2.0.xsd">

    <changeSet author="me" id="changeSetId1">
        <comment>Test</comment>

        <createTable tableName="${table.name}">
            <column name="id" type="int" />
            <column name="${column1.name}" type="varchar(${column1.length})" />
            <column name="${column2.name}" type="int" />
        </createTable>
    </changeSet>

</databaseChangeLog>

EDIT: A typical invocation (using filtered resources) would look like this: mvn resources:resources liquibase:update or more preferably use profiles... mvn resources:resources liquibase:update -P<profile_name>

EDIT2: There is one big advantage of this way of defining columns. You could use this property's (e.g.: column1.length) value (e.g.: 10) for validation of every layer: Hibernate, DAO, WEB, faces, JavaScript. Just use this property at each place where you need to validate against it. Even in i18n/messages.properties if needed (e.g.: input1.validation=No more than ${column1.length} letters.).

The only complication is that if you need to change this value you need to provide proper liquibase update/rollback script. Sometimes it is possible to change value and set new liquibase checksum (safe operation like increase varchar length), but other times you need to create a safe update changescript using new property/value.



回答2:

Take a look at here. You can either use a command line arguments (-D[arg name]=[arg value]) or environment variables. If you don't use any build manager tool such as Maven or Ant you will need to write a script for reading parameters from file and passing them to the command. Example