How to set up Liquibase with an Existing Project and Multiple Environments

The Getting Started Guide works when you want to use Liquibase on a new environment with an empty changelog file that matches your empty database. However, when you have multiple environments and want to set up Liquibase with all of them to match your current database schema, the process differs.

For example, you have an HR database and two different environments called: HR_Dev and HR_Test, and you want them all to match your HR database.

You will learn how to introduce Liquibase to your HR_Dev and HR_Test database environments without affecting your current database schema. You will create a changelog file that matches the current state of your HR database and then apply this changelog file to the HR_Dev and HR_Test databases so it will match all the environments.

Step 1: Create a changelog

First, you will create a changelog file that contains all the SQL changes from your existing project. In this example we will use the source HR database. You can create a changelog file to match your HR database manually or it can be done automatically by using the generate-changelog command.

Note: For any database larger than a few tables, use the generate-changelog command.

To run the generate-changelog command, specify the driver, class path, URL, and user authentication information in the Liquibase properties file. For more information, see Create and Configure a liquibase.properties File. You can also specify these properties in your command line.

Then run the generate-changelog command:

liquibase generate-changelog --changelog-file=dbchangelog.xml

Note: Enter the name of the changelog that you want to use in place of dbchangelog.xml.

The generate-changelog command generates a changelog file that contains all your objects (represented as changesets) and places the file in the same directory where the command was run.

Note: If there is a project that requires working on multiple schemas in one workflow, you can have the changelog containing multiple schemas by adding the following flags --schemas=<schema1>,<schem2>,<schema3> and --include-schema=true to the generate-changelog command.

The changelog file name extension determines the format of the changelog, so if you specify the file name as changelog.xml, you will get an XML formatted changelog. Likewise, if you specify the file name as .yaml, .json, or .sql, you will get changelogs formatted in YAML, JSON, or SQL, respectively.

Note: If you generate an SQL formatted changelog, specify the type name of the targeted database as a part of the file name:

changelog.<db_type>.sql

Note: Liquibase does not always detect complex structures like stored procedures or details like an index that is not clustered. Once you have generated a changelog, inspect the output. Review the generated changesets and ensure that the data types look as expected.

XML changelog example

This is the result of running the generate-changelog command on our sample database. Your changelog will contain changes from your database.

<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
    xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
    xmlns:pro="http://www.liquibase.org/xml/ns/pro"
    xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd
        http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
        http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd">
	<changeSet  author="diff-generated"  id="1185214997195-2">
		<createTable  name="DEPT">
			<column  name="DEPTNO"  type="NUMBER(2,0)"/>
			<column  name="DNAME"  type="VARCHAR2(14,0)"/>
			<column  name="LOC"  type="VARCHAR2(13,0)"/>
		</createTable>
	</changeSet>
	<changeSet  author="diff-generated"  id="1185214997195-6">
		<createIndex  indexName="PK_DEPT"  tableName="DEPT">
			<column  name="DEPTNO"/>
		</createIndex>
	</changeSet>
	<changeSet  author="diff-generated"  id="1185214997195-7">
		<createIndex  indexName="PK_EMP"  tableName="EMP">
			<column  name="EMPNO"/>
		</createIndex>
	</changeSet>
	<changeSet  author="diff-generated"  id="1185214997195-8">
		<addPrimaryKey  columnNames="DEPTNO"  tableName="DEPT"/>
	</changeSet>
</databaseChangeLog>

Step 2: Populate the DATABASECHANGELOG tracking table

Once you have your changelog file, populate the DATABASECHANGELOG tracking table with the changesets from this changelog.

Liquibase keeps track of your already deployed changes with the help of its DATABASECHANGELOG tracking table.

To create this table for the first time, use the changelog-sync command. The changelog-sync command will populate the DATABASECHANGELOG table with the changesets metadata as if you have been using Liquibase all along.

Another approach you can choose is to add the contexts.

Running the changelog-sync-sql and changelog-sync commands:

  • Run the changelog-sync-sql command to inspect the SQL and ensure that everything looks good before executing the changelog-sync command:
  • liquibase changelog-sync-sql --changelog-file=dbchangelog.xml

    Note: Enter the name of the changelog that you want to use in place of dbchangelog.xml.

  • Run the changelog-sync command to ensure that the changesets are treated as already run since they exist in our HR database. The command will mark the changesets in the changelog file as already deployed. This will prevent Liquibase from attempting to redeploy those changesets next time when you run the update command.
  • liquibase changelog-sync --changelog-file=dbchangelog.xml

    Note: Enter the name of the changelog that you want to use in place of dbchangelog.xml.

Adding the contexts

Alternatively, you can add contexts to the changesets such as <changeSet ... context="legacy">:

<changeSet  author="diff-generated"  id="1185214997195-8" context="legacy">
	<addPrimaryKey  columnNames="DEPTNO"  tableName="DEPT"/>
</changeSet>

The contexts can be added to the changeset to control which changeset will be executed in any run. Only the changesets marked with the specific contexts in your changelog that are used with the --context-filter flag at runtime will be deployed.

  • When you run the changelog on the HR_Dev and HR_Test database environments, enter the following:
  • liquibase update --context-filter=legacy
  • When you run it on your existing database, which is HR, enter the following:
  • liquibase update --context-filter=non-legacy

After creating a changelog and populating the HR DATABASECHANGELOG table with the changelog-sync command or with the contexts, you can now deploy this generated changelog to the HR_Dev and HR_Test database environments that need to match you HR database.

Note: If you use Liquibase versions 4.16.0 to 4.23.0, use the syntax contextFilter instead of context in your changesets. Also, use --contexts instead of --context-filter in the CLI.