Liquibase
Introducción
Liquibase es una herramienta de control de versiones para bases de datos que permite:
- Gestionar cambios incrementales en la estructura de la base de datos
- Mantener un historial completo de modificaciones
- Sincronizar cambios entre diferentes entornos
- Realizar rollbacks de manera segura
- Trabajar con múltiples formatos (YAML, XML, JSON, SQL)
Estructura de Archivos
La estructura de archivos sigue una organización jerárquica:
src/main/resources/
├── db/
│ ├── changelog/ # Directorio principal de Liquibase
│ │ ├── changes/ # Cambios individuales
│ │ │ ├── 01-create-users-table.yaml # Tabla de usuarios
│ │ │ ├── 02-create-roles-table.yaml # Tabla de roles
│ │ │ └── 03-create-privileges-table.yaml # Tabla de privilegios
│ │ └── db.changelog-master.yaml # Archivo maestro
│ └── scripts/ # Scripts SQL adicionales
│ └── initial-data.sql # Datos iniciales
Explicación de cada directorio:
/changelog
: Contiene toda la configuración de Liquibase/changes
: Almacena los changesets individuales/scripts
: Scripts SQL para datos iniciales o migraciones complejas
Configuración Detallada
El archivo application.yml
controla el comportamiento de Liquibase:
spring:
liquibase:
change-log: classpath:db/changelog/db.changelog-master.yaml # Ubicación del changelog principal
enabled: true # Activar/desactivar Liquibase
drop-first: false # Si debe eliminar schema al inicio
contexts: development # Contexto de ejecución
default-schema: public # Schema por defecto
parameters: # Parámetros personalizados
table-prefix: app_ # Ejemplo de prefijo para tablas
labels: "version-1" # Etiquetas para filtrar changesets
Changelog Master
El archivo maestro organiza la ejecución de los cambios:
databaseChangeLog:
# Configuración global
- property:
name: table.prefix
value: app_
# Precondiciones globales
- preConditions:
- runningAs:
username: db_admin
# Inclusión de changesets
- include:
file: changes/01-create-users-table.yaml
relativeToChangelogFile: true
context: "!prod" # No ejecutar en producción
# Más includes con configuración específica
- include:
file: changes/02-create-roles-table.yaml
relativeToChangelogFile: true
labels: "schema-setup"
Buenas Prácticas
-
Versionado:
- Usar prefijos numéricos en los archivos de cambios
- Nunca modificar changelogs ya ejecutados
- Un cambio por archivo para mejor trazabilidad
-
Nombrado:
- Nombres descriptivos para los archivos
- IDs únicos para cada changeset
- Incluir el autor en cada changeset
-
Organización:
- Separar cambios estructurales de datos
- Mantener un changelog master limpio
- Agrupar cambios relacionados
-
Rollback:
- Incluir siempre secciones de rollback
- Probar los rollbacks antes de desplegar
- Documentar cambios que no son reversibles
Comandos Avanzados
# Comandos básicos
./mvnw liquibase:update # Actualizar BD
./mvnw liquibase:rollback # Rollback
./mvnw liquibase:status # Ver estado
# Comandos avanzados
./mvnw liquibase:diff # Comparar esquemas
./mvnw liquibase:generateChangeLog # Generar changelog
./mvnw liquibase:clearCheckSums # Limpiar checksums
# Opciones específicas
./mvnw liquibase:update -Dliquibase.contexts=test # Contexto específico
./mvnw liquibase:rollback -Dliquibase.rollbackTag=v1.0 # Rollback a tag
Integración con Spring Boot
Configuración Avanzada
spring:
liquibase:
enabled: true
drop-first: false
change-log: classpath:db/changelog/db.changelog-master.yaml
contexts: development
default-schema: public
parameters:
app.name: myapp
app.version: 1.0.0
labels: "version-1,schema-update"
rollback-file: rollback-script.sql
test-rollback: true
database-change-log-lock-table: DATABASECHANGELOGLOCK
database-change-log-table: DATABASECHANGELOG
Eventos del Ciclo de Vida
@Component
public class LiquibaseCustomizer {
@EventListener
public void onLiquibaseStart(LiquibaseStartEvent event) {
// Personalización antes de la ejecución
}
@EventListener
public void onLiquibaseEnd(LiquibaseEndEvent event) {
// Limpieza después de la ejecución
}
}