VieTopik
Tiếng HànTiếng AnhIT
  • Góc học tập
Tải app
  • Thư viện
  • Luyện thi
  • Cẩm nang
  • Góc học tập
Spring Boot Web APIDữ liệu với JPA
Bài 14/19
5 phút

Migration

Nội dung bài · 5 mục
  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 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 TABLE như ở khoá SQL. GENERATED BY DEFAULT AS IDENTITY cho Oracle tự tăng id, khớp với GenerationType.IDENTITY củ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 v2

Chỉ 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.sql

Sử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=validate bá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âu
Câu 1

Bạn thêm field email vào class Customer. Cần làm gì để database có cột EMAIL?

Câu 2

Bảng flyway_schema_history dùng để làm gì?

Câu 3

Thư mục db/migration có nên commit lên git không?

JPA và repositoryTruy vấn với JPA

Nội dung bài

  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt