Database Migrations in Java: Why You Need Them and How They Work
Developing any serious application in Java is inextricably linked to the evolution of the database schema. Adding new fields, changing data types, creating indexes — all of this is inevitable as a project develops. Manually executing SQL scripts in different environments (local development environment, test bench, production) quickly leads to chaos: scripts get lost, are executed in the wrong order, and one team's database differs from another's. The solution to this problem is database migrations.
Migrations allow you to version schema changes, automatically apply them in the correct sequence, and roll them back if necessary. In the Java world, there are two undisputed leaders in this area: Flyway and Liquibase. Let's take a closer look at them.
Flyway: Simplicity and Reliability
Flyway is a lightweight, simple, and powerful migration tool. Its philosophy is: "Migrations are just SQL or Java classes." The main operating principles are:
- Versioning: each migration file has a unique version number (e.g.,
V1__create_users.sql,V2__add_email.sql). - Execution order: Flyway tracks applied migrations in a special table (
flyway_schema_history) and only applies new ones. - Two types of migrations: SQL scripts and Java migrations (for complex logic).
- Rollback: supports "undo" migrations (in the paid version) or manual writing of rollback scripts.
Example of working with Flyway
Suppose you need to create a users table. You create a file db/migration/V1__create_users.sql:
CREATE TABLE users ( id BIGINT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);Then you add a second migration V2__add_age.sql:
ALTER TABLE users ADD COLUMN age INT;Connecting Flyway to a Spring Boot application is done via application.properties:
spring.flyway.enabled=truespring.flyway.locations=classpath:db/migrationspring.datasource.url=jdbc:postgresql://localhost:5432/mydbspring.datasource.username=userspring.datasource.password=passWhen the application starts, Flyway will check the history table and apply all new migrations. If a migration has already been executed, it will be skipped.
Liquibase: Flexibility and Control
Liquibase is a more flexible and powerful tool that supports several formats for describing changes: XML, YAML, JSON, and SQL. Its key feature is changesets.
- Unique identifier: each changeset has an
idand anauthor. - Automatic SQL generation: Liquibase can generate SQL for a specific DBMS (PostgreSQL, MySQL, Oracle, etc.).
- Contexts: you can separate migrations for different environments (dev, test, prod).
- Rollback: each changeset can have a rollback instruction (
rollback).
Example of working with Liquibase
Example of a changeset in XML format (db/changelog/db.changelog-master.xml):
<?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-4.9.xsd">
<changeSet id="1" author="pythonlib"> < Also in library
Cryptography in Kotlin: Encryption and Hashing
Authorization and Authentication in Swift: A Complete Guide for iOS/macOS
Working with Dates in TypeScript: Popular Libraries and Examples
MongoDB.Driver for C# (.NET): Complete Guide with Examples
Object Serialization in C++: Libraries, Methods, and Code Examples