When developing web applications, one of the common problems to consider is how to create database diagrams in production and how to develop them progressively.
It is well known to use database migration tools in this field. These tools can help you build structures, run them while publishing, and they can also help you write automated tests, so you can be confident that the changes you make will work in production.
In the Java field, some well-known options are Flyway and Liquibase. In this article, we will study Liquibase as a way to perform database migration.
Benefits
Writing charts and data not related to databases. This is a feature that Flyway does not currently provide. The advantage of this method is that you only need to define the changes once and then test them on different databases. For example, type H2 Test again and run the migration on MySQL without changing the code. You can specify changes to the XML, YAML, JSON, and SQL formats and choose the style you want. We will choose XML as a structural property and a way to present written values ?? when inserting data (we'll see later). If you have such requirements, you can choose the changes to be applied in different environments (development, staging, quality assurance). An example of this is collecting some static data during the testing process instead of doing it in a production environment.
Liquibase Concepts
There are very few things to remember.
databaseChangeLog: This is where all the changes are specified. An empty databaseChangeLog looks like
<?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">
</databaseChangeLog>
ChangeSets: These are atomic changes and will be applied to the database. Each change group is uniquely identified by the file identifier that identifies the change group, author, and package. You may only need to make one or several changes to the change group. Each change group is triggered by Liquibase as a single transaction. It might look like an example of a change group
<changeSet id="01" author="hhimanshu">
<createTable tableName="book"
remarks="A table to contain all books">
<column name="id" type="int">
<constraints nullable="false" unique="true" primaryKey="true"/>
</column>
<column name="name" type="varchar(255)">
<constraints nullable="false" unique="true"/>
</column>
<column name="authors" type="int">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="authors"
remarks="A table to contain all the authors">
<column name="id" type="int">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="name" type="varchar(100)">
<constraints nullable="false"/>
</column>
</createTable>
Here in this sample, we are building 2 different tables as part of a single changeset.
DATABASECHANGELOG keeps reports of what all changesets have been applied to the database so far. A typical table may look like
Defining Changesets
The changesets could be anything similar to database developments, for example, create the table, insert into, alter table. Some of the examples are
creating a table and applying constraints at the column level
<createTable tableName="authors"
remarks="A table to contain all the authors">
<column name="id" type="int">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="name" type="varchar(100)">
<constraints nullable="false"/>
</column>
</createTable>
adding a foreign key constraint
<addForeignKeyConstraint baseTableName="books" baseColumnNames="author"
constraintName="author_fk"
referencedTableName="authors" referencedColumnNames="id"/>
inserting data into the table
<insert tableName="books">
<column name="id" valueNumeric="1"/>
<column name="name" value="book_01_a_01"/>
<column name="author" valueNumeric="01"/>
</insert>
How Liquibase integrate with Spring-boot
Now we are using the power of Liquibase with Spring-Boot.
Spring-boot give us the support for both Flyway and Liquibase out of the box
add the dependencies. If using maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
To organize the change set, I tend to save the change set in a separate file and use the include tag in my ChangeCog database to include it. For example, in my code base, I use it as
<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">
<include file="changelog/create-books-and-author-schema.xml" relativeToChangelogFile="true"/>
<include file="changelog/insert-data-authors.xml" relativeToChangelogFile="true"/>
<include file="changelog/insert-data-books.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
This way when Spring-boot application starts, it knows where is the starting point for your database changelog is
Additionally, you may want to add the following code in the propeties file
spring.jpa.hibernate.ddl-auto=none
spring.h2.console.enabled=true
The first line says Spring-boot to not create the database by hibernating then after this because Liquibase comes into picture and does this work for us.
That's it for now.
Thanks,
Abhishek Kumar