Migration
Nội dung bài · 5 mục
- 1.Khái niệm
- 2.Ví dụ
- 3.Thử ngay
- 4.Lỗi hay gặp
- 5.Tóm tắt
Bài trước dừng ở lỗi ORA-00942: class Product đã có nhưng database chưa
có bảng. Về sau, thêm field stock thì database cũng phải đổi theo.
Migration giữ cho cấu trúc database luôn khớp với class trong code.
Khái niệm
📜 Migration: file SQL có số phiên bản, mô tả cách đổi cấu trúc database từ phiên bản trước sang phiên bản mới.
🛫 Flyway: thư viện chạy các migration chưa chạy mỗi lần server khởi động, rồi ghi chúng vào bảng flyway_schema_history.
Mỗi lần sửa class ảnh hưởng tới bảng, bạn làm hai bước:
| Bước | Làm gì | Kết quả |
|---|---|---|
| 1 | viết file V<số>__<mô_tả>.sql trong src/main/resources/db/migration |
câu SQL đổi cấu trúc |
| 2 | ./mvnw spring-boot:run |
Flyway chạy các migration chưa chạy vào database |
Ví dụ
Thêm Flyway vào <dependencies> của pom.xml. Gói thứ hai giúp Flyway làm
việc được với Oracle.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-flyway</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-oracle</artifactId>
</dependency>Viết migration đầu tiên,
src/main/resources/db/migration/V1__create_products.sql:
CREATE TABLE products (
id NUMBER GENERATED BY DEFAULT AS IDENTITY
PRIMARY KEY,
name VARCHAR2(200) NOT NULL,
price NUMBER NOT NULL
);Thêm vào application.properties:
spring.jpa.hibernate.ddl-auto=validate- Tên file theo mẫu
V1__create_products.sql: chữV, số phiên bản, hai dấu gạch dưới, rồi mô tả. Flyway chạy các file theo thứ tự số. - Đây là câu
CREATE TABLEnhư ở khoá SQL.GENERATED BY DEFAULT AS IDENTITYcho Oracle tự tăngid, khớp vớiGenerationType.IDENTITYcủa entity. ddl-auto=validate: lúc khởi động, Hibernate so entity với bảng thật và dừng server nếu thiếu bảng hay thiếu cột. Hibernate không tự sửa bảng, việc đó thuộc về Flyway.- Lần chạy đầu, Flyway tạo thêm bảng
flyway_schema_historyđể ghi lại migration nào đã chạy. - Migration là file trong project, được commit lên git cùng code. Cả team và server dùng chung một lịch sử thay đổi database.
Thử ngay
Chạy server, gọi lại GET /api/products sẽ nhận []. Giờ thêm field
stock vào Product:
// Product.java
package com.shop.api;
import jakarta.persistence.*;
@Entity
@Table(name = "products")
class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name = "";
private long price;
private int stock;
public Long getId() { return id; }
public String getName() { return name; }
public void setName(String name) {
this.name = name;
}
public long getPrice() { return price; }
public void setPrice(long price) {
this.price = price;
}
public int getStock() { return stock; }
public void setStock(int stock) {
this.stock = stock;
}
}Viết migration thứ hai, V2__add_stock.sql, cạnh file V1:
ALTER TABLE products
ADD stock NUMBER(10) DEFAULT 0 NOT NULL;Rồi chạy lại ./mvnw spring-boot:run.
Đoán trước khi chạy: Flyway sẽ chạy lại cả V1 (và báo lỗi vì bảng đã
có), hay chỉ chạy V2?
Xem kết quả
Current version of schema "SHOPBOOT": 1
Migrating schema "SHOPBOOT" to version "2 - add stock"
Successfully applied 1 migration to schema
"SHOPBOOT", now at version v2Chỉ chạy V2. Flyway đọc flyway_schema_history, thấy V1 đã chạy nên bỏ
qua. Các dòng đã có vẫn giữ nguyên, cột STOCK nhận giá trị mặc định 0.
Lỗi hay gặp
Sửa class mà quên viết migration. Với ddl-auto=validate, server dừng
ngay lúc khởi động vì database chưa có cột mới.
Schema validation: missing column [stock] in table [products]# SAI — thêm field stock nhưng chỉ có V1
src/main/resources/db/migration/
V1__create_products.sql# ĐÚNG — mỗi thay đổi một migration mới
src/main/resources/db/migration/
V1__create_products.sql
V2__add_stock.sqlSửa file migration đã chạy. Flyway lưu mã kiểm tra (checksum) của từng
file đã chạy. File đổi thì server dừng với lỗi Migration checksum mismatch for migration version 1. Muốn đổi thêm thì viết migration mới.
Tóm tắt
- Migration là file SQL có số phiên bản, mô tả cách đổi cấu trúc database.
- Flyway tự chạy các migration chưa chạy mỗi lần server khởi động.
ddl-auto=validatebáo lỗi ngay khi entity và bảng lệch nhau.- Migration được commit lên git. Không sửa migration đã chạy, hãy viết migration mới.
Tự kiểm tra
0/3 câuBạn thêm field email vào class Customer. Cần làm gì để database có cột EMAIL?
Bảng flyway_schema_history dùng để làm gì?
Thư mục db/migration có nên commit lên git không?