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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With