はじめに
「DB データベースのバージョン管理ツールを使いましょう!」で記載した概要から、1歩進めた導入と運用をメモとしてまとめます。
今回は、良くあるパターンとして、Spring BootでAPIを作成。Admin機能系とUser機能系に分かれるWeb APIを想定して考えてみました!
【リポジトリ構成】
Admin、User、Commonの3つのリポジトリを管理するため、以下のような構造を採用します。
- Commonリポジトリ: すべてのDDL(データベース定義言語)を格納
- Adminリポジトリ: Adminサービスを開発します。Commonリポジトリをサブモジュールとして参照
- Userリポジトリ: Userサービスを開発します。Adminと同様にCommonリポジトリをサブモジュールとして参照
開発環境のセットアップ
Flywayの導入
まず、pom.xml(Maven)またはbuild.gradle(Gradle)にFlywayの依存関係を追加します。
下記の依存関係を追加することで、Spring Bootの自動設定機能がFlywayを認識し、アプリケーション起動時にマイグレーションを自動実行します。
Maven (pom.xml)
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
Gradle (build.gradle)
dependencies {
implementation 'org.flywaydb:flyway-core'
}
DDLの管理と命名規則
DDLの配置場所
すべてのDDLは、Commonリポジトリの src/main/resources/db/migration/ ディレクトリに配置します。これにより、DDLの変更を一元管理できます。
ファイル名の規則
Flywayはファイル名を解析してマイグレーションのバージョンと順序を決定します。以下の命名規則に従うことで、どのスキーマに適用されるDDLかが一目で分かります。
- V<バージョン>__<適用対象>__<説明>.sql
例:
- V1.0.0__user__create_profiles_table.sql:userスキーマに適用するDDL
- V1.0.1__admin__create_logs_table.sql:adminスキーマに適用するDDL
- V1.0.2__common__add_last_login.sql:adminとuser両方のスキーマに適用するDDL
Flywayの設定
各サービスの application.properties に、Flywayがマイグレーションを実行するための設定を記述します。
Adminサービスの設定
admin-repo/src/main/resources/application.properties に、Adminサービスが担当するスキーマと、参照するマイグレーションディレクトリを設定します。
# データベース接続情報
spring.datasource.url=jdbc:postgresql://localhost:5432/your_database
spring.datasource.username=your_user
spring.datasource.password=your_password
# Adminサービスが担当するスキーマ
spring.flyway.schemas=admin
# マイグレーションファイルの場所(Commonリポジトリを参照)
spring.flyway.locations=classpath:/db/migration
Userサービスの設定
Userサービスも同様に設定します。
# データベース接続情報
spring.datasource.url=jdbc:postgresql://localhost:5432/your_database
spring.datasource.username=your_user
spring.datasource.password=your_password
# Userサービスが担当するスキーマ
spring.flyway.schemas=user
# マイグレーションファイルの場所(Commonリポジトリを参照)
spring.flyway.locations=classpath:/db/migration
SQLファイルの書き方(プレースホルダーの活用)
SQLファイル内では、${flyway:defaultSchema} というプレースホルダーを使用します。これにより、Flywayがspring.flyway.schemasで設定されたスキーマ名に自動的に置き換えます。
例:V1.0.0__user__create_profiles_table.sql
CREATE TABLE ${flyway:defaultSchema}.user_profiles (
id BIGINT PRIMARY KEY,
nickname VARCHAR(255) NOT NULL
);
- Adminサービスから実行されると admin.user_profiles テーブルが作成される
- Userサービスから実行されると user.user_profiles テーブルが作成される
運用と実行フロー
初回デプロイ時
Adminサービスを起動
- Flywayはadminスキーマに接続し、admin.flyway_schema_historyテーブルを作成
- Commonリポジトリ内のすべてのDDLファイルをバージョン順に実行し、adminスキーマ内にすべてのテーブルを作成
Userサービスを起動
- Flywayはuserスキーマに接続し、user.flyway_schema_historyテーブルを作成
- Commonリポジトリ内のすべてのDDLファイルをバージョン順に実行し、userスキーマ内にすべてのテーブルを作成
DDL変更時の運用
- すべてのDDLはCommonリポジトリで管理します。AdminとUserのどちらの機能に関わる変更であっても、新しいDDLファイルを追加します
- 変更後、関連するサービスを再デプロイすることで、新しいDDLが適用されます。例えば、User関連のテーブルに変更があれば、Userサービスを再デプロイします。ただし、AdminとUser両方のスキーマに共通のテーブルに変更を加えた場合は、両方のサービスを再デプロイする必要があります
おわりに
共通系をサブモジュールとして使うやり方は良くあるけど、FlywayのDB管理を入れると混乱してしまったので、整理する良い機会になりました!
ただ、結局はCommonでDDLを管理しているので、変更の起点だけがAdmin、Userのどちらかになるだけなので、整理ができれば大丈夫!
参考(感謝)
- AIに聞きながら