Mastering Liquibase with Spring Boot: A Step‑by‑Step Database Change Management Guide
This tutorial walks through setting up Liquibase in a Spring Boot project, creating a Maven plugin to generate XML/YAML changelogs, configuring the application, and performing common database operations such as creating tables, adding columns, creating indexes, initializing data, while also addressing a common includeAll path issue.
This article introduces Liquibase, a database change management tool, and demonstrates a practical Spring Boot project that uses Liquibase to create tables, modify columns, add indexes, and initialize data.
Liquibase Template Generator Plugin
The tutorial first creates a Maven project liquibase-changelog-generate that can generate changelog files in both XML and YAML formats. The plugin declares the following dependencies:
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.8.6</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.6.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.6.4</version>
<configuration>
<goalPrefix>hresh</goalPrefix>
<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.6.3</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>An interface LiquibaseChangeLog provides utility methods for generating changelog file names and checking duplicate IDs:
public interface LiquibaseChangeLog {
default String getChangeLogFileName(String sourceFolderPath) {
System.out.println("> Please enter the id of this change:");
Scanner scanner = new Scanner(System.in);
String changeId = scanner.nextLine();
if (StrUtil.isBlank(changeId)) {
return null;
}
String changeIdPattern = "^[a-z][a-z0-9_]*$";
Pattern pattern = Pattern.compile(changeIdPattern);
Matcher matcher = pattern.matcher(changeId);
if (!matcher.find()) {
System.out.println("Change id should match " + changeIdPattern);
return null;
}
if (isExistedChangeId(changeId, sourceFolderPath)) {
System.out.println("Duplicate change id :" + changeId);
return null;
}
Date now = new Date();
String timestamp = DateUtil.format(now, "yyyyMMdd_HHmmss_SSS");
return timestamp + "__" + changeId;
}
default boolean isExistedChangeId(String changeId, String sourceFolderPath) {
File file = new File(sourceFolderPath);
File[] files = file.listFiles();
if (files == null) {
return false;
}
for (File f : files) {
if (f.isFile() && f.getName().contains(changeId)) {
return true;
}
}
return false;
}
}Two Mojo classes implement the interface: LiquibaseChangeLogXml generates an XML changelog, and LiquibaseChangeLogYaml generates a YAML changelog. Both obtain the Git user name via a GitUtil helper:
public class GitUtil {
public static String getGitUserName() {
try {
String cmd = "git config user.name";
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = reader.readLine();
p.waitFor();
reader.close();
p.destroy();
return line;
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
return "hresh";
}
}Spring Boot Liquibase Project
The second project, springboot-liquibase , demonstrates how Liquibase integrates with Spring Boot. Key Maven dependencies include Spring Boot starter web, MySQL connector, Druid datasource, MyBatis‑Plus, and Liquibase core:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>4.16.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
</dependencies>The application.yml configures the datasource and Liquibase settings:
server:
port: 8088
spring:
application:
name: springboot-liquibase
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mysql_db?serverTimezone=Hongkong&characterEncoding=utf-8&useSSL=false
username: root
password: root
liquibase:
enabled: true
change-log: classpath:liquibase/master.xml
database-change-log-table: databasechangelog
database-change-log-lock-table: databasechangeloglock
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
lazy-loading-enabled: true
changeLogFile: src/main/resources/liquibase/master.xmlThe master changelog ( master.xml) includes common properties and an includeAll directive that points to liquibase/changelogs/:
<?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">
<property name="id" value="int(11)" dbms="mysql"/>
<property name="time" value="timestamp" dbms="mysql"/>
<includeAll path="liquibase/changelog/"/>
</databaseChangeLog>Database Operations
Creating a table – after running mvn install, the plugin generates a YAML changelog named 20221124_161016_997__create_table_admin.yml with the following content:
databaseChangeLog:
- changeSet:
id: 20221124_161016_997__create_table_admin
author: hresh
changes:
- createTable:
tableName: admin
columns:
- column:
name: id
type: ${id}
autoIncrement: true
constraints:
primaryKey: true
nullable: false
- column:
name: name
type: varchar(50)
- column:
name: password
type: varchar(100)
- column:
name: create_time
type: ${time}Adding a column – the plugin creates 20221124_163754_923__add_column_address_in_admin.yml:
databaseChangeLog:
- changeSet:
id: 20221124_163754_923__add_column_address_in_admin
author: hresh
changes:
- addColumn:
tableName: admin
columns:
- column:
name: address
type: varchar(100)Creating an index – example changelog:
databaseChangeLog:
- changeSet:
id: 20221124_164641_992__create_index_in_admin
author: hresh
changes:
- createIndex:
tableName: admin
indexName: idx_name
columns:
- column:
name: nameTo modify an index, first drop it using a dropIndex changeSet.
Initializing data – a simple SQL changeSet inserts a record into the admin table:
databaseChangeLog:
- changeSet:
id: 20221124_165413_348__init_data_in_admin
author: hresh
changes:
- sql:
dbms: mysql
sql: "insert into admin(name,password) values('hresh','1234')"
stripComments: trueCommon Issue: Unwanted Files Loaded by includeAll
The original includeAll path classpath:/liquibase/changelog/** caused Liquibase to scan the same path inside the liquibase‑core JAR, resulting in many irrelevant files being listed in the console. Renaming the project directory from changelog to changelogs and updating the includeAll path resolves the problem.
After the rename, the console output shows only the intended changelog files.
Running the application displays the generated databasechangelog table entries and the newly created admin table structure.
Further Liquibase commands such as liquibase:dbDoc can generate visual documentation of the database schema, which is output to the target directory and can be viewed via index.html.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java High-Performance Architecture
Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
