使用 Flyway 在 Java 中自動執行資料庫遷移
資料庫遷移是軟體開發的重要方面,特別是在持續整合和交付 (CI/CD) 為標準實踐的環境中。隨著應用程式的成長和發展,它所依賴的資料庫模式也必須如此。手動管理這些架構變更可能會導致錯誤並消耗大量時間。
Flyway 登場,這是一款專為簡化資料庫遷移而客製化的寶貴開源工具。 Flyway 為您的資料庫引入了版本控制,使您能夠安全可靠地遷移架構。在本文中,我們將探索如何使用 Flyway 在多模組 gragle java 專案中自動化資料庫遷移,確保管理資料庫變更成為一個簡化的、防錯的過程。
更多有關飛行路線的詳細資訊
了解 Gradle 中的多項目構建
雖然一些較小的專案或整體應用程式可能僅使用一個建置檔案和統一的來源結構進行管理,但較大的專案經常被組織成多個相互依賴的模組。術語「相互依賴」是這裡的關鍵,強調了透過單一建置過程連接這些模組的需要。
Gradle 以其多專案建置功能(通常稱為多模組專案)來滿足這種設定。在 Gradle 的術語中,這些模組稱為子項目。
多專案建置是圍繞一個根專案建構的,並且可以包含其下的多個子專案。
目錄結構應如下圖所示:
├── .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) settings.gradle.kts 檔案應包含所有子項目。
(2) 每個子項目應該有自己的build.gradle.kts檔案。
利用 Gradle 子模組實現簡潔的架構
清潔架構是一種強調關注點分離的設計模式,使軟體更易於維護和測試。在專案中實作此架構的實用方法之一是使用 Gradle 的子模組結構來組織程式碼庫。以下是如何將 Clean Architecture 與 Gradle 子模組結合:
乾淨的架構層:
核心:
- 包含業務邏輯、領域模型和應用程式規則。 不依賴外部或網路。
- 應盡可能獨立於特定於框架的實作。
外在:
- 處理外部操作或集成,例如資料庫遷移或第三方服務互動。
- 業務邏輯可能依賴 Core,但不應依賴 Web。
網頁:
- 入口點,公開 REST API 並處理 HTTP 請求。
- 業務邏輯依賴核心,整合可能依賴外部。
├── .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 步: 建立一個基於 Java 的 Gradle 專案並將其命名為「SchoolStaff」。
第 2 步: 前往 Spring Initializr 並產生一個名為 Web.
的 REST API 項目第 3 步: 建立一個基於 Java 的 Gradle 專案並命名為 External.
第 4 步: 建立一個基於 Java 的 Gradle 專案並將其命名為 Core.
根目錄 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() } }
「Web」專案所需的依賴項。
rootProject.name = "SchoolStaff" include("Core", "External", "Web")
「核心」專案所需的依賴項。
dependencies { implementation(project(":Core")) implementation(project(":External")) }
「外部」項目所需的依賴項。
dependencies { runtimeOnly(project(":External")) }
我們使用以下插件進行 Flyway 遷移:
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")) }
這種方法非常適合生產環境,因為它確保了受控且可靠的遷移。我們不會在每次應用程式啟動時自動運行遷移,而是僅在必要時執行遷移,從而提供更大的靈活性和控制力。
我們也利用 Spring 應用程式中的 application.properties 檔案來管理資料庫連線和憑證。 BaselineOnMigrate = true 設定可確保將初始遷移用作未來遷移的基準。
plugins { id("org.flywaydb.flyway") version "11.0.1" }
我們可以使用 JPA Buddy 產生外部專案的 resources/db/migration 目錄中的所有遷移檔案。
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 }
從根項目中,我們可以使用以下命令執行 Flyway 遷移:
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) );
這會將所有遷移檔案套用到資料庫。
結論
我們探索如何在 Gradle 多模組專案中使用 Flyway 自動化資料庫遷移,這對於在 CI/CD 環境中維護架構一致性至關重要。
我們還介紹了 Gradle 如何支援多項目構建,將複雜的項目組織成可管理的子項目,每個子項目都有自己的構建配置,統一在根構建腳本下。
最後,我們將 Clean Architecture 與 Gradle 模組結合起來,將專案建置為核心層、外部層和 Web 層,促進關注點和依賴管理的清晰分離。
這些實踐增強了模組化、自動化和可維護性,為可擴展、無錯誤的軟體開發奠定了基礎。
以上是多模組 Gradle 專案中的 Flyway 遷移(乾淨架構)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

javaispopularforcross-platformdesktopapplicationsduetoits“ writeonce,runany where”哲學。 1)itusesbytiesebyTecodeThatrunsonAnyJvm-備用Platform.2)librarieslikeslikeslikeswingingandjavafxhelpcreatenative-lookingenative-lookinguisis.3)

在Java中編寫平台特定代碼的原因包括訪問特定操作系統功能、與特定硬件交互和優化性能。 1)使用JNA或JNI訪問Windows註冊表;2)通過JNI與Linux特定硬件驅動程序交互;3)通過JNI使用Metal優化macOS上的遊戲性能。儘管如此,編寫平台特定代碼會影響代碼的可移植性、增加複雜性、可能帶來性能開銷和安全風險。

Java將通過雲原生應用、多平台部署和跨語言互操作進一步提昇平台獨立性。 1)雲原生應用將使用GraalVM和Quarkus提升啟動速度。 2)Java將擴展到嵌入式設備、移動設備和量子計算機。 3)通過GraalVM,Java將與Python、JavaScript等語言無縫集成,增強跨語言互操作性。

Java的強類型系統通過類型安全、統一的類型轉換和多態性確保了平台獨立性。 1)類型安全在編譯時進行類型檢查,避免運行時錯誤;2)統一的類型轉換規則在所有平台上一致;3)多態性和接口機制使代碼在不同平台上行為一致。

JNI會破壞Java的平台獨立性。 1)JNI需要特定平台的本地庫,2)本地代碼需在目標平台編譯和鏈接,3)不同版本的操作系統或JVM可能需要不同的本地庫版本,4)本地代碼可能引入安全漏洞或導致程序崩潰。

新興技術對Java的平台獨立性既有威脅也有增強。 1)雲計算和容器化技術如Docker增強了Java的平台獨立性,但需要優化以適應不同雲環境。 2)WebAssembly通過GraalVM編譯Java代碼,擴展了其平台獨立性,但需與其他語言競爭性能。

不同JVM實現都能提供平台獨立性,但表現略有不同。 1.OracleHotSpot和OpenJDKJVM在平台獨立性上表現相似,但OpenJDK可能需額外配置。 2.IBMJ9JVM在特定操作系統上表現優化。 3.GraalVM支持多語言,需額外配置。 4.AzulZingJVM需特定平台調整。

平台獨立性通過在多種操作系統上運行同一套代碼,降低開發成本和縮短開發時間。具體表現為:1.減少開發時間,只需維護一套代碼;2.降低維護成本,統一測試流程;3.快速迭代和團隊協作,簡化部署過程。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

SublimeText3 Linux新版
SublimeText3 Linux最新版

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Atom編輯器mac版下載
最受歡迎的的開源編輯器

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

禪工作室 13.0.1
強大的PHP整合開發環境