Intro
In this article, we will dive deep into a practical guide on how to use Liquibase as a tool for managing database changes and maintaining the integrity of your data. Liquibase supports these databases.
Table of Contents
Open Table of Contents
What is Liquibase
Liquibase is an open-source and database-independent tool for managing database schema migrations and doing version control. It helps developers and database administrators maintain data integrity and ensure that database deployments, changelist rollbacks and application changes are always in sync.
Liquibase Concepts
Some of the key components and concepts of Liquibase include:
- Changelog: This is a YAML, JSON or XML file that tracks all the historical changes made to a database. The historical changes are usually paths to files that contain changesets.
- Changeset: Changeset is a unit of change that occurs in the database. These changesets are independent and agnostic of any other changeset.
- DatabaseChangeLog Table:
Liquibase uses a special table called
DatabaseChangeLog
that stores information about the changesets to a database that have been applied, rolled back or are pending. This table is created automatically by Liquibase if none exists. - DatabaseChangeLogLock Table:
To ensure that concurrent changes to the database are prevented, Liquibase uses a
DatabaseChangeLogLock
to make sure that only one Liquibase instance is created or runs at a time. This table is created automatically by Liquibase if none exists.
What is DB Management
Database management is the actions taken to manipulate and control data to meet the necessary conditions throughout the entire data lifecycle. Some of the data lifecycle actions include creation, management, use, share, collect/reuse, and destroy. Therefore, database management is tasked with protecting the data of an organization, and its clients, preventing legal and compliance risk and keeping data-driven applications performing optimally.
Show Me the Code!!
Spring boot Init
Head over to Spring Initializr and create a spring boot app. Note that we are using Java. Add all necessary dependencies including MySQL Driver and the Liquibase dependency libraries. As of 26th of November 2023, Java 17 and 21 are the LTS (Long Term Support) for Java programming language. Therefore, Spring boot apps can only be initialized with either JDK’s.
If you already have s Spring boot app, head over to Maven Repository and pick the latest version of the Liquibase dependency library. Alternatively, you could copy the version below.
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>4.25.0</version>
</dependency>
Spring boot Configs
Open the resources package in your spring boot project, create an application.yaml
file and add the following configurations:
spring:
liquibase:
enabled: true
changelog: classpath:db/changelog/db.changelog.yaml
datasource:
url: jdbc:mysql://localhost:3306/mydatabase
username: myusername
password: mypassword
driver-class-name: com.mysql.cj.jdbc.Driver
server:
port: 8080
servlet:
context-path: /api
These liquibase configuration will help Liquibase find the path to the changelog file with all the changesets.
The datasource configuration sets up our MySQL database. For this, you need to create a MySQL instance connection with MySQL workbench with those credentials.
Alternatively, you can use MySQL shell to create a superuser myusername
with password mypassword
.
Example
sudo mysql -u root -p
mysql> CREATE USER 'myusername'@'localhost'IDENTIFIED BY 'mypassword';
Query Ok
mysql> GRANT ALL PRIVILEGES ON * . * TO 'myusername'@'localhost';
Query Ok
mysql> FLUSH PRIVILEGES;
Query Ok
Creating a Java Entity
We will continue with the previous example where we built a REST API with Spring boot. In the article, we used the following class to create a database table:
@Entity
@Table
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class PlaygroundTable {
@Id
@Column
private int Id;
@Column
private String name;
@Column
private String description;
}
We will rename the class to PlaygroundEntity
and remove the Lombok field annotations since, these will be handled by Liquibase.
In addition, use your code editor to generate and override equals
and hashcode
methods within the class.
PlaygroundEntity.java
@Entity
@Table(name = "playground")
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class PlaygroundEntity {
@Id
private int Id;
private String name;
private String description;
@Override
---
@Override
---
}
We have renamed the class to ..Entity
because, an entity is a representation of a table in a relational database, while each
field in an entity class will correspond to a column in that table. As your code base gets larger, it would be great to
distinguish Entities from DTO’s, etc.
Creating a MySQL Table with Liquibase
Within the resources package, create a db/changelog
package. Within the new package, create a YAML file and name it
create_new_playground_table.yaml
. This file will contain our Liquibase changeset for creating a new table as per the
entity that we have created in the PlaygroundEntity.java
class
create_new_playground_table.yaml
databaseChangelog:
- changeSet:
validCheckSum: ANY
id: create-new-playground-table
author: your name
changes:
- createTable:
tableName: playground
columns:
- column:
name: id
type: BIGINT
autoIncrement: true
constraints:
primaryKey: true
- column:
name: name
type: VARCHAR(45)
nullable: false
- column:
name: description
type: TEXT
nullable: true
Creating a Liquibase DB Changelog
Create a new YAML file and name it db.changelog.yaml
, in the db/changelog
package. Within that
file, add the following path to the changeset created above:
databaseChangeLog:
- include:
file: db/changelog/create_new_playground_table.yaml
This will enable Liquibase to run the changeset in the MySQL database. If the changeset file path is not added in the changelog package, then your migrations will never run .
Finally, mvn spring-boot:run
your spring boot application.
Test the API with Postman using the url, http://localhost:8080/api/playground
Noteworthy
It is important to follow particular file naming conventions so that your team is in sync with your database changes. For example
create_<...>_.yaml
when creating new tablesrename_<...>_.yaml
when renaming table columnsadd_new_<...>_.yaml
when adding indexes, e.t.c in existing tables
Alternatively, you could use SQL syntax such CREATE…, ALTER…, as a naming convention for your changeset files.