1. GORM là gì?
GORM (Go ORM) là thư viện Object-Relational Mapping dành cho Go, giúp làm việc với cơ sở dữ liệu quan hệ thông qua các struct và API của Go thay vì phải viết SQL cho mọi thao tác.
Trong một ứng dụng backend, dữ liệu thường được lưu trong PostgreSQL, MySQL hoặc SQLite. Nếu không sử dụng ORM, developer thường phải tự viết câu SQL, truyền tham số, thực thi truy vấn và chuyển kết quả từ các hàng trong database thành struct Go.
Ví dụ, thay vì viết SQL:
SELECT * FROM users WHERE id = 1;
Có thể dùng GORM:
var user User
result := db.First(&user, 1)
if result.Error != nil {
return result.Error
}
GORM sẽ xây dựng và thực thi truy vấn phù hợp với database driver đang sử dụng, sau đó ánh xạ dữ liệu trả về vào biến user.
2. ORM hoạt động như thế nào?
Để sử dụng GORM hiệu quả, cần hiểu vai trò của từng thành phần.
Giả sử ứng dụng quản lý người dùng. Trong Go, ta định nghĩa:
type User struct {
ID uint
Name string
Email string
}
Struct User biểu diễn dữ liệu trong chương trình. GORM dựa trên cấu trúc này và các quy ước mặc định để ánh xạ sang bảng trong database.
Một thao tác như:
user := User{
Name: "An",
Email: "[email protected]",
}
result := db.Create(&user)
sẽ đi qua các bước khái quát:
- GORM đọc cấu trúc model và thông tin cấu hình.
- GORM xây dựng câu SQL tương ứng.
- Database driver gửi truy vấn đến database.
- Database thực thi câu SQL và trả về kết quả.
- GORM cập nhật các thông tin liên quan vào struct, chẳng hạn ID được sinh tự động.
- Ứng dụng kiểm tra lỗi qua
result.Error.
3. Model trong GORM
Model là thành phần cốt lõi của GORM. Một model thường biểu diễn một thực thể nghiệp vụ và được ánh xạ tới một bảng trong database.
Định nghĩa model
type User struct {
ID uint
Name string
Email string
Age int
}
Theo quy ước mặc định, GORM thường ánh xạ model này tới bảng users.
Sử dụng gorm.Model
GORM cung cấp struct nền gorm.Model:
type User struct {
gorm.Model
Name string
Email string
}
gorm.Model bao gồm các trường:
type Model struct {
ID uint
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt
}
Tùy chỉnh tên bảng
Có thể ghi đè quy ước tên bảng bằng phương thức TableName:
type User struct {
ID uint
Name string
}
func (User) TableName() string {
return "app_users"
}
Khi đó, model User được ánh xạ tới bảng app_users.
4. Associations – Quan hệ giữa các model
Trong database quan hệ, các bảng thường liên kết với nhau bằng foreign key. GORM hỗ trợ ánh xạ những mối quan hệ này thành các field trong struct.
Ba nhóm quan hệ cơ bản là:
- One-to-One: một-một.
- One-to-Many / Many-to-One: một-nhiều / nhiều-một.
- Many-to-Many: nhiều-nhiều.
Belongs To – Quan hệ nhiều-một
Ví dụ nhiều bài viết thuộc về một người dùng:
type User struct {
ID uint
Name string
}
type Post struct {
ID uint
Title string
UserID uint
User User
}
Post.UserID là foreign key tham chiếu đến người dùng. Post.User biểu diễn quan hệ trong model.
Truy vấn bài viết cùng thông tin người dùng:
var post Post
err := db.Preload("User").
First(&post, 1).Error
Has Many – Quan hệ một-nhiều
Một người dùng có thể có nhiều bài viết:
type User struct {
ID uint
Name string
Posts []Post
}
type Post struct {
ID uint
Title string
UserID uint
}
Có thể tải người dùng cùng các bài viết:
var user User
err := db.Preload("Posts").
First(&user, 1).Error
Has One – Quan hệ một-một
Ví dụ một người dùng có một hồ sơ chi tiết:
type User struct {
ID uint
Name string
Profile Profile
}
type Profile struct {
ID uint
Bio string
UserID uint
}
Profile.UserID liên kết hồ sơ với người dùng.
var user User
err := db.Preload("Profile").
First(&user, 1).Error
Nếu quan hệ là một-một theo nghiệp vụ, nên thiết lập unique constraint cho foreign key phù hợp. Khai báo struct không tự nó thay thế việc thiết kế constraint ở database.
5. Tổng kết
GORM là một ORM giúp developer Go làm việc với database quan hệ thông qua model và API Go, giảm lượng code CRUD lặp lại và hỗ trợ nhiều tính năng như association, transaction, migration, hooks, logging và query builder.
Tuy nhiên, sử dụng GORM hiệu quả không chỉ là ghi nhớ cú pháp. Developer cần hiểu SQL được sinh ra, cách database thực thi truy vấn, cơ chế transaction, các ràng buộc dữ liệu và những đánh đổi về hiệu năng.
Các nguyên tắc cần ghi nhớ:
- Model biểu diễn cấu trúc dữ liệu; schema thực tế vẫn cần được quản lý.
- Luôn kiểm tra lỗi sau thao tác database.
- Hiểu cách
Updatesxử lý zero-value. - Dùng parameterized query và kiểm soát SQL động.
- Dùng transaction khi nhiều thay đổi cần thành công hoặc thất bại cùng nhau.
- Dùng
PreloadhoặcJoinsđúng mục đích để tránh N+1 Query. - Kiểm tra SQL và execution plan khi tối ưu hiệu năng.
- Đặt logic nghiệp vụ phức tạp ở service layer thay vì phụ thuộc hoàn toàn vào hooks.
- Kết hợp GORM với SQL trực tiếp khi điều đó làm truy vấn rõ ràng hoặc hiệu quả hơn.








Khoá học lập trình game con rắn cho trẻ em




