資料庫遷移
本文檔說明如何使用 Flyway 管理花店系統的資料庫 Schema 變更。
Flyway 簡介
Flyway 是一個資料庫遷移工具,用於版本控制資料庫 Schema 變更。
優點
- 版本控制:每個遷移腳本都有版本號
- 可重複執行:確保所有環境的資料庫結構一致
- 追蹤歷史:記錄已執行的遷移
遷移腳本位置
app-server/src/main/resources/db/migration/
├── V1__create_tenant_table.sql
├── V2__create_auth_tables.sql
├── V3__create_product_table.sql
├── V4__create_order_tables.sql
├── V5__create_customer_table.sql
└── ...
命名規範
遷移腳本必須遵循以下命名規範:
V{版本號}__{描述}.sql
- V:表示版本化遷移(Versioned Migration)
- 版本號:整數,依序遞增(1, 2, 3...)
- __:雙底線分隔符
- 描述:使用底線分隔的描述文字
範例
V1__create_tenant_table.sql
V2__create_auth_tables.sql
V3__add_product_sku_column.sql
撰寫遷移腳本
建立資料表
-- V3__create_product_table.sql
CREATE TABLE product (
id VARCHAR(36) PRIMARY KEY,
tenant_id VARCHAR(36) NOT NULL,
sku VARCHAR(30) NOT NULL,
name VARCHAR(200) NOT NULL,
category_code VARCHAR(36) NOT NULL,
description VARCHAR(2000),
price DECIMAL(10, 2) NOT NULL,
cost DECIMAL(10, 2),
stock INTEGER NOT NULL DEFAULT 0,
low_stock_threshold INTEGER NOT NULL DEFAULT 5,
stock_unit VARCHAR(20) NOT NULL DEFAULT '個',
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
featured BOOLEAN NOT NULL DEFAULT FALSE,
new_arrival BOOLEAN NOT NULL DEFAULT FALSE,
-- 審計欄位(與 AuditableTenantEntity 一致)
created_by VARCHAR(100),
created_date TIMESTAMP,
last_modified_by VARCHAR(100),
last_modified_date TIMESTAMP,
CONSTRAINT fk_product_tenant FOREIGN KEY (tenant_id) REFERENCES tenant(id),
CONSTRAINT uk_product_tenant_sku UNIQUE (tenant_id, sku)
);
CREATE INDEX idx_product_tenant ON product(tenant_id);
CREATE INDEX idx_product_sku ON product(sku);
CREATE INDEX idx_product_category ON product(category_code);
CREATE INDEX idx_product_status ON product(status);
審計欄位說明:
created_by/created_date:建立者與建立時間last_modified_by/last_modified_date:最後修改者與修改時間- 這些欄位由
AuditableTenantEntity基類透過 Spring Data JPA Auditing 自動管理
新增欄位
-- V10__add_product_featured_column.sql
ALTER TABLE product ADD COLUMN featured BOOLEAN NOT NULL DEFAULT FALSE;
ALTER TABLE product ADD COLUMN new_arrival BOOLEAN NOT NULL DEFAULT FALSE;
建立索引
-- V11__add_product_indexes.sql
CREATE INDEX idx_product_featured ON product(featured) WHERE featured = TRUE;
CREATE INDEX idx_product_new_arrival ON product(new_arrival) WHERE new_arrival = TRUE;
執行遷移
自動執行
Spring Boot 啟動時會自動執行未套用的遷移:
# application.yml
spring:
flyway:
enabled: true
locations: classpath:db/migration
手動執行
# 執行遷移
./gradlew flywayMigrate
# 查看遷移狀態
./gradlew flywayInfo
# 驗證遷移
./gradlew flywayValidate
最佳實踐
1. 遷移腳本不可修改
一旦遷移腳本已在任何環境執行,就不應該修改。如需變更,請建立新的遷移腳本。
2. 保持向後相容
新增欄位時使用 DEFAULT 值或允許 NULL:
-- 好:有預設值
ALTER TABLE product ADD COLUMN discount DECIMAL(5, 2) DEFAULT 0;
-- 好:允許 NULL
ALTER TABLE product ADD COLUMN description VARCHAR(2000);
-- 避免:NOT NULL 且無預設值(會導致現有資料失敗)
ALTER TABLE product ADD COLUMN required_field VARCHAR(100) NOT NULL;
3. 大型資料表變更
對於大型資料表,考慮分批處理:
-- 分批更新資料
UPDATE product SET status = 'ACTIVE' WHERE status IS NULL LIMIT 1000;
4. 測試遷移
在本地或測試環境驗證遷移腳本:
# 重建資料庫並執行所有遷移
./gradlew flywayClean flywayMigrate
常見問題
遷移失敗
如果遷移失敗,Flyway 會記錄失敗狀態。修復後需要:
# 修復失敗的遷移記錄
./gradlew flywayRepair
版本衝突
多人開發時可能出現版本號衝突,建議:
- 使用較大的版本號間隔
- 合併前檢查
flyway_schema_history表 - 協調團隊成員避免衝突
下一步
- Entity 設計 - Entity 與資料表對應
- AppFuse 框架應用 - 框架核心功能
- 專案模式 - 專案架構總覽