1. Giới thiệu

Go-pg sử dụng công nghệ ORM (tức Object-relation mapping) giúp ánh xạ bảng cơ sở dữ liệu vào trong struct

Điều đấy có nghĩa là với mỗi struct trong golang có thể dùng làm đại diện để truy vấn đến bảng trong postgresql và trả ra đối tượng struct với giá trị tương ứng.

2. Cách định nghĩa model, tên struct, tên cột hợp lý

Go-pg có thể tự động nhận biết tên trường, tên struct, kiểu biến để khởi tạo bảng trong postgresql. Ví dụ:

  • nếu tên struct là Genre sẽ mặc định có tên bảng là genres
  • tên trường là FullName sẽ có tên cột là full_name
  • Kiểu string sẽ tương ứng với kiểu text trong database, int thành bigint,…
  • Trường có tên là Id tự động được thêm vào primary key.

Nếu không muốn để mặc định thì có thể ghi đè bằng những tags như: pg:"type:kiểu",pg:"tên cột",… hay thêm các ràng buộc cho cột như pg:,unique

Có thể tham khảo thêm tại đây

Ví dụ về định nghĩa model:

type User struct{
    tableName struct{} `pg:"auth.users"`    //Tên schema auth, bảng users

    Id int `pg:"type:serial,pk"`    //Cột id đặt là primary key, với kiểu là serial

    FirstName string    //String sẽ tương ứng với kiểu text trong database, tên cột là first_name

    LastName string     //tên cột là last_name

    Email string    `pg:",unique"`  //Email điều kiện là không được trùng lặp

    Password string
}
  • Trường Id trong model User trên thay vì để kiểu mặc định là bigint, ta thay bằng serial. Và đuôi ,pk không thực sự cần thiết vì id sẽ mặc định là primary key
  • Nếu bỏ dòng tableName thì tên table sẽ mặc định là users. Nếu muốn ghi đè tên mặc định hoặc tạo bảng trong một schema thì đây là điều bắt buộc

3. Định nghĩa model quan hệ 1 – 1

Giả sử ta có 2 bảng User với Profile, với mỗi User chỉ có một Profile và ngược lại. Đây là quan hệ một một. Ta có thể định nghĩa model như sau

type User struct{
    tableName struct{} `pg:"auth.users"`

    Id int `pg:"serial"`

    Name string

    Profile *Profile `pg:"rel:belongs-to"`  //Profile thuộc về User
}
type Profile struct{
    tableName struct{} `pg:"auth.profile"`

    Id     int    `pg:"type:serial"`

    Avatar string

    UserId int  `pg:",unique"` //Id của User mà Profile thuộc về, đây là trường cần thiết để go-pg hiểu được quan hệ
}

Lưu ý: – Việc đặt unique ở UserId trong Profile không bắt buộc, chỉ nhằm để không có UserId nào giống nhau, như vậy sẽ đảm bảo quan hệ thực sự là 1 – 1 hơn. Nếu không có unique ta có thể có 2 Profile với cùng một UserId, như vậy sẽ mất đi bản chất quan hệ 1 – 1.

4. Định nghĩa model quan hệ 1 – nhiều

Một user có thể có nhiều bài post. Ta có thể định nghĩa model thể hiện quan hệ này như sau:

type User struct{
    tableName struct{}  `pg:"auth.users"`

    Name string

    //Với mỗi user có thể lấy ra nhiều bài post của chính user đó
    Posts []Post  `pg:"rel:has-many,join_fk:user_id"`
}

Lưu ý: chỉ nên dùng join_fk khi ta muốn sử dụng foreign key với tên khác mặc định. Trong ví dụ trên không thực sự cần thiết

type Post struct{
    tableName struct{} `pg:"blog.post"`

    Id int `pg:"type:serial" `

    Content string `pg:",notnull"`

    Title string    `pg:",notnull"`

    //Đây là trường cần thiết để go-pg hiểu được quan hệ, nếu thay đổi cần thay đổi giá trị join_fk ở User trên
    UserId int `pg:"type:integer"`

    User *User `pg:"rel:has-one"`   //Mỗi post có thể lấy 1 user
}

5. Định nghĩa model quan hệ nhiều – nhiều

Một User có nhiều Role (như admin, teacher,…) và ngược lại một Role cũng có thể có nhiều User. Đây là quan hệ nhiều – nhiều. Trong quan hệ nhiều – nhiều, cách thường thấy là tạo bảng thứ 3 chứa hai id của 2 bảng còn lại. Ta có thể định nghĩa model thể hiện quan hệ này như sau:

type User struct{
    tableName struct{} `pg:"auth.users"`

    Id int `pg:"type:serial"`

    Name string

    //Quan hệ nhiều nhiều tham chiếu đến bảng auth.user_role để lấy giá trị
    Roles []Role `pg:"many2many:auth.user_role"`
}
type Role struct{
    tableName struct{} `pg:"auth.role"`

    Id int    `pg:"type:serial"`

    Name string
}
//Bảng thứ 3 tên auth.user_role thể hiện quan hệ giữa 2 bảng trên
type UserRole struct{

    tableName struct{} `pg:"auth.user_role"`

    UserId int  // Id của User

    RoleId int  // Id của Role
}

Để ORM hiểu được bảng user_role là bảng thể hiện quan hệ nhiều – nhiều của 2 bảng user và role. Ta cần dùng hàm RegisterTable như sau:

    orm.RegisterTable((*UserRole)(nil))

Lưu ý: ta cần chạy hàm này trước khi các model User và Role được sử dụng đến, cách tốt nhất là chạy ngay từ đầu khi mới bắt đầu kết nối database.

Kết

Việc định nghĩa struct model golang cũng chính là đang tạo bảng trong postgresql. Đây là bước cần thiết để ta có thể thao tác với cơ sở dữ liệu sau này.

(https://techmaster.vn/posts/36674/dinh-nghia-model-quan-he-trong-go-pg)

About the Author

Ha Trung Vi

View all author's posts

Leave a Comment

Your email address will not be published. Required fields are marked *

Bài viết khác

GORM

1. ORM là gì? Trước hết để hiểu được thư viện Gorm chúng ta cần tìm hiểu về ORM, một công cụ quan trọng và thường xuyên được áp dụng trong quản trị cơ sở dữ liệu. ORM là tên viết tắt của cụm từ “Object Relational Mapping” đây là tên gọi chỉ việc ánh […]

REST API với Golang, Gin, MinIO và Docker

Đầu tiên, chúng ta sẽ viết một đoạn mã nhỏ bằng chữ Hello World. Bước 1: Tạo thư mục để chứa mã nguồn của dự án Todo App mkdir go-rest-api Bước 2: Khởi tạo Go Modules go mod init TodoApp go get -u github.com/gin-gonic/gin Bước 3: Tạo tệp main.go và viết đầu tiên chương trình […]

REST API cơ bản trong Golang

Cấu trúc project Chúng ta hãy tạo cấu trúc thư mục như hình bên dưới, project này có tên GolangRestApi, có thể clone về với đường link sau: Github Sau khi clone về, đổi tên project thành GolangRestApi. Vào GOPATH, copy vào thư mục src: Code Rest Api Golang entities/user.go Khai báo cấu trúc của […]

Golang

Golang là gì? Go hay còn gọi là Golang là ngôn ngữ lập trình mã nguồn mở, được thiết kế tại Google bởi Robert Griesemer, Rob Pike, and Ken Thompson. Go có cú pháp giống với C và tất nhiên nó là ngôn ngữ lập trình biên dịch (compiled programming language) Cú pháp của ngôn […]

Elasticsearch

Elasticsearch là gì? Elasticsearch là một search engine (công cụ tìm kiếm) rất mạnh mẽ. Elasticsearch cũng có thể coi là một document oriented database, nó chứa dữ liệu giống như một database và thực hiện tìm kiếm trên những dữ liệu đó. Đại khái là thay vì bạn tìm kiếm trên file, trên các […]

Testing

Testing là gì? Thường thì mọi người hiểu khái niệm test chỉ là chạy test, chạy phần mềm nhưng đó chỉ là một phần không phải tất cả các hoạt động test. Các hoạt động test tồn tại trước và sau khi chạy PM bao gồm: lên kế hoạch và kiểm soát, chọn điều kiện […]