How to generate Liquibase changelogs by diffing local JPA entities against a database.

Photo by Pawel Czerwinski, https://unsplash.com/de/fotos/weissblaue-und-rote-abstrakte-malerei-3NXZA_V3qOQ

Liquibase is a popular, open-source framework for managing database schema changes. However, manually writing the required changelog files can be tedious and error-prone. In a more efficient workflow, you would

  • apply the schema changes to the JPA entities in your local development environment
  • let the corresponding Liquibase changelog file be generated by diffing these changes against a database that still contains the old schema version
  • review the generated changelog file (and adapt it, if necessary)

This article shows you the necessary steps for performing the changelog generation.

Initial Setup

The following steps are only required as initial setup, so you won’t have to repeat them for every single changelog generation. First, add the following plugin to your Maven POM:

<plugin>
  <groupId>org.liquibase</groupId>
  <artifactId>liquibase-maven-plugin</artifactId>
  <version>${liquibase.version}</version>
  <dependencies>
    <dependency>
      <groupId>org.liquibase.ext</groupId>
      <artifactId>liquibase-hibernate5</artifactId>
      <version>${liquibase.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
      <version>${spring-boot.version}</version>
    </dependency>
    <dependency>
      <groupId>javax.validation</groupId>
      <artifactId>validation-api</artifactId>
      <version>${javax-validation.version}</version>
    </dependency>
  </dependencies>
  <configuration>
    <changeLogFile>src/main/resources/db/changelog.xml</changeLogFile>
    <diffChangeLogFile>src/main/resources/db/changelogs/changelog.VERSION.xml</diffChangeLogFile>
    <driver>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver>
    <url>jdbc:sqlserver://db.example.com:1234;databaseName=example-db</url>
    <username>DB_USERNAME</username>
    <password>DB_PASSWORD</password>
    <referenceUrl>hibernate:spring:com.example.entities?dialect=org.hibernate.dialect.SQLServerDialect</referenceUrl>
    <verbose>true</verbose>
  </configuration>
</plugin>

You will have to adapt these configuration properties to your specific environment. They are self-explanatory for the most part, but a short description is given further down below.

If possible in your project, choose the most recent versions for the required dependencies. For example, the following versions should work fine with each other:

  • liquibase.version: 4.x.y
  • spring-boot.version: 2.x.y
  • javax-validation.version: 2.0.1.Final (unchanged for several years)

Changelog Generation

With the above setup in place, invoke the following command to generate the changelog file at the configured location:

mvn liquibase:diff

Aftwards, you will have to

  • review the generated file (and adapt it, if necessary)
  • change the VERSION in the filename to the desired changelog version
  • import the generated changelog file in your embracing changelog file

Configuration Parameters

The following table provides a brief description of the configuration parameters used above. You can find a full list of parameters in the Liquibase documentation

Parameter Explanation
changeLogFile Name and path for the existing, embracing changelog file.
diffChangeLogFile Name and path for the changelog file to be generated.
driver JDBC driver for connecting to the database containing the old DB schema.
url JDBC URL for connecting to the database containing the old DB schema.
username User name for connecting to the database containing the old DB schema.
password Password for connecting to the database containing the old DB schema.
referenceUrl Hibernate URL with the name of the Java package that contains your JPA entities. If necessary, you can also specify Hibernate naming strategies here.
verbose Increases the log output of the generation process (optional).
diffExcludeObjects Allows you to specify objects that shall be excluded from the generation process (optional). For example, provide ‘table:FOOBAR’ to exlude the ‘FOOBAR’ DB table.