Spring Boot + Liquibase Example (2024)
In this tutorial, we'll configure Liquibase with a Spring Boot project, and use XML to document database schema changes. When the spring boot project is started, the schema changes will be applied immediately to the configured database through Liquibase.
What is Liquibase?
Liquibase is an open-source tool for keeping track of database schema script revisions. It works with a variety of database types and accepts a variety of file formats for defining the database structure.
Liquibase can roll changes back and forward from a given point, removing the need to remember what was the last update or script you executed on a particular DB instance.
When it becomes necessary to update/revert changes in a database or migrate it from one version to another, database schema migration is done. Liquibase and Flyway are the two main migrating tools.
Refer Spring Boot Liquibase using plain SQL queries Example for its implementation.
What is Flyway?
Flyway is an open source database migration software. It has Migrate, Clean, Info, Validate, Undo, Baseline, and Repair seven basic commands, SQL (database-specific syntax (such as PL/SQL, T-SQL, etc.) or Java migrations are supported (for advanced data transformations or dealing with LOBs).
You can also refer Java base migration using Spring Boot + Flyway Example.
Refer example for Flyway Command Line base migration.
Differences between Flyway and Liquibase
Refer Liquibase VS Flyway for more details.
FlywayDB |
Liquibase |
|
Diff utility to compare two databases | No | Yes |
Generates SQL for you | Yes | No |
Rollback | Paid Service | Yes, available |
Targeted rollback for any single change and Targeted rollback for a set of changes | No | Paid Service |
Ability to manage change files in a variety of ways and can use the monitoring and reporting dashboard. | No | Yes |
Specifying changes file | SQL | SQL, XML, JSON, YAML |
Repeatable migrations | Yes | Yes |
Dry runs | Paid Service | Yes, available |
Preconditions | No | Yes |
Take a look at our suggested posts:
Let's start developing Spring Boot application with Liquibase support.
Project Structure
Maven Dependency
Add dependencies for Liquibase liquibase-core
.
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.techgeeknext</groupId>
<artifactId>spring-boot-liquibase-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-boot-liquibase-example</name>
<description>Spring Boot + Liquibase + JPA Example</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
Provide database connection details in properties file.
spring.datasource.url=jdbc:mysql://localhost/techgeeknextLiquibasedb?createDatabaseIfNotExist=true&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.platform=mysql
spring.jpa.hibernate.ddl-auto=update
Liquibase Changelog File
db.changelog-master.yaml
The change log file is the primary source of configuration for Liquibase. If we don't specify a
change log file location in Spring Boot, the default path for YAML is
db/changelog/db.changelog-master.yaml
.
Create the master change log file changelog-master.xml at default liquibase XML and included change
log file by using include
with correct sequence.
databaseChangeLog:
- include:
file: db/changelog/create-company-and-employee-schema.xml
- include:
file: db/changelog/insert-employee-data.xml
- include:
file: db/changelog/insert-company-data.xml
create-company-and-employee-schema.xml
- Create schema for company and employee table.
- The
databaseChangeLog
tag must be the root element in every change log file. - Write database related operation in
changeSet
tag withauthor
and uniqueid
attribute in liquibase defined XML syntax.
<?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.1.xsd">
<changeSet id="01" author="techgeeknext">
<createTable tableName="company"
remarks="Company Data">
<column name="id" type="int" autoIncrement="true">
<constraints nullable="false" unique="true" primaryKey="true"/>
</column>
<column name="name" type="varchar(255)">
<constraints nullable="false" unique="true"/>
</column>
<column name="employee" type="int">
<constraints nullable="false"/>
</column>
</createTable>
<!-- for manual rollback
<rollback>
<dropTable tableName="company"/>
</rollback>
-->
<createTable tableName="employees"
remarks="Employees Data">
<column name="id" type="int" autoIncrement="true">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="name" type="varchar(100)">
<constraints nullable="false"/>
</column>
</createTable>
<addForeignKeyConstraint baseTableName="company" baseColumnNames="employee"
constraintName="employee_fk"
referencedTableName="employees" referencedColumnNames="id"/>
</changeSet>
</databaseChangeLog>
insert-company-data.xml
Insert few test data into company table.
<?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.1.xsd">
<changeSet id="03" author="techgeeknext">
<comment>Inserting Company records</comment>
<insert tableName="company">
<column name="id" valueNumeric="1"/>
<column name="name" value="techgeeknext_company_01"/>
<column name="employee" valueNumeric="01"/>
</insert>
<insert tableName="company">
<column name="id" valueNumeric="2"/>
<column name="name" value="techgeeknext_company_02"/>
<column name="employee" valueNumeric="02"/>
</insert>
<insert tableName="company">
<column name="id" valueNumeric="3"/>
<column name="name" value="techgeeknext_company_03"/>
<column name="employee" valueNumeric="03"/>
</insert>
<insert tableName="company">
<column name="id" valueNumeric="4"/>
<column name="name" value="techgeeknext_company_04"/>
<column name="employee" valueNumeric="04"/>
</insert>
<insert tableName="company">
<column name="id" valueNumeric="5"/>
<column name="name" value="techgeeknext_company_05"/>
<column name="employee" valueNumeric="05"/>
</insert>
<!--
To update the company table data on precondition
if name is techgeeknext_company_03 then update employee to 05
<preConditions>
<dbms type="mysql"/>
</preConditions>
<update tableName="company">
<column name="employee" value="05"/>
<where>name = 'techgeeknext_company_03'</where>
</update>
!-->
</changeSet>
</databaseChangeLog>
insert-employee-data.xml
Insert few test data into employee table.
<?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.1.xsd">
<changeSet id="02" author="techgeeknext">
<comment>Inserting employees</comment>
<insert tableName="employees">
<column name="id" valueNumeric="01"/>
<column name="name" value="techgeeknext_employee_01"/>
</insert>
<insert tableName="employees">
<column name="id" valueNumeric="02"/>
<column name="name" value="techgeeknext_employee_02"/>
</insert>
<insert tableName="employees">
<column name="id" valueNumeric="03"/>
<column name="name" value="techgeeknext_employee_03"/>
</insert>
<insert tableName="employees">
<column name="id" valueNumeric="04"/>
<column name="name" value="techgeeknext_employee_04"/>
</insert>
<insert tableName="employees">
<column name="id" valueNumeric="05"/>
<column name="name" value="techgeeknext_employee_05"/>
</insert>
</changeSet>
</databaseChangeLog>
Test
Now, execute mvn spring-boot run
command to start spring boot application.
Once application has started, you can go to MYSQL and can see the generated table by the
application.
As shown below, you can generate change set between local/test (techgeeknextLiquibasedb-test)
and
development (techgeeknextLiquibasedb-dev) database using liquibase:diff
command.
mvn liquibase:diff -Ptest -Dliquibase.url="jdbc:mysql://localhost/techgeeknextLiquibasedb-test?autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true" -Dliquibase.username="root" -Dliquibase.password="root" -Dliquibase.referenceUrl="jdbc:mysql://localhost/techgeeknextLiquibasedb-dev?autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true" -Dliquibase.referenceUsername="root" -Dliquibase.referencePassword="root"
Important Liquibase Properties
There are some important liquibase properties that you can define in application.properties file as given below. For more configuration properties can refer to this reference.
Properties |
Usage |
spring.liquibase.change-log=classpath:db/changelog/db.changelog-master.xml
|
Path of changelog configuration |
spring.liquibase.labels |
runtime labels - comma-separated list |
spring.liquibase.database-change-log-lock-table |
Table name to track concurrent Liquibase activities. |
spring.liquibase.contexts |
runtime contexts - comma-separated list |
spring.liquibase.database-change-log-table |
tracking change history table name |
spring.liquibase.default-schema |
Default database schema |
spring.liquibase.liquibase-tablespace |
Tablespace for Liquibase objects |
spring.liquibase.user |
Username of the database to migrate |
spring.liquibase.password |
Password of the database to migrate |
spring.liquibase.url |
URL of the database to migrate |
Download Source Code
The full source code for this article can be found on below.Download it here - Spring Boot + Liquibase Example