☕ 🚀 Database Migrations in TuskLang Java

Java Documentation

🚀 Database Migrations in TuskLang Java

"We don't bow to any king" - Migrate your database like a Java master

TuskLang Java provides sophisticated database migration capabilities that integrate seamlessly with Spring Boot, JPA, and modern Java patterns. Create, manage, and execute database migrations with enterprise-grade reliability and version control.

🎯 Overview

Database migrations in TuskLang Java combine the power of Java migration technologies with TuskLang's configuration system. From JPA schema generation to Spring Boot Flyway integration, we'll show you how to build robust, scalable migration systems.

🔧 Core Migration Features

1. JPA Schema Migrations

import org.tusklang.java.TuskLang;
import org.tusklang.java.migrations.TuskJPAMigrationManager;
import javax.persistence.*;
import java.util.Map;
import java.util.List;

@Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) private String name; @Column(unique = true, nullable = false) private String email; @Column(name = "created_at") private java.time.LocalDateTime createdAt; // Constructors, getters, setters public User() {} public User(String name, String email) { this.name = name; this.email = email; this.createdAt = java.time.LocalDateTime.now(); } // Getters and setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public java.time.LocalDateTime getCreatedAt() { return createdAt; } public void setCreatedAt(java.time.LocalDateTime createdAt) { this.createdAt = createdAt; } }

public class JPAMigrationExample { public static void main(String[] args) { TuskLang parser = new TuskLang(); String tskContent = """ [jpa_migrations] # JPA Schema Migration Configuration enable_schema_generation: true enable_schema_validation: true enable_schema_update: true [schema_config] # Schema configuration create_schema: true drop_schema: false validate_schema: true update_schema: true [migration_001_initial_schema] # Initial schema migration version: "001" description: "Create initial database schema" environment: ["development", "test", "staging", "production"] up_method: """ function migrateUp(entityManager) { // Create users table entityManager.createNativeQuery(""" CREATE TABLE IF NOT EXISTS users ( id BIGINT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) """).executeUpdate(); // Create orders table entityManager.createNativeQuery(""" CREATE TABLE IF NOT EXISTS orders ( id BIGINT AUTO_INCREMENT PRIMARY KEY, user_id BIGINT NOT NULL, total_amount DECIMAL(10,2) NOT NULL, status VARCHAR(50) DEFAULT 'pending', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ) """).executeUpdate(); // Create posts table entityManager.createNativeQuery(""" CREATE TABLE IF NOT EXISTS posts ( id BIGINT AUTO_INCREMENT PRIMARY KEY, author_id BIGINT NOT NULL, title VARCHAR(255) NOT NULL, content TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (author_id) REFERENCES users(id) ) """).executeUpdate(); return 3; // Number of tables created } """ down_method: """ function migrateDown(entityManager) { // Drop tables in reverse order entityManager.createNativeQuery("DROP TABLE IF EXISTS posts").executeUpdate(); entityManager.createNativeQuery("DROP TABLE IF EXISTS orders").executeUpdate(); entityManager.createNativeQuery("DROP TABLE IF EXISTS users").executeUpdate(); return 3; // Number of tables dropped } """ [migration_002_add_user_roles] # Add user roles migration version: "002" description: "Add user roles and permissions" environment: ["development", "test", "staging", "production"] up_method: """ function migrateUp(entityManager) { // Create roles table entityManager.createNativeQuery(""" CREATE TABLE IF NOT EXISTS roles ( id BIGINT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) UNIQUE NOT NULL, description TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) """).executeUpdate(); // Create user_roles junction table entityManager.createNativeQuery(""" CREATE TABLE IF NOT EXISTS user_roles ( user_id BIGINT NOT NULL, role_id BIGINT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (user_id, role_id), FOREIGN KEY (user_id) REFERENCES users(id), FOREIGN KEY (role_id) REFERENCES roles(id) ) """).executeUpdate(); // Insert default roles entityManager.createNativeQuery(""" INSERT INTO roles (name, description) VALUES ('user', 'Regular user'), ('admin', 'Administrator'), ('moderator', 'Content moderator') """).executeUpdate(); return 2; // Number of tables created } """ down_method: """ function migrateDown(entityManager) { // Drop tables in reverse order entityManager.createNativeQuery("DROP TABLE IF EXISTS user_roles").executeUpdate(); entityManager.createNativeQuery("DROP TABLE IF EXISTS roles").executeUpdate(); return 2; // Number of tables dropped } """ [migration_003_add_indexes] # Add database indexes migration version: "003" description: "Add performance indexes" environment: ["development", "test", "staging", "production"] up_method: """ function migrateUp(entityManager) { // Add indexes for better performance entityManager.createNativeQuery(""" CREATE INDEX IF NOT EXISTS idx_users_email ON users(email) """).executeUpdate(); entityManager.createNativeQuery(""" CREATE INDEX IF NOT EXISTS idx_orders_user_id ON orders(user_id) """).executeUpdate(); entityManager.createNativeQuery(""" CREATE INDEX IF NOT EXISTS idx_orders_status ON orders(status) """).executeUpdate(); entityManager.createNativeQuery(""" CREATE INDEX IF NOT EXISTS idx_posts_author_id ON posts(author_id) """).executeUpdate(); entityManager.createNativeQuery(""" CREATE INDEX IF NOT EXISTS idx_posts_created_at ON posts(created_at) """).executeUpdate(); return 5; // Number of indexes created } """ down_method: """ function migrateDown(entityManager) { // Drop indexes entityManager.createNativeQuery("DROP INDEX IF EXISTS idx_posts_created_at").executeUpdate(); entityManager.createNativeQuery("DROP INDEX IF EXISTS idx_posts_author_id").executeUpdate(); entityManager.createNativeQuery("DROP INDEX IF EXISTS idx_orders_status").executeUpdate(); entityManager.createNativeQuery("DROP INDEX IF EXISTS idx_orders_user_id").executeUpdate(); entityManager.createNativeQuery("DROP INDEX IF EXISTS idx_users_email").executeUpdate(); return 5; // Number of indexes dropped } """ """; Map<String, Object> config = parser.parse(tskContent); // Initialize JPA migration manager TuskJPAMigrationManager jpaMigrationManager = new TuskJPAMigrationManager(); jpaMigrationManager.configure(config); // Execute migrations int tablesCreated = jpaMigrationManager.migrateUp("migration_001_initial_schema"); int rolesAdded = jpaMigrationManager.migrateUp("migration_002_add_user_roles"); int indexesAdded = jpaMigrationManager.migrateUp("migration_003_add_indexes"); System.out.println("Migration 001: Created " + tablesCreated + " tables"); System.out.println("Migration 002: Added " + rolesAdded + " role tables"); System.out.println("Migration 003: Added " + indexesAdded + " indexes"); // Rollback if needed // jpaMigrationManager.migrateDown("migration_003_add_indexes"); } }

2. Spring Boot Flyway Integration

import org.tusklang.java.TuskLang;
import org.tusklang.java.migrations.TuskFlywayMigrationManager;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.Map;
import java.util.List;

@SpringBootApplication public class FlywayMigrationExample { public static void main(String[] args) { TuskLang parser = new TuskLang(); String tskContent = """ [flyway_migrations] # Flyway Migration Configuration enable_flyway: true enable_baseline: true enable_clean: false [flyway_config] # Flyway configuration locations: ["classpath:db/migration"] baseline_on_migrate: true validate_on_migrate: true out_of_order: false [migration_001_initial_schema] # Initial schema migration version: "001" description: "Create initial database schema" sql_file: "V001__Create_initial_schema.sql" sql_content: """ -- Create users table CREATE TABLE IF NOT EXISTS users ( id BIGINT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Create orders table CREATE TABLE IF NOT EXISTS orders ( id BIGINT AUTO_INCREMENT PRIMARY KEY, user_id BIGINT NOT NULL, total_amount DECIMAL(10,2) NOT NULL, status VARCHAR(50) DEFAULT 'pending', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ); -- Create posts table CREATE TABLE IF NOT EXISTS posts ( id BIGINT AUTO_INCREMENT PRIMARY KEY, author_id BIGINT NOT NULL, title VARCHAR(255) NOT NULL, content TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (author_id) REFERENCES users(id) ); """ [migration_002_add_user_roles] # Add user roles migration version: "002" description: "Add user roles and permissions" sql_file: "V002__Add_user_roles.sql" sql_content: """ -- Create roles table CREATE TABLE IF NOT EXISTS roles ( id BIGINT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) UNIQUE NOT NULL, description TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Create user_roles junction table CREATE TABLE IF NOT EXISTS user_roles ( user_id BIGINT NOT NULL, role_id BIGINT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (user_id, role_id), FOREIGN KEY (user_id) REFERENCES users(id), FOREIGN KEY (role_id) REFERENCES roles(id) ); -- Insert default roles INSERT INTO roles (name, description) VALUES ('user', 'Regular user'), ('admin', 'Administrator'), ('moderator', 'Content moderator'); """ [migration_003_add_user_profile] # Add user profile migration version: "003" description: "Add user profile information" sql_file: "V003__Add_user_profile.sql" sql_content: """ -- Add profile columns to users table ALTER TABLE users ADD COLUMN bio TEXT; ALTER TABLE users ADD COLUMN avatar VARCHAR(255); ALTER TABLE users ADD COLUMN phone VARCHAR(20); ALTER TABLE users ADD COLUMN date_of_birth DATE; -- Create user_profiles table for extended profile data CREATE TABLE IF NOT EXISTS user_profiles ( id BIGINT AUTO_INCREMENT PRIMARY KEY, user_id BIGINT UNIQUE NOT NULL, bio TEXT, avatar VARCHAR(255), phone VARCHAR(20), date_of_birth DATE, location VARCHAR(255), website VARCHAR(255), social_links JSON, preferences JSON, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ); """ [migration_004_add_audit_tables] # Add audit tables migration version: "004" description: "Add audit and logging tables" sql_file: "V004__Add_audit_tables.sql" sql_content: """ -- Create audit_log table CREATE TABLE IF NOT EXISTS audit_log ( id BIGINT AUTO_INCREMENT PRIMARY KEY, user_id BIGINT, action VARCHAR(100) NOT NULL, table_name VARCHAR(100), record_id BIGINT, old_values JSON, new_values JSON, ip_address VARCHAR(45), user_agent TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ); -- Create system_log table CREATE TABLE IF NOT EXISTS system_log ( id BIGINT AUTO_INCREMENT PRIMARY KEY, level VARCHAR(20) NOT NULL, message TEXT NOT NULL, stack_trace TEXT, context JSON, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Add indexes for audit tables CREATE INDEX idx_audit_log_user_id ON audit_log(user_id); CREATE INDEX idx_audit_log_action ON audit_log(action); CREATE INDEX idx_audit_log_created_at ON audit_log(created_at); CREATE INDEX idx_system_log_level ON system_log(level); CREATE INDEX idx_system_log_created_at ON system_log(created_at); """ [flyway_methods] # Flyway migration methods execute_flyway_migration: """ function executeFlywayMigration(migrationName) { let flyway = new Flyway(); flyway.setDataSource(dataSource); flyway.setLocations("classpath:db/migration"); flyway.setBaselineOnMigrate(true); flyway.setValidateOnMigrate(true); // Execute migration let result = flyway.migrate(); return { applied: result.applied, target: result.target, executionTime: result.executionTime }; } """ create_migration_file: """ function createMigrationFile(version, description, sqlContent) { let fileName = "V" + version + "__" + description.replace(/[^a-zA-Z0-9]/g, "_") + ".sql"; let filePath = "src/main/resources/db/migration/" + fileName; // Write SQL content to file writeFile(filePath, sqlContent); return { fileName: fileName, filePath: filePath, version: version, description: description }; } """ validate_migration: """ function validateMigration(migrationName) { let flyway = new Flyway(); flyway.setDataSource(dataSource); flyway.setLocations("classpath:db/migration"); // Validate migrations let validationResult = flyway.validate(); return { valid: validationResult.errorDetails === null, errors: validationResult.errorDetails, warnings: validationResult.warningDetails }; } """ """; Map<String, Object> config = parser.parse(tskContent); // Initialize Flyway migration manager TuskFlywayMigrationManager flywayMigrationManager = new TuskFlywayMigrationManager(); flywayMigrationManager.configure(config); // Create migration files Map<String, Object> migration1 = flywayMigrationManager.createMigrationFile("flyway_methods", "create_migration_file", Map.of( "version", "001", "description", "Create initial schema", "sqlContent", config.get("migration_001_initial_schema.sql_content") )); Map<String, Object> migration2 = flywayMigrationManager.createMigrationFile("flyway_methods", "create_migration_file", Map.of( "version", "002", "description", "Add user roles", "sqlContent", config.get("migration_002_add_user_roles.sql_content") )); Map<String, Object> migration3 = flywayMigrationManager.createMigrationFile("flyway_methods", "create_migration_file", Map.of( "version", "003", "description", "Add user profile", "sqlContent", config.get("migration_003_add_user_profile.sql_content") )); Map<String, Object> migration4 = flywayMigrationManager.createMigrationFile("flyway_methods", "create_migration_file", Map.of( "version", "004", "description", "Add audit tables", "sqlContent", config.get("migration_004_add_audit_tables.sql_content") )); // Execute migrations Map<String, Object> result1 = flywayMigrationManager.executeMigration("flyway_methods", "execute_flyway_migration", Map.of("migrationName", "001")); Map<String, Object> result2 = flywayMigrationManager.executeMigration("flyway_methods", "execute_flyway_migration", Map.of("migrationName", "002")); Map<String, Object> result3 = flywayMigrationManager.executeMigration("flyway_methods", "execute_flyway_migration", Map.of("migrationName", "003")); Map<String, Object> result4 = flywayMigrationManager.executeMigration("flyway_methods", "execute_flyway_migration", Map.of("migrationName", "004")); // Validate migrations Map<String, Object> validation = flywayMigrationManager.validateMigration("flyway_methods", "validate_migration", Map.of("migrationName", "all")); System.out.println("Created migration files:"); System.out.println("- " + migration1.get("fileName")); System.out.println("- " + migration2.get("fileName")); System.out.println("- " + migration3.get("fileName")); System.out.println("- " + migration4.get("fileName")); System.out.println("Migration results:"); System.out.println("Migration 001: " + result1.get("applied") + " applied"); System.out.println("Migration 002: " + result2.get("applied") + " applied"); System.out.println("Migration 003: " + result3.get("applied") + " applied"); System.out.println("Migration 004: " + result4.get("applied") + " applied"); System.out.println("Validation result: " + validation.get("valid")); } }

3. Data Migrations

import org.tusklang.java.TuskLang;
import org.tusklang.java.migrations.TuskDataMigrationManager;
import java.util.Map;
import java.util.List;

public class DataMigrationExample { public static void main(String[] args) { TuskLang parser = new TuskLang(); String tskContent = """ [data_migrations] # Data Migration Configuration enable_data_migration: true enable_data_validation: true enable_rollback_support: true [data_migration_001_seed_default_data] # Seed default data migration version: "001" description: "Seed default application data" environment: ["development", "test", "staging"] up_method: """ function migrateUp(entityManager) { let inserted = 0; // Insert default roles let roles = [ { name: 'user', description: 'Regular user' }, { name: 'admin', description: 'Administrator' }, { name: 'moderator', description: 'Content moderator' } ]; for (let role of roles) { let existingRole = entityManager.createQuery("SELECT r FROM Role r WHERE r.name = :name") .setParameter("name", role.name) .getResultList(); if (existingRole.length === 0) { let newRole = new Role(role.name, role.description); entityManager.persist(newRole); inserted++; } } // Insert default users let users = [ { name: 'System Admin', email: 'admin@example.com', role: 'admin' }, { name: 'Default User', email: 'user@example.com', role: 'user' } ]; for (let userData of users) { let existingUser = entityManager.createQuery("SELECT u FROM User u WHERE u.email = :email") .setParameter("email", userData.email) .getResultList(); if (existingUser.length === 0) { let user = new User(userData.name, userData.email); entityManager.persist(user); // Assign role let role = entityManager.createQuery("SELECT r FROM Role r WHERE r.name = :name") .setParameter("name", userData.role) .getSingleResult(); user.getRoles().add(role); inserted++; } } return inserted; } """ down_method: """ function migrateDown(entityManager) { let deleted = 0; // Delete default users let defaultEmails = ['admin@example.com', 'user@example.com']; for (let email of defaultEmails) { let users = entityManager.createQuery("SELECT u FROM User u WHERE u.email = :email") .setParameter("email", email) .getResultList(); for (let user of users) { entityManager.remove(user); deleted++; } } // Delete default roles let defaultRoles = ['user', 'admin', 'moderator']; for (let roleName of defaultRoles) { let roles = entityManager.createQuery("SELECT r FROM Role r WHERE r.name = :name") .setParameter("name", roleName) .getResultList(); for (let role of roles) { entityManager.remove(role); deleted++; } } return deleted; } """ [data_migration_002_migrate_user_data] # Migrate user data structure version: "002" description: "Migrate user data to new structure" environment: ["development", "test", "staging", "production"] up_method: """ function migrateUp(entityManager) { let migrated = 0; // Get all users without profiles let users = entityManager.createQuery("SELECT u FROM User u WHERE u.profile IS NULL") .getResultList(); for (let user of users) { // Create user profile let profile = new UserProfile(); profile.setUser(user); profile.setBio(user.getBio() || ""); profile.setAvatar(user.getAvatar() || ""); profile.setPhone(user.getPhone() || ""); profile.setDateOfBirth(user.getDateOfBirth()); entityManager.persist(profile); user.setProfile(profile); migrated++; } return migrated; } """ down_method: """ function migrateDown(entityManager) { let reverted = 0; // Get all user profiles let profiles = entityManager.createQuery("SELECT p FROM UserProfile p") .getResultList(); for (let profile of profiles) { let user = profile.getUser(); // Restore data to user table user.setBio(profile.getBio()); user.setAvatar(profile.getAvatar()); user.setPhone(profile.getPhone()); user.setDateOfBirth(profile.getDateOfBirth()); user.setProfile(null); entityManager.remove(profile); reverted++; } return reverted; } """ [data_migration_003_update_order_statuses] # Update order status values version: "003" description: "Update order status values to new format" environment: ["development", "test", "staging", "production"] up_method: """ function migrateUp(entityManager) { let updated = 0; // Update old status values to new format let statusUpdates = [ { old: 'pending', new: 'PENDING' }, { old: 'processing', new: 'PROCESSING' }, { old: 'completed', new: 'COMPLETED' }, { old: 'cancelled', new: 'CANCELLED' }, { old: 'refunded', new: 'REFUNDED' } ]; for (let update of statusUpdates) { let orders = entityManager.createQuery("SELECT o FROM Order o WHERE o.status = :oldStatus") .setParameter("oldStatus", update.old) .getResultList(); for (let order of orders) { order.setStatus(update.new); updated++; } } return updated; } """ down_method: """ function migrateDown(entityManager) { let reverted = 0; // Revert status values to old format let statusReverts = [ { new: 'PENDING', old: 'pending' }, { new: 'PROCESSING', old: 'processing' }, { new: 'COMPLETED', old: 'completed' }, { new: 'CANCELLED', old: 'cancelled' }, { new: 'REFUNDED', old: 'refunded' } ]; for (let revert of statusReverts) { let orders = entityManager.createQuery("SELECT o FROM Order o WHERE o.status = :newStatus") .setParameter("newStatus", revert.new) .getResultList(); for (let order of orders) { order.setStatus(revert.old); reverted++; } } return reverted; } """ [data_migration_methods] # Data migration methods execute_data_migration: """ function executeDataMigration(migrationName) { let migration = @data_migrations[migrationName]; let entityManager = getEntityManager(); try { entityManager.getTransaction().begin(); let result = migration.up_method(entityManager); entityManager.getTransaction().commit(); return { success: true, migrated: result, migration: migrationName }; } catch (error) { entityManager.getTransaction().rollback(); return { success: false, error: error.message, migration: migrationName }; } } """ rollback_data_migration: """ function rollbackDataMigration(migrationName) { let migration = @data_migrations[migrationName]; let entityManager = getEntityManager(); try { entityManager.getTransaction().begin(); let result = migration.down_method(entityManager); entityManager.getTransaction().commit(); return { success: true, reverted: result, migration: migrationName }; } catch (error) { entityManager.getTransaction().rollback(); return { success: false, error: error.message, migration: migrationName }; } } """ validate_data_migration: """ function validateDataMigration(migrationName) { let migration = @data_migrations[migrationName]; let entityManager = getEntityManager(); // Validate migration can be executed try { // Test migration logic without committing entityManager.getTransaction().begin(); // Execute validation logic here let isValid = true; let errors = []; entityManager.getTransaction().rollback(); return { valid: isValid, errors: errors, migration: migrationName }; } catch (error) { entityManager.getTransaction().rollback(); return { valid: false, errors: [error.message], migration: migrationName }; } } """ """; Map<String, Object> config = parser.parse(tskContent); // Initialize data migration manager TuskDataMigrationManager dataMigrationManager = new TuskDataMigrationManager(); dataMigrationManager.configure(config); // Execute data migrations Map<String, Object> result1 = dataMigrationManager.executeDataMigration("data_migration_methods", "execute_data_migration", Map.of("migrationName", "data_migration_001_seed_default_data")); Map<String, Object> result2 = dataMigrationManager.executeDataMigration("data_migration_methods", "execute_data_migration", Map.of("migrationName", "data_migration_002_migrate_user_data")); Map<String, Object> result3 = dataMigrationManager.executeDataMigration("data_migration_methods", "execute_data_migration", Map.of("migrationName", "data_migration_003_update_order_statuses")); // Validate migrations Map<String, Object> validation1 = dataMigrationManager.validateMigration("data_migration_methods", "validate_data_migration", Map.of("migrationName", "data_migration_001_seed_default_data")); Map<String, Object> validation2 = dataMigrationManager.validateMigration("data_migration_methods", "validate_data_migration", Map.of("migrationName", "data_migration_002_migrate_user_data")); Map<String, Object> validation3 = dataMigrationManager.validateMigration("data_migration_methods", "validate_data_migration", Map.of("migrationName", "data_migration_003_update_order_statuses")); System.out.println("Data Migration Results:"); System.out.println("Migration 001: " + (result1.get("success") ? "Success" : "Failed") + " (" + result1.get("migrated") + " records)"); System.out.println("Migration 002: " + (result2.get("success") ? "Success" : "Failed") + " (" + result2.get("migrated") + " records)"); System.out.println("Migration 003: " + (result3.get("success") ? "Success" : "Failed") + " (" + result3.get("migrated") + " records)"); System.out.println("Validation Results:"); System.out.println("Migration 001: " + (validation1.get("valid") ? "Valid" : "Invalid")); System.out.println("Migration 002: " + (validation2.get("valid") ? "Valid" : "Invalid")); System.out.println("Migration 003: " + (validation3.get("valid") ? "Valid" : "Invalid")); } }

4. Migration Version Control

import org.tusklang.java.TuskLang;
import org.tusklang.java.migrations.TuskMigrationVersionControl;
import java.util.Map;
import java.util.List;

public class MigrationVersionControlExample { public static void main(String[] args) { TuskLang parser = new TuskLang(); String tskContent = """ [migration_version_control] # Migration Version Control Configuration enable_version_tracking: true enable_migration_history: true enable_rollback_tracking: true [version_control_config] # Version control configuration version_table: "migration_versions" history_table: "migration_history" enable_checksums: true enable_timestamps: true [migration_versions] # Migration version definitions version_001: { version: "001" description: "Initial schema" checksum: "abc123" applied_at: "2024-01-01 10:00:00" environment: "development" } version_002: { version: "002" description: "Add user roles" checksum: "def456" applied_at: "2024-01-02 11:00:00" environment: "development" } version_003: { version: "003" description: "Add user profile" checksum: "ghi789" applied_at: "2024-01-03 12:00:00" environment: "development" } version_004: { version: "004" description: "Add audit tables" checksum: "jkl012" applied_at: "2024-01-04 13:00:00" environment: "development" } [version_control_methods] # Version control methods track_migration: """ function trackMigration(version, description, checksum) { let entityManager = getEntityManager(); let migrationVersion = new MigrationVersion(); migrationVersion.setVersion(version); migrationVersion.setDescription(description); migrationVersion.setChecksum(checksum); migrationVersion.setAppliedAt(new Date()); migrationVersion.setEnvironment(@env("SPRING_PROFILES_ACTIVE", "development")); entityManager.persist(migrationVersion); // Add to history let history = new MigrationHistory(); history.setVersion(version); history.setDescription(description); history.setAction("APPLY"); history.setTimestamp(new Date()); history.setEnvironment(@env("SPRING_PROFILES_ACTIVE", "development")); entityManager.persist(history); return { version: version, applied: true, timestamp: new Date() }; } """ get_migration_status: """ function getMigrationStatus() { let entityManager = getEntityManager(); let appliedMigrations = entityManager.createQuery("SELECT mv FROM MigrationVersion mv ORDER BY mv.version") .getResultList(); let pendingMigrations = []; let allVersions = ["001", "002", "003", "004"]; for (let version of allVersions) { let applied = appliedMigrations.find(mv => mv.getVersion() === version); if (!applied) { pendingMigrations.push(version); } } return { applied: appliedMigrations.map(mv => mv.getVersion()), pending: pendingMigrations, total: allVersions.length, applied_count: appliedMigrations.length, pending_count: pendingMigrations.length }; } """ rollback_migration: """ function rollbackMigration(version) { let entityManager = getEntityManager(); // Find migration version let migrationVersion = entityManager.createQuery("SELECT mv FROM MigrationVersion mv WHERE mv.version = :version") .setParameter("version", version) .getSingleResult(); // Remove from version table entityManager.remove(migrationVersion); // Add rollback to history let history = new MigrationHistory(); history.setVersion(version); history.setDescription(migrationVersion.getDescription()); history.setAction("ROLLBACK"); history.setTimestamp(new Date()); history.setEnvironment(@env("SPRING_PROFILES_ACTIVE", "development")); entityManager.persist(history); return { version: version, rolled_back: true, timestamp: new Date() }; } """ get_migration_history: """ function getMigrationHistory(limit) { let entityManager = getEntityManager(); let history = entityManager.createQuery("SELECT mh FROM MigrationHistory mh ORDER BY mh.timestamp DESC") .setMaxResults(limit || 50) .getResultList(); return history.map(h => ({ version: h.getVersion(), description: h.getDescription(), action: h.getAction(), timestamp: h.getTimestamp(), environment: h.getEnvironment() })); } """ """; Map<String, Object> config = parser.parse(tskContent); // Initialize migration version control TuskMigrationVersionControl versionControl = new TuskMigrationVersionControl(); versionControl.configure(config); // Track migrations Map<String, Object> track1 = versionControl.trackMigration("version_control_methods", "track_migration", Map.of("version", "001", "description", "Initial schema", "checksum", "abc123")); Map<String, Object> track2 = versionControl.trackMigration("version_control_methods", "track_migration", Map.of("version", "002", "description", "Add user roles", "checksum", "def456")); Map<String, Object> track3 = versionControl.trackMigration("version_control_methods", "track_migration", Map.of("version", "003", "description", "Add user profile", "checksum", "ghi789")); // Get migration status Map<String, Object> status = versionControl.getMigrationStatus("version_control_methods", "get_migration_status", Map.of()); // Get migration history List<Map<String, Object>> history = versionControl.getMigrationHistory("version_control_methods", "get_migration_history", Map.of("limit", 10)); // Rollback a migration Map<String, Object> rollback = versionControl.rollbackMigration("version_control_methods", "rollback_migration", Map.of("version", "003")); System.out.println("Migration Tracking:"); System.out.println("Version 001: " + (track1.get("applied") ? "Applied" : "Failed")); System.out.println("Version 002: " + (track2.get("applied") ? "Applied" : "Failed")); System.out.println("Version 003: " + (track3.get("applied") ? "Applied" : "Failed")); System.out.println("Migration Status:"); System.out.println("Applied: " + status.get("applied_count") + "/" + status.get("total")); System.out.println("Pending: " + status.get("pending_count")); System.out.println("Applied versions: " + status.get("applied")); System.out.println("Pending versions: " + status.get("pending")); System.out.println("Migration History:"); for (Map<String, Object> entry : history) { System.out.println(entry.get("timestamp") + " - " + entry.get("action") + " " + entry.get("version") + ": " + entry.get("description")); } System.out.println("Rollback Result:"); System.out.println("Version " + rollback.get("version") + ": " + (rollback.get("rolled_back") ? "Rolled back" : "Failed")); } }

🔧 Spring Boot Integration

1. Spring Boot Configuration

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.tusklang.java.TuskLang;
import org.tusklang.java.spring.TuskMigrationConfig;

@SpringBootApplication @Configuration public class MigrationApplication { @Bean public TuskMigrationConfig tuskMigrationConfig() { TuskLang parser = new TuskLang(); return parser.parseFile("migrations.tsk", TuskMigrationConfig.class); } public static void main(String[] args) { SpringApplication.run(MigrationApplication.class, args); } }

@TuskConfig public class TuskMigrationConfig { private JPAMigrationConfig jpaMigrations; private FlywayMigrationConfig flywayMigrations; private DataMigrationConfig dataMigrations; private MigrationVersionControlConfig versionControl; // Getters and setters public JPAMigrationConfig getJpaMigrations() { return jpaMigrations; } public void setJpaMigrations(JPAMigrationConfig jpaMigrations) { this.jpaMigrations = jpaMigrations; } public FlywayMigrationConfig getFlywayMigrations() { return flywayMigrations; } public void setFlywayMigrations(FlywayMigrationConfig flywayMigrations) { this.flywayMigrations = flywayMigrations; } public DataMigrationConfig getDataMigrations() { return dataMigrations; } public void setDataMigrations(DataMigrationConfig dataMigrations) { this.dataMigrations = dataMigrations; } public MigrationVersionControlConfig getVersionControl() { return versionControl; } public void setVersionControl(MigrationVersionControlConfig versionControl) { this.versionControl = versionControl; } }

🎯 Best Practices

1. Migration Design Patterns

// ✅ Use versioned migrations
- Always use version numbers
- Use descriptive names
- Include rollback support

// ✅ Implement proper validation - Validate migrations before execution - Check data integrity - Test rollback procedures

// ✅ Use environment-specific migrations - Different migrations for different environments - Conditional migration execution - Environment-specific data

// ✅ Implement proper error handling - Use transactions for migrations - Implement rollback mechanisms - Log migration errors

2. Performance Optimization

// 1. Migration Execution
- Use batch operations for large datasets
- Implement incremental migrations
- Monitor migration performance

// 2. Database Optimization - Use appropriate indexes - Optimize SQL queries - Monitor database performance

// 3. Version Control - Track migration versions - Implement checksums - Maintain migration history

// 4. Testing - Test migrations in development - Validate migration results - Test rollback procedures

🚀 Summary

TuskLang Java database migrations provide:

- JPA Schema Migrations: Seamless JPA integration with schema generation - Spring Boot Flyway Integration: Native Spring Boot Flyway support - Data Migrations: Comprehensive data migration capabilities - Migration Version Control: Complete version tracking and history - Spring Boot Integration: Native Spring Boot configuration support

With these migration features, your Java applications will achieve enterprise-grade database migration management while maintaining the flexibility and power of TuskLang configuration.

"We don't bow to any king" - Migrate your database like a Java master with TuskLang!