ホームページ Java &#&チュートリアル マルチモジュール Gradle プロジェクトでの Flyway の移行 (クリーン アーキテクチャ)

マルチモジュール Gradle プロジェクトでの Flyway の移行 (クリーン アーキテクチャ)

Jan 19, 2025 am 08:05 AM

Flyway を使用した Java でのデータベース移行の自動化

データベースの移行は、特に継続的インテグレーションとデリバリー (CI/CD) が標準的な実践である環境では、ソフトウェア開発の重要な側面です。アプリケーションが成長し、進化するにつれて、アプリケーションが依存するデータベース スキーマも変化する必要があります。これらのスキーマ変更を手動で管理すると、エラーが発生し、かなりの時間がかかる可能性があります。

データベースの移行を簡素化するために調整された貴重なオープンソース ツールである Flyway を紹介します。 Flyway はデータベースにバージョン管理を導入し、スキーマを安全かつ確実に移行できるようにします。この記事では、Flyway を使用してマルチモジュールの Gragle Java プロジェクトでデータベースの移行を自動化し、データベースの変更管理が合理化され、エラーが発生しにくいプロセスになるようにする方法を検討します。

フライウェイの詳細

Gradle でのマルチプロジェクト ビルドを理解する

一部の小規模なプロジェクトやモノリシック アプリケーションは、1 つのビルド ファイルと統一されたソース構造だけで管理できる場合がありますが、大規模なプロジェクトは、相互依存する複数のモジュールに編成されることがよくあります。ここでは「相互依存」という用語が重要であり、単一のビルド プロセスを介してこれらのモジュールを接続する必要性を強調しています。

Gradle は、マルチモジュール プロジェクトと呼ばれることが多いマルチプロジェクト ビルド機能を使用して、このセットアップに対応します。 Gradle の用語では、これらのモジュールはサブプロジェクトと呼ばれます。

マルチプロジェクト ビルドは 1 つのルート プロジェクトを中心に構成され、その下に複数のサブプロジェクトを含めることができます。

gradle project

ディレクトリ構造は次のようになります:

├── .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 サブモジュールの活用

クリーン アーキテクチャは、関心事の分離を強調する設計パターンであり、ソフトウェアの保守とテストが容易になります。このアーキテクチャをプロジェクトに実装する実際的な方法の 1 つは、Gradle のサブモジュール構造を使用してコードベースを編成することです。 Clean Architecture と Gradle サブモジュールを調整する方法は次のとおりです:

クリーンなアーキテクチャ層:
コア:

  • ビジネス ロジック、ドメイン モデル、アプリケーション ルールが含まれます。 外部または Web に依存しません。
  • 可能な限りフレームワーク固有の実装から独立させる必要があります。

外部:

  • データベースの移行やサードパーティのサービスとのやり取りなど、外部のアクションや統合を処理します。
  • ビジネス ロジックはコアに依存する可能性がありますが、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 プロジェクトを作成し、外部 という名前を付けます。

ステップ 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 を使用して、外部プロジェクトの resource/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 がマルチプロジェクト ビルドをサポートし、複雑なプロジェクトを管理しやすいサブプロジェクトに編成し、それぞれが独自のビルド構成を持ち、ルート ビルド スクリプトの下に統合される方法についても説明しました。

最後に、クリーン アーキテクチャと Gradle モジュールを調整し、プロジェクトをコア層、外部層、Web 層に構造化し、懸念事項と依存関係管理の明確な分離を促進しました。

これらの実践により、モジュール性、自動化、保守性が強化され、スケーラブルでエラーのないソフトウェア開発の準備が整えられます。

以上がマルチモジュール Gradle プロジェクトでの Flyway の移行 (クリーン アーキテクチャ)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Javaのクラスロードメカニズムは、さまざまなクラスローダーやその委任モデルを含むどのように機能しますか? Javaのクラスロードメカニズムは、さまざまなクラスローダーやその委任モデルを含むどのように機能しますか? Mar 17, 2025 pm 05:35 PM

Javaのクラスロードには、ブートストラップ、拡張機能、およびアプリケーションクラスローダーを備えた階層システムを使用して、クラスの読み込み、リンク、および初期化が含まれます。親の委任モデルは、コアクラスが最初にロードされ、カスタムクラスのLOAに影響を与えることを保証します

カフェインやグアバキャッシュなどのライブラリを使用して、Javaアプリケーションにマルチレベルキャッシュを実装するにはどうすればよいですか? カフェインやグアバキャッシュなどのライブラリを使用して、Javaアプリケーションにマルチレベルキャッシュを実装するにはどうすればよいですか? Mar 17, 2025 pm 05:44 PM

この記事では、カフェインとグアバキャッシュを使用してJavaでマルチレベルキャッシュを実装してアプリケーションのパフォーマンスを向上させています。セットアップ、統合、パフォーマンスの利点をカバーし、構成と立ち退きポリシー管理Best Pra

キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPA(Java Persistence API)を使用するにはどうすればよいですか? キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPA(Java Persistence API)を使用するにはどうすればよいですか? Mar 17, 2025 pm 05:43 PM

この記事では、キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPAを使用することについて説明します。潜在的な落とし穴を強調しながら、パフォーマンスを最適化するためのセットアップ、エンティティマッピング、およびベストプラクティスをカバーしています。[159文字]

高度なJavaプロジェクト管理、自動化の構築、依存関係の解像度にMavenまたはGradleを使用するにはどうすればよいですか? 高度なJavaプロジェクト管理、自動化の構築、依存関係の解像度にMavenまたはGradleを使用するにはどうすればよいですか? Mar 17, 2025 pm 05:46 PM

この記事では、Javaプロジェクト管理、自動化の構築、依存関係の解像度にMavenとGradleを使用して、アプローチと最適化戦略を比較して説明します。

適切なバージョン化と依存関係管理を備えたカスタムJavaライブラリ(JARファイル)を作成および使用するにはどうすればよいですか? 適切なバージョン化と依存関係管理を備えたカスタムJavaライブラリ(JARファイル)を作成および使用するにはどうすればよいですか? Mar 17, 2025 pm 05:45 PM

この記事では、MavenやGradleなどのツールを使用して、適切なバージョン化と依存関係管理を使用して、カスタムJavaライブラリ(JARファイル)の作成と使用について説明します。

See all articles