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

Web Security

Khái niệm Web Security Web Security là tập hợp các nguyên tắc, biện pháp và công nghệ nhằm bảo vệ website, ứng dụng web và dữ liệu khỏi các hành vi truy cập trái phép, tấn công độc hại hoặc khai thác lỗ hổng. Nó không chỉ bao gồm việc ngăn chặn hacker, mà còn […]

Markdown

Markdown là một ngôn ngữ đánh dấu nhẹ (lightweight markup language) dùng để định dạng văn bản thuần túy (plain text), thường được sử dụng trong các tài liệu như README, bài viết blog, tài liệu hướng dẫn, và cả trong GitHub, Stack Overflow, hoặc các trình soạn thảo như VS Code, Obsidian… Markdown được […]

CSS

CSS (Cascading Style Sheets – tạm dịch: Tập tin định kiểu tầng) là ngôn ngữ dùng để mô tả cách trình bày (giao diện) của một tài liệu HTML. Nói đơn giản, CSS giúp làm đẹp trang web: chỉnh màu sắc, font chữ, bố cục, khoảng cách, hiệu ứng chuyển động, v.v. CSS được phát […]

HTML

HTML (HyperText Markup Language) là ngôn ngữ đánh dấu siêu văn bản, được dùng để xây dựng cấu trúc của một trang web. Nói cách khác, HTML cho trình duyệt biết nội dung nào sẽ hiển thị và hiển thị như thế nào (như tiêu đề, đoạn văn, hình ảnh, liên kết…). Một tài liệu […]

Browser

Browser (Web Browser, Trình duyệt web) là phần mềm trên máy tính, điện thoại hoặc thiết bị thông minh, cho phép người dùng truy cập, hiển thị và tương tác với các trang web, tài nguyên Internet. Về bản chất, trình duyệt gửi các yêu cầu (HTTP/HTTPS request) đến máy chủ web, nhận về mã […]

Tìm hiểu DNS

DNS là gì? DNS (Domain Name System) là một dịch vụ phân giải tên miền, giúp chuyển đổi các tên miền (ví dụ: www.ducphat.com) thành địa chỉ IP (ví dụ: 93.184.216.34) và ngược lại. Thay vì phải nhớ dãy số IP, chúng ta chỉ cần nhập tên miền, DNS sẽ tìm kiếm địa chỉ IP […]