iT邦幫忙

2025 iThome 鐵人賽

DAY 11
0
佛心分享-SideProject30

我的時間到底去哪裡了!? – 個人時間數據系統開發挑戰系列 第 11

為什麼需要資料庫遷移?用 Flyway 管理 Spring Boot 專案的資料庫內容

  • 分享至 

  • xImage
  •  

今天會有這篇因為我換了一台電腦開發,問題馬上就出現了。

問題:開發陣地轉移後,新陣地沒有相同的資料表配置

我的資料庫服務跑在本地,當我換了一台電腦,所有資料庫的設定都要重新來一次

就算我可以拿docker-compose.yml再啟一個相同的PostgreSQL資料庫,裡面也沒有相同的資料表,需要重新執行SQL 腳本才行,麻煩呀。而且儘管把觀點拓展,不限於我的專案,開發時也可能遇到這些問題:

  • 新功能需要新增資料表欄位,但每個開發者的資料庫狀態都不同(尤其是當大家都在本機跑資料庫)
  • 測試環境、正式環境的資料庫結構不一致
  • 部署時忘記執行某些 SQL 腳本,導致應用程式出錯
  • 無法追蹤資料庫結構的變更歷史

你可能會說,記得執行 SQL 腳本就好,但這容易出錯且難以管理。

這個時候Flyway 可以解決這些問題。

什麼是 Flyway?

Flyway 是一個開源的資料庫遷移工具,主要特點:

  • 版本控制:每個遷移檔案都有版本號,確保執行順序
  • 自動化:應用程式啟動時自動執行未執行的遷移
  • 安全性:避免重複執行,追蹤執行歷史
  • 跨平台:支援多種資料庫(PostgreSQL、MySQL、Oracle 等)

在 Spring Boot 中整合 Flyway

1. 加入依賴

在 pom.xml 中加入 Flyway 依賴:

<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
</dependency>

Spring Boot 會自動偵測並啟用 Flyway。

2. 配置設定

在 application.yml 中配置 Flyway:

flyway:
  enabled: true
  baseline-on-migrate: true
  locations: classpath:db/migration
  validate-on-migrate: true
  out-of-order: false
  table: flyway_schema_history
  baseline-version: 1

3. 建立遷移檔案

在 src/main/resources/db/migration/ 目錄下建立 SQL 檔案,命名規則:V{版本號}__{描述}.sql

檔案命名規則

  • V{版本號}__{描述}.sql
  • 版本號必須是數字,且要比現有的版本號大
  • 描述部分用底線分隔單詞

實際範例:MyMomentum 專案

以我的專案為例,建立初始資料庫結構:

**檔案:**V1__Initial_schema.sql

-- 啟用 UUID 生成功能
CREATE EXTENSION IF NOT EXISTS "pgcrypto";

-- 建立枚舉類型
CREATE TYPE record_source AS ENUM ('LIVE', 'MANUAL');

-- 使用者表
CREATE TABLE users (
  id          BIGSERIAL PRIMARY KEY,
  email       VARCHAR(255),
  name        VARCHAR(255),
  google_sub  VARCHAR(255) NOT NULL,
  created_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at  TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- 活動表
CREATE TABLE activities (
  id           UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id      BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  name         VARCHAR(100) NOT NULL,
  target_time  INT NOT NULL DEFAULT 0,
  color        VARCHAR(16),
  icon         VARCHAR(16),
  created_at   TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at   TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- 活動記錄表
CREATE TABLE activity_records (
  id           UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id      BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  activity_id  UUID NOT NULL REFERENCES activities(id) ON DELETE CASCADE,
  source       record_source NOT NULL,
  duration     INT CHECK (duration IS NULL OR duration > 0),
  executed_at  TIMESTAMPTZ NOT NULL,
  created_at   TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at   TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- 建立索引
CREATE UNIQUE INDEX idx_users_google_sub ON users (google_sub);
CREATE INDEX idx_activities_user ON activities(user_id);
CREATE INDEX idx_records_user_time ON activity_records(user_id, executed_at DESC);

執行流程

當 Spring Boot 應用程式啟動時,Flyway 會自動執行以下步驟:

  1. 連接到資料庫
  2. 檢查是否存在 flyway_schema_history
  3. 如果不存在,建立該表並執行所有遷移檔案
  4. 如果存在,檢查是否有新的遷移檔案需要執行
  5. 記錄執行歷史,避免重複執行

都設定好就可以啟動系統,看看遷移有沒有成功

https://ithelp.ithome.com.tw/upload/images/20250923/201602798eIY2XlCfj.png

此時所有表都成功建立了(但資料沒有,這正常)

還有一張flyway_schema_history 來記錄flyway的執行狀況,下次啟動時會根據這張表的紀錄來決定是否執行遷移檔(V1__Initial_schema.sql)的內容。

同時 Flyway 也會建立一張 “flyway_schema_history” 來記錄執行狀況。

下次啟動時,會依據這張表的紀錄來判斷是否需要再次執行 V1__Initial_schema.sql


上一篇
後端認證實作:Google OAuth + JWT 無狀態認證系統
下一篇
活動 CRUD API 設計與 Repository 實作
系列文
我的時間到底去哪裡了!? – 個人時間數據系統開發挑戰15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言