Friday, 2 April 2021
Liquibase Demostration with Spring Boot Application
The following demonstration is a Spring Boot application which only exposes a GET endpoint /users/:id. To integrate Liquibase, add a dependency for it in pom.xml.
```
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
```
The changelog files are located in resources/db/changelog/.
![image](https://user-images.githubusercontent.com/35857179/107869366-52681700-6ec8-11eb-8d44-f2eb27a28ee2.png)
Liquibase supports SQL, XML, JSON and YAML format for storing changelog files. The 00-db.changelog-master.yaml includes the changelog files for the releases in the correct order.
00-db.changelog-master.yaml
```yml
databaseChangeLog:
- include:
file: 01-db.changelog-yaml-example.yaml
relativeToChangelogFile: true
- include:
file: 02-db.changelog-sql-example.sql
relativeToChangelogFile: true
- include:
file: 03-db.changelog-json-example.json
relativeToChangelogFile: true
- include:
file: 04-db.changelog-xml-example.xml
relativeToChangelogFile: true
```
01-db.changelog-yaml-example.yaml
Here's an example of changelog in YAML format. It creates a table called user_details with four fields – id, username, first_name, last_name. A ChangeSet is identified by id and author. For best practice, keep only one change per ChangeSet. Pre-conditions can also be added here.
```yml
databaseChangeLog:
- changeSet:
id: create-table-user
author: liquibase-demo-service
preConditions:
- onFail: MARK_RAN
not:
tableExists:
tableName: user_details
changes:
- createTable:
columns:
- column:
autoIncrement: true
constraints:
nullable: false
primaryKey: true
primaryKeyName: user_pkey
name: id
type: BIGINT
- column:
constraints:
nullable: false
name: username
type: TEXT
- column:
constraints:
nullable: false
name: first_name
type: TEXT
- column:
name: last_name
type: TEXT
tableName: user_details
```
02-db.changelog-sql-example.sql
Here's an example of changelog in SQL format. It must start with the line –liquibase formatted sql to provide liquibase with metadata, followed by arbitrary SQL statements with a comment of the form :
``--changeset author:id attribute1:value1 attribute2:value2 [...]``.
```sql
--liquibase formatted sql
--changeset liquibase-demo-service:add-user-name-constraint
ALTER TABLE user_details ADD CONSTRAINT user_details_username_key UNIQUE (username);
```
03-db.changelog-json-example.json
Here's an example of changelog in JSON format.
```json
{ "databaseChangeLog": [
{
"changeSet": {
"id": "add-last-name-constraint",
"author": "liquibase-demo-service",
"changes": [
{
"addNotNullConstraint": {
"columnName": "last_name",
"constraintName": "user_last_name_key",
"tableName": "user_details"
}
}]
}
}
]
}
```
04-db.changelog-xml-example.xml
Here's an example of changelog in XML format. It utilizes loadUpdateData to loads and update from a CSV file into an existing table.
```
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<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 author="liquibase-docs" id="loadUpdateData-example" context="!prod">
<loadUpdateData
encoding="UTF-8"
relativeToChangelogFile="true"
file="../data/users.csv"
onlyUpdate="false"
primaryKey="id"
quotchar="'"
separator=","
tableName="user_details">
</loadUpdateData>
</changeSet>
</databaseChangeLog>
```
By default, Liquibase is enabled. Those changelog files will be executed at Spring Boot startup. To disable it, add the following property in src\main\resources\application.yaml.
```
spring:
liquibase:
enabled: false
```
To deploy any changes in the changelog files that have not been deployed to database yet, run the update goal.
```
./mvnw org.liquibase:liquibase-maven-plugin:update \
-Dliquibase.url=jdbc:postgresql://localhost:5432/liquibasedemo?current_schema=public \
-Dliquibase.changeLogFile=src/main/resources/db/changelog/00-db.changelog-master.yaml \
-Dliquibase.username=demouser \
-Dliquibase.password=demopassword
```
![image](https://user-images.githubusercontent.com/35857179/107869368-572ccb00-6ec8-11eb-9394-7eae484da444.png)
After running update goal, four tables have been created.
![image](https://user-images.githubusercontent.com/35857179/107869369-598f2500-6ec8-11eb-8106-9cfa12dcf198.png)
databasechangelog tracks which changeset have been run.
![image](https://user-images.githubusercontent.com/35857179/107869370-5b58e880-6ec8-11eb-890c-54b93cc9338a.png)
databasechangeloglock ensures there is only one Liquibase is running at one time as multiple instances being executed against the same database concurrently will lead to conflicts.
The table user_details is defined in 01-db.changelog-yaml-example.yaml, with constraints defined in 02-db.changelog-sql-example.sql and 03-db.changelog-json-example.json. The data is loaded in 04-db.changelog-xml-example.xml.
![image](https://user-images.githubusercontent.com/35857179/107869372-5dbb4280-6ec8-11eb-8cf0-77217ca33ce9.png)
user_details_id_seq is a sequence table for user_details.
![image](https://user-images.githubusercontent.com/35857179/107869373-601d9c80-6ec8-11eb-96aa-52885e47b98f.png)
To verify the result, start the Sprint Boot Application.
![image](https://user-images.githubusercontent.com/35857179/107869374-627ff680-6ec8-11eb-84ef-c8c89d2cb304.png)
Get user with id 100000000
![image](https://user-images.githubusercontent.com/35857179/107869375-64e25080-6ec8-11eb-8023-b9b12b2ae05d.png)
Tag can be used to mark the current database state for rollback in the future.
![image](https://user-images.githubusercontent.com/35857179/107869380-6e6bb880-6ec8-11eb-96d0-97abe0c884ff.png)
To create a tag, run the following goal
```
./mvnw org.liquibase:liquibase-maven-plugin:tag \
-Dliquibase.tag=version1 \
-Dliquibase.url=jdbc:postgresql://localhost:5432/liquibasedemo?current_schema=public \
-Dliquibase.username=demouser \
-Dliquibase.password=demopassword
```
![image](https://user-images.githubusercontent.com/35857179/107869381-70ce1280-6ec8-11eb-9060-ac59485cf0b2.png)
A tag version has been added.
![image](https://user-images.githubusercontent.com/35857179/107869383-73306c80-6ec8-11eb-8997-d4df594ae9a3.png)
There are three rollback modes – rollbackByTag, rollbackToDate and rollbackCount.
· RollbackByTag reverts all changes made to the database after the specific tag.
· RollbackToDate reverts all changes made to the database from the current date to the date and time you specify.
· RollbackCount reverts the changes sequentially starting with the most recent changes.
There are another modes such as rollbackOneChangeSet and rollbackOneUpdate but it requires Liquibase Pro.
Take the first one as an example, supposing there is another changelog – adding middle_name in user_details.
05-add-middle-name.json
Here we add the rollback statement to this changeset.
```
{ "databaseChangeLog": [
{
"changeSet": {
"id": "add-middle-name",
"author": "liquibase-demo-service",
"changes":[{
"addColumn":{
"catalogName":"cat",
"columns":[{
"column":{
"name":"middle_name",
"type":"TEXT"
}
}
],
"schemaName":"public",
"tableName":"user_details"
}
}
],
"rollback": [
{
"sql": {
"sql": "ALTER TABLE USER_DETAILS DROP COLUMN middle_name;"
}
}
]
}
}
]}
```
Deploy this changelog
```
./mvnw org.liquibase:liquibase-maven-plugin:update \
-Dliquibase.url=jdbc:postgresql://localhost:5432/liquibasedemo?current_schema=public \
-Dliquibase.changeLogFile=src/main/resources/db/changelog/05-add-middle-name.json \
-Dliquibase.username=demouser \
-Dliquibase.password=demopassword
```
The column "middle_name" has been added.
![image](https://user-images.githubusercontent.com/35857179/107869386-7592c680-6ec8-11eb-8236-7de18624480c.png)
The latest changelog is after the tag version1.
![image](https://user-images.githubusercontent.com/35857179/107869388-77f52080-6ec8-11eb-9171-257909b42f41.png)
If we need to revert the changes after it, update 00-db.changelog-master.yaml to include the latest changelog.
```
- include:
file: 05-add-middle-name.json
relativeToChangelogFile: true
```
then run the following goal.
```
./mvnw org.liquibase:liquibase-maven-plugin:tag \
-Dliquibase.tag=version1 \
-Dliquibase.url=jdbc:postgresql://localhost:5432/liquibasedemo?current_schema=public \
-Dliquibase.username=demouser \
-Dliquibase.password=demopassword
```
![image](https://user-images.githubusercontent.com/35857179/107869389-79bee400-6ec8-11eb-94fd-4e32ff05b1ae.png)
The record for 05-add-middle-name.json has been dropped.
![image](https://user-images.githubusercontent.com/35857179/107869390-7b88a780-6ec8-11eb-9868-23997a906655.png)
The column middle_name has been dropped.
![image](https://user-images.githubusercontent.com/35857179/107869393-7d526b00-6ec8-11eb-9e5b-88a55ddc383f.png)
Similarly, we can use RollbackToDate or RollbackCount to revert the changes.
RollbackToDate
liquibase:rollback -Dliquibase.rollbackCount=1
RollbackCount
liquibase:rollback "-Dliquibase.rollbackDate=Feb 03, 2021"
To conclude, we can define changelogs in 4 possible formats and run the Maven Goals to deploy them to database in the pipeline. We can also create a tag to mark the current state and rollback if necessary.
Subscribe to:
Post Comments (Atom)
A Fun Problem - Math
# Problem Statement JATC's math teacher always gives the class some interesting math problems so that they don't get bored. Today t...
-
SHA stands for Secure Hashing Algorithm and 2 is just a version number. SHA-2 revises the construction and the big-length of the signature f...
-
Contest Link: [https://www.e-olymp.com/en/contests/19775](https://www.e-olymp.com/en/contests/19775) Full Solution: [https://github.com/...
No comments:
Post a Comment