Running Liquibase from Java on a selected Postgres schema

Posted 10 Jun 2020 by Erik Lumme

Running Liquibase from Java is useful to ensure a schema is up to date on startup, or to update a schema as part of an integration test.

All code in this post can be found on GitHub.

The first step is to add the Liquibase core dependency from Maven central. Also ensure that your database driver of choice is on the classpath.

I created a class LiquibaseRunner with a constructor that accepts the database connection properties, as well as the names of two database schemas: the schema where the database change log tables are located, and the schema to update.

Liquibase requires a database connection. How this is obtained depends on your setup, one example is through the java.sql.DriverManager.

In a Hibernate Session, which you can get from an EntityManager with entityManager.unwrap(Session.class), there is a method doWork that provides a java.sql.Connection.

With the connection, we can create a Liquibase Datebase object.

Here the schemas are set. With SET search_path TO <schema>, we set the schema for that connection, which is the one Liquibase will update.

We can then create the Database object using the DatabaseFactory. We set the default schema name, which will be the schema where the databasechangelog and databasechangeloglock tables reside.

When using Postgres, if the default schema is not set in Liquibase, it will be the result of the SELECT current_schema() query. In our case, that is the schema set as the search_path.

With these pieces in place, we can construct a Liquibase object.

The CHANGELOG_PATH is the path to the Liquibase change log. If it is on the classpath, the ClassLoaderResourceAccessor can be used. If it is not, another accessor should be used, such as the FileSystemResourceAccessor.

As the name suggests, the ClassLoaderResourceAccessor uses ClassLoader#getResource, as opposed to Class#getResource. This means that the path should not have a leading slash.

Now the updates can be run. We use Java’s try-with-resources to ensure the Liquibase instance is closed afterwards, which also closes the database connection.

The Contexts and LabelExpression can be used to only run certain change log entries, see Contexts vs. Labels.

Check out the complete example on GitHub, which also shows how to load the connection parameters from a properties file, and how the LiquibaseRunner is run.