Datenbank-Migrationen sind ein kritischer Bestandteil moderner Softwareentwicklung. Jede Änderung am Schema muss nachvollziehbar, reproduzierbar und rückgängig machbar sein. Während Flyway auf nummerierte SQL-Dateien setzt, verfolgt Liquibase einen deklarativen Ansatz: Änderungen werden in Changeset-Dateien in den Formaten YAML, XML, JSON oder SQL beschrieben.
Warum Liquibase?
Liquibase hat gegenüber Flyway einige entscheidende Vorteile:
- Datenbankunabhängigkeit — ein Changeset kann (mit Einschränkungen) gegen PostgreSQL, MySQL, Oracle und MSSQL ausgeführt werden
- Rollback-Unterstützung — Liquibase kann Änderungen automatisch oder manuell zurücksetzen
- Mehrere Formate — YAML, XML, JSON oder SQL als Changeset-Format
- Preconditions — Bedingungen, die vor der Ausführung geprüft werden
- Contexts und Labels — Migrationen lassen sich zielgerichtet auf bestimmte Umgebungen anwenden
Integration mit Spring Boot 4.1
In Spring Boot 4.1 ist Liquibase per Auto-Configuration integriert. Sobald liquibase-core auf dem Classpath liegt, führt Spring Boot beim Start automatisch liquibase update aus:
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
Code-Sprache: HTML, XML (xml)
<em># application.yml</em>
spring:
liquibase:
change-log: classpath:db/changelog/db.changelog-master.yaml
enabled: true
Code-Sprache: HTML, XML (xml)
Die Master-Changelog-Datei referenziert alle einzelnen Changesets:
<em># db.changelog-master.yaml</em>
databaseChangeLog:
- include:
file: db/changelog/001-create-users.yaml
- include:
file: db/changelog/002-add-email-column.yaml
- include:
file: db/changelog/003-create-orders.sql
Code-Sprache: PHP (php)
Changesets in YAML
YAML ist das am einfachsten lesbare Format für Liquibase-Changesets:
<em># 001-create-users.yaml</em>
databaseChangeLog:
- changeSet:
id: 1
author: rene
changes:
- createTable:
tableName: users
columns:
- column:
name: id
type: BIGINT
autoIncrement: true
constraints:
primaryKey: true
- column:
name: username
type: VARCHAR(255)
constraints:
nullable: false
unique: true
- column:
name: created_at
type: TIMESTAMP
defaultValueComputed: CURRENT_TIMESTAMP
Code-Sprache: PHP (php)
Rollbacks
Ein Rollback beschreibt, wie eine Migration rückgängig gemacht wird:
- changeSet:
id: 2
author: rene
changes:
- addColumn:
tableName: users
columns:
- column:
name: email
type: VARCHAR(320)
rollback:
- dropColumn:
tableName: users
columnName: email
Bei einfachen Änderungen wie createTable generiert Liquibase das Rollback automatisch. Bei komplexeren Operationen muss es explizit definiert werden.
SQL-basierte Changesets
Auch purer SQL-Code lässt sich verwenden — mit allen Vorteilen des Liquibase-Trackings:
<em>-- 002-add-index.sql</em>
<em>-- liquibase formatted sql</em>
<em>-- changeset rene:3</em>
CREATE INDEX idx_users_email ON users(email);
<em>-- rollback DROP INDEX idx_users_email;</em>
Code-Sprache: HTML, XML (xml)
Wichtig: Der Kommentar -- liquibase formatted sql teilt Liquibase mit, dass die SQL-Datei Changeset-Metadaten enthält.
Preconditions
Preconditions verhindern, dass Migrationen unter falschen Voraussetzungen ausgeführt werden:
- changeSet:
id: 4
author: rene
preConditions:
- onFail: HALT
- tableExists:
tableName: users
- not:
columnExists:
tableName: users
columnName: phone
changes:
- addColumn:
tableName: users
columns:
- column:
name: phone
type: VARCHAR(20)
Mit onFail: HALT, MARK_RAN oder CONTINUE steuert man das Verhalten, falls die Vorbedingung nicht erfüllt ist.
Kontextabhängige Migrationen
Contexts und Labels erlauben migrationsspezifische Ausführungen je nach Umgebung:
- changeSet:
id: 5
author: rene
context: dev
labels: seed
changes:
- insert:
tableName: users
columns:
- column:
name: username
value: "testuser"
- column:
name: email
value: "test@example.com"
Code-Sprache: JavaScript (javascript)
<em># Nur Changesets mit dem Kontext "dev" ausführen</em>
mvn liquibase:update -Dliquibase.contextFilter=dev
<em># Changesets mit Label "seed" ausschließen</em>
mvn liquibase:update -Dliquibase.labelFilter=!seed
Code-Sprache: HTML, XML (xml)
Fazit
Liquibase ist die ideale Wahl, wenn du datenbankunabhängige, deklarativ beschriebene Migrationen mit vollständiger Rollback-Fähigkeit benötigst. Die Unterstützung für YAML-Changelogs macht Changesets besonders lesbar und diff-bar, während Contexts und Preconditions die Steuerung in komplexen Deployment-Pipelines erlauben. In Spring Boot 4.1 ist Liquibase per Autokonfiguration sofort einsatzbereit — sobald liquibase-core auf dem Classpath liegt, werden Migrationen beim Anwendungsstart automatisch ausgeführt.