Liquibase with SpringBoot
We will be building an application which uses Liquibase as the Data Migration tool.
Git Code Link : https://github.com/Viveksingh1313/liquibase-springboot
Liquibase
Liquibase is used to evolve the database schema. Database migration tools helps track, version control, and automate DB schema changes across environments. With the rise of Agile and DevOps methodologies that are needed to accomplish continuous integration and deployment, it’s more important than ever to apply CI/CD to databases.
Read more about evolutionary database design https://martinfowler.com/articles/evodb.html
Use cases done in the project :
1.Create table
2. Insert a record
3. Update a record
4. Delete a record
5. Add a column
6. Insert records
7. Usage of Context. Can be used to target environments.
8. Usage of labels
9. Rollback
Running and checking the application (Check readme file also) :
Requirement : Java18
You can change the version ac to your jdk. Just remember to change it on
pom.xml inside java.version property.
Build the application :
mvn clean install
Start the application :
mvn spring-boot:run
Application link :
localhost:8080
H2 DB Link to view all DB changes :
http://localhost:8080/h2-console
Username/Password is vivek/password for h2 DB. You can
change it inside application.properties.
To see changes done by this application :
Run these sql queries :
select * from databasechangelog
select * from applicationinfo
You would find all the scripts to be run against DB inside src/main/java/resources/dblogs/changelog/changes
Theoretical Explanation about all concepts of Liquibase :-
Liquibase Features :
- Flexible database change. SQL, YAML, JSON, XML can be used.
- Version control your changes.
- Control over when and where to deploy.
- Easily Rollback changes
- Context (Target specific environments) and preconditions can be used
- Wide Integration and Database platform support
Information on working of Liquibase
The heart of the liquibase is a changelog file. Inside directory resources/db/changelog/ create a master file named ‘changelog-master.xml’. With this Liquibase will run automatically
on app startup. This file will have references to all your scripts that you want to run to make DB changes . Example in screenshot below :
Changelog Formats :
A changeset is uniquely tagged by both an author
and an id
attribute (author:id
). The id
tag is only used as an identifier, it does not direct the order that changes are run and does not have to be an integer. If you do not know or do not want to save the actual author, use a placeholder value such as UNKNOWN
. To execute the changeset, you must include both author
and id
.
Screenshot below as an example :
vivek is the author and id is 2 in above changeset.
Tables involved in Liquibase :
- DATABASECHANGELOG
Liquibase uses the DATABASECHANGELOG table to track which changesets have been run. If the table does not exist in the database, Liquibase creates one automatically. Also gives important details about all scripts that have been run to modify DB.
2. DATABASECHANGELOGLOCK
Liquibase uses the DATABASECHANGELOGLOCK table to ensure only one instance of Liquibase runs at a time. lock is maintained so that only 1 session/instance can be run at any point in time.
There is also a concept of Validchecksum which is used to make sure all your older scripts are the same, and haven’t been changed. If your older scripts have changed, then it will have a different hash value which will not match with the column md5sum in databasechangelog table.
From official docs : In order to detect changes between what is currently in the changelog vs. what was actually run against the database, Liquibase stores a checksum with each changeset entry in the DATABASECHANGELOG tracking table.
To change default changelog file (application.yml):
spring:
liquibase:
changeLog: "classpath:db/migration/my-master-change-log.json"
To disable liquibase :
spring.liquibase.enabled=false
Why Liquibase over Flyway
Here’s what Flyway and Liquibase have in common:
- Using a migrations-based approach to database change
- At update time, both tools check if a change has already been deployed
- Running from command line or Maven
- Offering support and enhanced features as a paid add-on to their open source offering
- Using SQL-based migrations (both can use plain SQL)
- Repeatable migrations (both can perform rerunnable vs. non-rerunnable changes)
Difference b/w Liquibase and Flyway
- Liquibase supports a wide range of DB types including mongo, cassandra, redshift. Comparatively more than Flyway.
- Liquibase hub is a UI tool for teams to easily view, organize, and report database DevOps metrics on their pipelines. Flyway doesn’t have any such provisions.
- Liquibase has been in the market since 2006. Has around 75 million downloads. Flway has been in the market since 2010 with 50million downloads.
- Flyway uses SQL for defining a change. On the other hand Liquibase provides flexibility to specify a change in different formats including SQL , XML, YAML, and JSON.
- Flyway needs a specific file format to keep track of changes. Liquibase would need a master ledger to keep track of changes.
- Liquibase and Flyway provides a way to rollback everything or undo specific migrations. Liquibase is free and will serve our purpose, flyway needs pro services.
- Managing changes across env looks easier in Liquibase
- Flyway provides Java file based migration. Flyway has a native Java API. It is designed to help us with more complex migrations like BLOB and CLOB changes or advanced bulk data changes. This API can be very useful in some cases and may be the reason to choose Flyway over Liquibase.
- Liquibase offers an added feature called pre-conditions. Preconditions allow users to apply changes based on the current state of the database. A changeset will only execute if it passes these preconditions.
- Liquibase supports snapshots. Flyway doesn't. Using snapshots you can compare older and newer schema changes.
Label and Contexts
Label and Contexts in Liquibase allows you to run a script/changeset across one of the environments you want to target. Out of dev, test, int, prod you can run your script to run across just test environment. Example below :
And then your provide a property inside application.yml :
Best Practices
- Define the team’s changeset ID format. (example-vivek:1)
- Don’t Modify a ChangeSet
- Instead, add a new changeSet if
modifications are needed for the change that has been applied by an existing changeSet. - We strongly encourage having only one change per changeset. This makes each change atomic within a single transaction.
- Multiple independent changes in one changeset creates a risk that some changes deploy while a later change fails. This leaves the database in a partially deployed state which requires manual intervention to correct.
- Use SQL if you are familiar with it and do not want to learn a new way to specify database changes.
- Plan a rollback strategy. If you use sql as the language for liquibase, rollbacks aren’t possible automatically.
- Use Liquibase Contexts. Contexts help you target specific environments.
Git Code Link : https://github.com/Viveksingh1313/liquibase-springboot
Hope this article was helpful. You can follow me for much such content.
You can also reach me out at LinkedIn or vivek.sinless@gmail.com
References
https://reflectoring.io/database-migration-spring-boot-liquibase/
https://www.codeusingjava.com/boot/liq
https://docs.liquibase.com/concepts/changelogs/changelog-formats.html
https://docs.liquibase.com/workflows/liquibase-community/liquibase-auto-rollback.html
https://docs.liquibase.com/concepts/changelogs/preconditions.html
https://stackoverflow.com/questions/69996601/liquibase-labelshttps://www.liquibase.com/blog/what-affects-changeset-checksums
https://docs.liquibase.com/concepts/changelogs/changelog-formats.html
https://www.liquibase.com/blog/contexts-vs-labels
https://docs.liquibase.com/concepts/bestpractices.html