Using Liquibase with Spring Boot and Maven
When developing software, it is common to create a database schema during production. Liquibase is a great migration tool that helps with creating the database schema, then running deployment and some testing to the database to ensure that the changes will work in production. The purpose of this tutorial is to guide you through the process of using Liquibase migration tool for a Java Spring Boot application with Maven.
Spring
Liquibase can be run in a Spring environment by declaring a liquibase.spring.SpringLiquibase
bean.
Example
<bean id="liquibase" class="liquibase.integration.spring.SpringLiquibase">
<property name="dataSource" ref="myDataSource" />
<property name="changeLog" value="classpath:db-changelog.xml" />
<!--
contexts specifies the runtime contexts to use.
-->
<property name="contexts" value="test, production" />
</bean>
Overview
What is Liquibase?
Liquibase provides a great starting point for teams addressing the challenges that come with managing database schema changes.
It has the ability to manage revisions of your database schema scripts. It works across various types of databases and supports various file formats for defining the DB structure. Liquibase has the ability to roll changes back and forward from a specific point - saving you from the need to know what was the last change or script you ran on a specific DB instance.
What is Spring Boot?
Spring Boot is an open source Java-based framework used to create micro service. It is used to build stand-alone and production-ready Spring applications.
What is Maven?
Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project's build, reporting and documentation from a central piece of information.
The Spring Boot Maven plugin has two main features:
- It collects all the jar files in the classpath and builds a single
uber-jar
. This helps to execute your service in more convenient way. - It searches for the
public static void main()
method to flag any classes with that method signature as a runnable class.
Prerequisites
- Go to https://www.liquibase.org/download to install the latest version of Liquibase. Liquibase requires Java 8+. If you use the installer, it already includes Java.
- Go to https://maven.apache.org/install.html to install Maven.
Tutorial
To create a Liquibase project with Spring Boot and Maven, perform the following steps:
- Create a new project folder and name it
LiquibaseProj
. - In your
LiquibaseProj
folder, create a new text file and name itliquibase.properties
. - Edit the
liquibase.properties
file to add the following properties:
changeLogFile: dbchangelog.xml
url: jdbc:h2:mem:my_db;MODE=Mysql;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;DATABASE_TO_UPPER=false;INIT=CREATE SCHEMA IF NOT EXISTS my_db\\;SET SCHEMA my_db
classpath: ../../Liquibase_Drivers/postgresql-42.2.8.jar
The changeLogFile
property points to the changelog file that we will create later in this tutorial. Since the changelog is in the home directory, there is no need to specify a path to it. If the changelog is located somewhere else, then add a relative path.
Windows example: changeLogFile: ..\\<path to changelog>\\changelogs\\dbchangelog.xml
Linux example: ../<path to changelog>/changelogs/dbchangelog.xml
The url
property is your database url. In this example, we use an in-memory h2 database.
If there is a user and password associated with the database, then add the username
and password
properties to the properties file as well.
If you already have a Liquibase Pro key and want to apply it to your project, add the following property to your liquibase.properties file:
liquibaseProLicenseKey: <paste license key>
- In your
LiquibaseProj
folder, create a new text file and name itdbchangelog.xml
. The changelog files contain a sequence of changesets, each of which makes small changes to the structure of your database.
Note: Instead of creating an empty changelog file, you can use an existing database to generate a changelog. In this tutorial, you will manually add a single change. To add this change, open the dbchangelog.xml
file and update the changelogfile with the following code snippet:
<?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"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">
</databaseChangeLog>
- Add a changeset to the changelog. The changesets are uniquely identified by
author
andid
attributes. Liquibase attempts to execute each changeset in a transaction that is committed at the end. In thedbchangelog.xml
file, add a new “department” create table changeset as follows:
<?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"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">
<changeSet id="1" author="bob">
<createTable tableName="department">
<column name="id" type="int">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="name" type="varchar(50)">
<constraints nullable="false"/>
</column>
<column name="active" type="boolean"
defaultValueBoolean="true"/>
</createTable>
</changeSet>
</databaseChangeLog>
Note: The preceding changeset is XML format. The corresponding SQL statement looks like the following:
CREATE TABLE "department"
( "id" number(*,0),
"name" VARCHAR2(50 BYTE),
"active" NUMBER(1,0) DEFAULT 1
);
- In your
LiquibaseProj
folder create a text document namedpom.xml
. - Open the
pom.xml
file and update it with the following code snippet:
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.liquibase-support.app</groupId>
<artifactId>Liquibase-app-1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Liquibase-app</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>8</java.version>
<liquibase.propertyFile>${project.basedir}/liquibase.properties</liquibase.propertyFile>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<propertyFile>${liquibase.propertyFile}</propertyFile>
</configuration>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.6.Final</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.4.0-b180830.0359</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
- Download and unzip the
src.zip
to yourLiquibaseProj
directory. Thesrc.zip
file contains java scripts to run a Spring application.
Note: In the src directory, you will see the path to your application code: src/main/java/com/application.java
and the path to some unit tests: src/test/java/com/applicationTests.java
.
- Open the command prompt and navigate to the
LiquibaseProj
directory.
- Run the following command to compile and test your Spring Boot application code:
mvn package
- Run the following command to deploy your changes:
mvn liquibase:update
- In the console output, you will see the following SQL execution:
CREATE TABLE department (id INT NOT NULL, name VARCHAR(50) NOT NULL, active BOOLEAN DEFAULT TRUE, CONSTRAINT PK_DEPARTMENT PRIMARY KEY (id))
Table department created.
Also, you will see two more tables:
- DATABASECHANGELOG tracking table. This table keeps a record of all the changesets that were deployed. This way, next time when you deploy again, the changesets in the changelog will be compared with the DATABASECHANGELOG tracking table, and only the new changesets that were not found in the DATABASECHANGELOG will be deployed. You will see that a new row was created in that table with the changeset information we have just deployed. For example:
ID | AUTHOR | FILENAME | DATEEXECUTED | ORDEREXECUTED | EXECTYPE | MDSUM | … |
---|---|---|---|---|---|---|---|
1 | bob | dbchangelog.xml | date&time
|
1 | EXECUTED | checksumvalue
|
… |
- DATABASECHANGELOGLOCK. This table is used internally by Liquibase to manage access to the changelog table during deployment.
See also