


Flyway-Migrationen in Gradle-Projekten mit mehreren Modulen (Clean Architecture)
Automatisierung von Datenbankmigrationen in Java mit Flyway
Datenbankmigrationen sind ein entscheidender Aspekt der Softwareentwicklung, insbesondere in Umgebungen, in denen kontinuierliche Integration und Bereitstellung (CI/CD) Standard sind. Wenn Ihre Anwendung wächst und sich weiterentwickelt, muss auch das Datenbankschema wachsen, von dem sie abhängt. Die manuelle Verwaltung dieser Schemaänderungen kann zu Fehlern führen und viel Zeit in Anspruch nehmen.
Da kommt Flyway ins Spiel, ein unschätzbar wertvolles Open-Source-Tool, das darauf zugeschnitten ist, Datenbankmigrationen zu vereinfachen. Flyway führt die Versionskontrolle in Ihre Datenbank ein, sodass Sie Ihr Schema sicher und zuverlässig migrieren können. In diesem Artikel erfahren Sie, wie Sie Datenbankmigrationen in Multi-Modul-Gragle-Java-Projekten mithilfe von Flyway automatisieren und so sicherstellen, dass die Verwaltung von Datenbankänderungen zu einem optimierten, fehlerresistenten Prozess wird.
Weitere Details zum Flyway
Grundlegendes zu Multiprojekt-Builds in Gradle
Während einige kleinere Projekte oder monolithische Anwendungen möglicherweise mit nur einer Build-Datei und einer einheitlichen Quellstruktur auskommen, sind größere Projekte häufig in mehreren, voneinander abhängigen Modulen organisiert. Der Begriff „interdependent“ ist hier von entscheidender Bedeutung und unterstreicht die Notwendigkeit, diese Module über einen einzigen Build-Prozess zu verbinden.
Gradle unterstützt dieses Setup mit seiner Multiprojekt-Build-Fähigkeit, die oft als Multimodulprojekt bezeichnet wird. In der Terminologie von Gradle werden diese Module Teilprojekte genannt.
Ein Multiprojekt-Build ist um ein Stammprojekt herum strukturiert und kann mehrere Unterprojekte darunter enthalten.
Die Verzeichnisstruktur sollte wie folgt aussehen:
├── .gradle │ └── ⋮ ├── gradle │ ├── libs.versions.toml │ └── wrapper ├── gradlew ├── gradlew.bat ├── settings.gradle.kts (1) ├── sub-project-1 │ └── build.gradle.kts (2) ├── sub-project-2 │ └── build.gradle.kts (2) └── sub-project-3 └── build.gradle.kts (2)
(1) Die Datei „settings.gradle.kts“ sollte alle Unterprojekte enthalten.
(2) Jedes Unterprojekt sollte seine eigene build.gradle.kts-Datei haben.
Nutzung von Gradle-Submodulen für eine saubere Architektur
Clean Architecture ist ein Entwurfsmuster, das die Trennung von Belangen betont und so die Wartung und das Testen von Software erleichtert. Eine der praktischen Möglichkeiten, diese Architektur in einem Projekt zu implementieren, besteht darin, die Untermodulstruktur von Gradle zum Organisieren Ihrer Codebasis zu verwenden. So können Sie Clean Architecture mit Gradle-Untermodulen ausrichten:
Saubere Architekturebenen:
Kern:
- Enthält Geschäftslogik, Domänenmodelle und Anwendungsregeln. Hat keine Abhängigkeit von Extern oder Web.
- Sollte nach Möglichkeit unabhängig von Framework-spezifischen Implementierungen sein.
Extern:
- Verwaltet externe Aktionen oder Integrationen, wie Datenbankmigrationen oder Interaktionen mit Drittanbieterdiensten.
- Kann für die Geschäftslogik von Core abhängig sein, sollte aber nicht von Web abhängen.
Web:
- Der Einstiegspunkt, der eine REST-API verfügbar macht und HTTP-Anfragen verarbeitet.
- Hängt von Core für die Geschäftslogik ab und kann von External für Integrationen abhängen.
├── .gradle │ └── ⋮ ├── gradle │ ├── libs.versions.toml │ └── wrapper ├── gradlew ├── gradlew.bat ├── settings.gradle.kts (1) ├── sub-project-1 │ └── build.gradle.kts (2) ├── sub-project-2 │ └── build.gradle.kts (2) └── sub-project-3 └── build.gradle.kts (2)
Schritt 1: Erstellen Sie ein Java-basiertes Gradle-Projekt und nennen Sie es „SchoolStaff“.
Schritt 2: Gehen Sie zu Spring Initializr und generieren Sie ein REST-API-Projekt mit dem Namen Web.
Schritt 3: Erstellen Sie ein Java-basiertes Gradle-Projekt und nennen Sie es Extern.
Schritt 4: Erstellen Sie ein Java-basiertes Gradle-Projekt und nennen Sie es Core.
Root build.gradle.kts
SchoolStaff/ ├── Core/ │ ├── src/ │ │ └── main/ │ │ ├── java/ # Business logic and domain objects │ │ └── resources/ # Core-specific resources (if any) │ └── build.gradle.kts ├── External/ │ ├── src/ │ │ └── main/ │ │ ├── java/ # External integration code │ │ └── resources/ # db/migration and other external resources │ └── build.gradle.kts ├── Web/ │ ├── src/ │ │ └── main/ │ │ ├── java/ # REST controllers and entry-point logic │ │ └── resources/ # Application-specific configuration │ └── build.gradle.kts ├── build.gradle.kts # Root Gradle build └── settings.gradle.kts # Project module settings
settings.gradle.kts
plugins { id("java") } allprojects { group = "school.staff" version = "1.0.0" repositories { mavenLocal() mavenCentral() } } subprojects { apply(plugin = "java") dependencies { testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") } tasks.test { useJUnitPlatform() } }
Erforderliche Abhängigkeiten für das „Web“-Projekt.
rootProject.name = "SchoolStaff" include("Core", "External", "Web")
Erforderliche Abhängigkeiten für das „Core“-Projekt.
dependencies { implementation(project(":Core")) implementation(project(":External")) }
Erforderliche Abhängigkeiten für das „Externe“ Projekt.
dependencies { runtimeOnly(project(":External")) }
Wir verwenden das folgende Plugin für die Flyway-Migration:
import java.sql.DriverManager import java.util.Properties // Function to load properties based on the environment fun loadProperties(env: String): Properties { val properties = Properties() val propsFile = file("../web/src/main/resources/application-$env.properties") if (propsFile.exists()) { propsFile.inputStream().use { properties.load(it) } } else { throw GradleException("Properties file for environment '$env' not found: ${propsFile.absolutePath}") } return properties } // Set the environment (default is 'dev' if no argument is passed) val env = project.findProperty("env")?.toString() ?: "dev" // Load properties for the chosen environment val dbProps = loadProperties(env) buildscript { dependencies { classpath("org.flywaydb:flyway-database-postgresql:11.1.0") // This is required for the flyway plugin to work on the migration, otherwise it will throw an error as No Database found classpath("org.postgresql:postgresql:42.7.4") } } plugins { id("java-library") id("org.flywaydb.flyway") version "11.0.1" } group = "school.staff" version = "unspecified" repositories { mavenLocal() mavenCentral() } dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jpa:3.4.0") implementation("org.postgresql:postgresql:42.7.4") implementation("org.flywaydb:flyway-core:11.0.1") implementation("org.flywaydb:flyway-database-postgresql:11.0.1") implementation("org.flywaydb:flyway-gradle-plugin:11.0.1") implementation (project(":Core")) testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") } tasks.test { useJUnitPlatform() } // Task to create the database if it doesn't exist tasks.register("createDatabase") { doLast { val dbUrl = dbProps["spring.datasource.url"] as String val dbUsername = dbProps["spring.datasource.username"] as String val dbPassword = dbProps["spring.datasource.password"] as String // Extract the base URL and database name val baseDbUrl = dbUrl.substringBeforeLast("/")+ "/" val dbName = dbUrl.substringAfterLast("/") // Connect to the PostgreSQL server (without the specific database) DriverManager.getConnection(baseDbUrl, dbUsername, dbPassword).use { connection -> val stmt = connection.createStatement() val resultSet = stmt.executeQuery("SELECT 1 FROM pg_database WHERE datname = '$dbName'") if (!resultSet.next()) { println("Database '$dbName' does not exist. Creating it...") stmt.executeUpdate("CREATE DATABASE \"$dbName\"") println("Database '$dbName' created successfully.") } else { println("Database '$dbName' already exists.") } } } } flyway { url = dbProps["spring.datasource.url"] as String user = dbProps["spring.datasource.username"] as String password = dbProps["spring.datasource.password"] as String locations = arrayOf("classpath:db/migration") baselineOnMigrate = true } //Ensure classes are built before migration tasks.named("flywayMigrate").configure { dependsOn(tasks.named("createDatabase")) dependsOn(tasks.named("classes")) }
Dieser Ansatz eignet sich gut für Produktionsumgebungen, da er kontrollierte und zuverlässige Migrationen gewährleistet. Anstatt Migrationen automatisch bei jedem Anwendungsstart durchzuführen, führen wir sie nur bei Bedarf aus, was für mehr Flexibilität und Kontrolle sorgt.
Wir verwenden auch die Datei application.properties in der Spring-Anwendung, um Datenbankverbindungen und Anmeldeinformationen zu verwalten. Die Einstellung „baselineOnMigrate = true“ stellt sicher, dass die anfängliche Migration als Basis für zukünftige Migrationen verwendet wird.
plugins { id("org.flywaydb.flyway") version "11.0.1" }
Wir können JPA Buddy verwenden, um alle Migrationsdateien im Verzeichnis resources/db/migration des externen Projekts zu generieren.
V1__Initial_Migration
flyway { url = dbProps["spring.datasource.url"] as String user = dbProps["spring.datasource.username"] as String password = dbProps["spring.datasource.password"] as String locations = arrayOf("classpath:db/migration") baselineOnMigrate = true }
Vom Root-Projekt aus können wir die Flyway-Migration mit dem folgenden Befehl ausführen:
CREATE TABLE _user ( id UUID NOT NULL, created_by UUID, created_date TIMESTAMP WITH TIME ZONE, last_modified_by UUID, last_modified_date TIMESTAMP WITH TIME ZONE, first_name VARCHAR(255), last_name VARCHAR(255), email VARCHAR(255), password VARCHAR(255), tenant_id UUID, CONSTRAINT pk__user PRIMARY KEY (id) );
Dadurch werden alle Migrationsdateien auf die Datenbank angewendet.
Abschluss
Wir haben untersucht, wie Datenbankmigrationen mithilfe von Flyway innerhalb eines Gradle-Multimodulprojekts automatisiert werden können, was für die Aufrechterhaltung der Schemakonsistenz in CI/CD-Umgebungen von entscheidender Bedeutung ist.
Wir haben auch behandelt, wie Gradle Multiprojekt-Builds unterstützt und komplexe Projekte in überschaubare Unterprojekte organisiert, jedes mit seiner eigenen Build-Konfiguration, vereinheitlicht unter einem Root-Build-Skript.
Zuletzt haben wir Clean Architecture mit Gradle-Modulen in Einklang gebracht und das Projekt in Core-, External- und Web-Schichten strukturiert, um eine saubere Trennung von Anliegen und Abhängigkeitsmanagement zu fördern.
Diese Praktiken verbessern die Modularität, Automatisierung und Wartbarkeit und schaffen die Voraussetzungen für eine skalierbare, fehlerfreie Softwareentwicklung.
Das obige ist der detaillierte Inhalt vonFlyway-Migrationen in Gradle-Projekten mit mehreren Modulen (Clean Architecture). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

In dem Artikel werden Maven und Gradle für Java -Projektmanagement, Aufbau von Automatisierung und Abhängigkeitslösung erörtert, die ihre Ansätze und Optimierungsstrategien vergleichen.

In dem Artikel werden benutzerdefinierte Java -Bibliotheken (JAR -Dateien) mit ordnungsgemäßem Versioning- und Abhängigkeitsmanagement erstellt und verwendet, wobei Tools wie Maven und Gradle verwendet werden.

In dem Artikel wird in der Implementierung von mehrstufigem Caching in Java mithilfe von Koffein- und Guava-Cache zur Verbesserung der Anwendungsleistung erläutert. Es deckt die Einrichtungs-, Integrations- und Leistungsvorteile sowie die Bestrafung des Konfigurations- und Räumungsrichtlinienmanagements ab

In dem Artikel werden mit JPA für Objektrelationszuordnungen mit erweiterten Funktionen wie Caching und faulen Laden erläutert. Es deckt Setup, Entity -Mapping und Best Practices zur Optimierung der Leistung ab und hebt potenzielle Fallstricke hervor. [159 Charaktere]

Mit der Klassenbelastung von Java wird das Laden, Verknüpfen und Initialisieren von Klassen mithilfe eines hierarchischen Systems mit Bootstrap-, Erweiterungs- und Anwendungsklassenloadern umfasst. Das übergeordnete Delegationsmodell stellt sicher


Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

SublimeText3 Linux neue Version
SublimeText3 Linux neueste Version

Dreamweaver Mac
Visuelle Webentwicklungstools

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

mPDF
mPDF ist eine PHP-Bibliothek, die PDF-Dateien aus UTF-8-codiertem HTML generieren kann. Der ursprüngliche Autor, Ian Back, hat mPDF geschrieben, um PDF-Dateien „on the fly“ von seiner Website auszugeben und verschiedene Sprachen zu verarbeiten. Es ist langsamer und erzeugt bei der Verwendung von Unicode-Schriftarten größere Dateien als Originalskripte wie HTML2FPDF, unterstützt aber CSS-Stile usw. und verfügt über viele Verbesserungen. Unterstützt fast alle Sprachen, einschließlich RTL (Arabisch und Hebräisch) und CJK (Chinesisch, Japanisch und Koreanisch). Unterstützt verschachtelte Elemente auf Blockebene (wie P, DIV),

VSCode Windows 64-Bit-Download
Ein kostenloser und leistungsstarker IDE-Editor von Microsoft