สรุปสั้น ๆ
เขียน Go ต่อกับฐานข้อมูล SQL ไม่รู้จะจัก GORM ไม่ได้แล้วว
เขียนโดย
Sirasit Boonklang (Aeff)
Tech and Coding Consultant
บทความนี้ตีพิมพ์ และ เผยแพร่เมื่อ 9 พฤษภาคม 2566
GORM คืออะไร
GORM คือ Library ของ ORM สำหรับใช้งานในภาษา Golang
แล้วเจ้า ORM เนี่ยคืออะไรอีก?
ORM คือ เทคนิคที่ช่วยให้เราสามารถแมปข้อมูลระหว่าง Relational Database กับภาษาโปรแกรมมิ่งที่เขียนแบบ OOP โดยจะทำให้เราไม่จำเป็นต้องเขียนคำสั่ง SQL เอง แต่จะเป็นการเขียนในรูปแบบคำสั่งของภาษาโปรแกรมมิ่งนั้น ๆ ได้เลย ทำให้ลดความซับซ้อนของการติดต่อหรือมี Interact กับฐานข้อมูล
ฟีเจอร์เด็ด ๆ ของเจ้า GORM
1. Associations: GORM รองรับการเชื่อมโยงประเภทต่าง ๆ เช่น has one, have many, belongs to, many to many, polymorphism และ single-table inheritance สิ่งนี้ทำให้คุณสามารถกำหนดและจัดการความสัมพันธ์ระหว่างตารางฐานข้อมูลต่าง ๆ ได้อย่างง่ายดาย
2. Hooks: GORM จัดเตรียม hooks สำหรับ ก่อนและหลัง Create/Save/Update/Delete/Find operation ทำให้คุณสามารถ custom logic ได้
3.Eager loading: GORM รองรับ eager loading โดยใช้ Method Preload และ Joins ทำให้ลดจำนวนการดึงข้อมูลเฉพาะที่เกี่ยวข้อง
4.Transactions: GORM รองรับ transaction และ nested transaction ช่วยให้มั่นใจได้ถึงความสอดคล้องและความสมบูรณ์ของข้อมูลเมื่อมีการใช้ฐานข้อมูลหลาย operation
5. Context and Prepared Statement Mode รองรับ Context และโหมดคำสั่งที่เตรียมไว้ ทำให้ลดความเสี่ยงของการโจมตี SQL Injection
6. Batch Insert และ FindInBatches: GORM มีฟังก์ชันการแทรกและการค้นหาใน Batch ซึ่งช่วยปรับปรุงประสิทธิภาพการทำงานเมื่อทำงานกับข้อมูลจำนวนมาก
7. SQL Builder: ตัวสร้าง SQL ที่รองรับ Upsert, Locking, Optimizer/Index/Comment Hints, Argument ที่มีชื่อ และ SubQuery
8.Composite Primary Key: GORM รองรับ คีย์หลักแบบผสม Index และ constraint ทำให้คุณสามารถกำหนด schema ซับซ้อนมากขึ้นและรับประกันความสมบูรณ์ของข้อมูลได้
9.Auto Migrations: ฟังก์ชันการย้ายข้อมูลอัตโนมัติที่สามารถสร้างตารางฐานข้อมูลแบบออโต้และอัปเดต schema ได้ตามใจต้องการ
10.Logger: GORM เค้ามี ****Logger**** ที่สามารถช่วยให้เรา Debug และเพิ่มประสิทธิภาพการดึงข้อมูลได้
11.API, Plugin และ Extension: มี API, Plugin และ Extension ให้ใช้เป็นกระบุง (เยอะมาก) ทำให้สามารถเพิ่มฟังก์ชันการทำงานเพิ่มเติมหรือต่อกับเครื่องมืออื่น ๆ ได้อีกมากมาย
12.Developer Friendly: เหล่าเดฟอย่างเรา ๆ จะยิ้มง่ายเพราะมันใช้ได้ง่าย Docs ก็อ่านไม่ยาก ใครอยากอ่านเพิ่มเติมสามารถไปตำได้ที่ [GORM Guides | GORM – The fantastic ORM library for Golang, aims to be developer friendly.](https://gorm.io/docs/)
9.Auto Migrations: ฟังก์ชันการย้ายข้อมูลอัตโนมัติที่สามารถสร้างตารางฐานข้อมูลแบบออโต้และอัปเดต schema ได้ตามใจต้องการ
10.Logger: GORM เค้ามี Logger ที่สามารถช่วยให้เรา Debug และเพิ่มประสิทธิภาพการดึงข้อมูลได้
11.API, Plugin และ Extension: มี API, Plugin และ Extension ให้ใช้เป็นกระบุง (เยอะมาก) ทำให้สามารถเพิ่มฟังก์ชันการทำงานเพิ่มเติมหรือต่อกับเครื่องมืออื่น ๆ ได้อีกมากมาย
12.Developer Friendly: เหล่าเดฟอย่างเรา ๆ จะยิ้มง่ายเพราะมันใช้ได้ง่าย Docs ก็อ่านไม่ยาก ใครอยากอ่านเพิ่มเติมสามารถไปตำได้ที่ GORM Guides | GORM – The fantastic ORM library for Golang, aims to be developer friendly.
เมื่อเราได้รู้จักกับ GORM กันไปแล้วเรามาดูวิธีการใช้งานเบื้องต้นกันดีกว่าาาา
ตัวอย่างการใช้งาน GORM ต่อกับฐานข้อมูล MySQL
1.เริ่มจากสร้างโฟลเดอร์โปรเจกต์ด้วยคำสั่ง md <ชื่อโฟลเดอร์> แล้วทำการ cd <ชื่อโฟลเดอร์> หลังจากนั้นเปิดโปรแกรม VS Code ด้วยคำสั่ง code .
2. เริ่มจากการสร้าง go mod ของโปรเจกต์ด้วยคำสั่ง go mod init <github repo>/ชื่อโปรเจกต์
3. ติดตั้ง GORM ด้วยคำสั่ง go get -u gorm.io/gorm
4. สร้างไฟล์ main.go เริ่มต้นประกาศ package เริ่มต้นเป็น main สร้างฟังก์ชัน main ให้เรียบร้อย และทำการ import “gorm.io/gorm” มาด้วยนะ
package main
import (
"gorm.io/gorm"
)
func main() {
}
5. ต่อมากำหนดโครงสร้างของข้อมูล ชื่อตารางและฟิลด์ต่าง ๆ (คอลัมน์ของตาราง) ว่ามีอะไรบ้างโดยใน Go เวลาที่เขียนเป็น ORM เราจะเขียนอยู่ในรูปแบบ Struct นะ
ในตัวอย่างนี้ เราได้กำหนดโครงสร้างของตาราง `User` ด้วยฟิลด์ ID, Name, Email, Age, CreateAt และ UpdatedAt และเรามีการใช้ gorm ในการกำหนดข้อจำกัดสำหรับแต่ละฟิลด์
type User struct {
ID uint `gorm:"primarykey"`
Name string `gorm:"not null"`
Email string `gorm:"unique"`
Age int
CreatedAt time.Time
UpdatedAt time.Time
}
ส่วนการเชื่อมต่อกับฐานข้อมูล
6. ต่อมาเราก็มาทำการเชื่อมต่อกับฐานข้อมูลโดยตัวอย่างนี้ผมจะใช้เป็น MySQL แต่ไม่ใช่ว่า GORM จะต่อได้แค่ MySQL นะ มันยังต่อกับ PostgreSQL, SQLite, SQL Server, และ TiDB ได้อีกด้วย โดยในส่วนของการเรียกใช้งาน MySQL จะต้องทำการติดตั้งด้วยคำสั่ง go get gorm.io/driver/mysql
และเรียกใช้งานในส่วนของ import ด้วยนะครับ
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
7. การสร้าง GORM Database Connection เพื่อเชื่อมต่อกับฐานข้อมูล MySQL
db, err := gorm.Open(mysql.Open("username:password@tcp(127.0.0.1:3306)/ชื่อฐานข้อมูล?charset=utf8mb4&parseTime=True&loc=Local"), &gorm.Config{})
if err != nil {
panic("failed to connect to database")
}
- mysql.Open: เป็นการระบุว่าเรากำลังใช้ไดรเวอร์ MySQL เพื่อเชื่อมต่อกับฐานข้อมูล
- &gorm.Config{}: สร้าง GORM Config ใหม่พร้อมค่า default
- db, err := gorm.Open(…): เปิด Database Connection ใหม่โดยใช้ไดรเวอร์และ Configuration
- if err != nil {…}: เป็นตัวเช็ค error
8. ก่อนที่เราจะใช้ User model ได้ เราต้องสร้างตารางในฐานข้อมูลก่อน โดยใช้ฟังก์ชัน AutoMigrate ของ GORM ฟังก์ชันนี้จะสร้างตารางสำหรับ User model โดยอัตโนมัติ
db.AutoMigrate(&User{})
9. เมื่อเราทำการต่อกับฐานข้อมูลเรียบร้อยแล้วต่อมาเรามาลองทำ CRUD Operation สำหรับการเพิ่มข้อมูล ดึงข้อมูล อัปเดตข้อมูล และลองลบข้อมูลในฐานข้อมูลด้วย Go กันครับ
Create Operation
10. การเพิ่มข้อมูลไปยังฐานข้อมูล เราสามารถสร้าง User คนใหม่เข้าไปได้โดยใช้ฟังก์ชัน Create ที่มากับ GORM ได้เลย เช่น เราจะลองสร้าง User ชื่อ Sirasit, อีเมลคือ sirasit@example.com และอายุเป็น 25 ปี แล้วใช้ฟังก์ชัน Create จะเขียนได้ตามตัวอย่างด้านล่าง
user := User{
Name: "Sirasit",
Email: "sirasit@example.com",
Age: 25,
}
result := db.Create(&user)
if result.Error != nil {
panic("failed to create user")
}
ตัวอย่างโค้ดแบบเต็ม ๆ นะครับ
package main
import (
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primarykey"`
Name string `gorm:"not null"`
Email string `gorm:"unique"`
Age int
CreatedAt time.Time
UpdatedAt time.Time
}
func main() {
db, err := gorm.Open(mysql.Open("ชื่อผู้ใช้:รหัสผ่าน(127.0.0.1:3306)/ชื่อฐานข้อมูล?charset=utf8mb4&parseTime=True&loc=Local"), &gorm.Config{})
if err != nil {
panic("failed to connect to database")
}
db.AutoMigrate(&User{})
user := User{
Name: "Sirasit",
Email: "sirasit@example.com",
Age: 25,
}
result := db.Create(&user)
if result.Error != nil {
panic("failed to create user")
}
}
ผลลัพธ์ที่ได้จากการรันโปรแกรมจะเห็นได้ว่ามีข้อมูลที่เราได้ทำการเพิ่มเข้าไป ไปอยู่ในฐานข้อมูลเป็นที่เรียบร้อยแล้วนะครับ สำหรับในตอนนี้ผมจะใช้เครื่องมือที่ชื่อว่า MySQL Workbench ในการเรียกดูข้อมูลนะครับ
สำหรับใครที่อยากดูวิธีการใช้งาน MySQL Workbench สามารถดูขั้นตอนการใช้งานร่วมกับภาษา Go ได้ที่ https://youtu.be/fjEB75Xotxc?t=12764
Read Operation
11. ในการอ่านข้อมูลจากฐานข้อมูลเราสามารถใช้ฟังก์ชัน Find และ First ได้ โดยเมื่อเราได้ทำการดึงข้อมูลมาแล้วเราจะทำการเช็ค Error และใช้ for loop ในการดึงค่าของข้อมูลแต่ละตัวออกมาแสดง
var users []User
result := db.Find(&users)
if result.Error != nil {
panic("Failed to find users")
}
for _, user := range users {
fmt.Printf("ID: %d, Name: %s, Email: %s, Age: %d\n", user.ID, user.Name, user.Email)
}
หรือหากต้องการดึงเฉพาะ ID นั้น ๆ เราก็สามารถใช้ฟังก์ชัน First หรือ Find และผ่านค่าของตัวแปรชื่อตารางและ ID เข้าไปได้
var user User
result := db.Find(&user, 1) // Find the user with ID 1
if result.Error != nil {
panic(result.Error)
}
fmt.Println(user)
Update Operation
12. ในการอัปเดตเราสามารถใช้ Method Model() และ Updates() ในการอัปเดตข้อมูลได้ โดยในตัวอย่างนี้ จะใช้ db.First() เพื่อค้นหา user ที่มี ID เป็น 1 แล้วก็ใช้ db.Model().Updates() เพื่ออัปเดต Name ให้เป็น “Sirasit Boonklang” แทน และในตัวอย่างโค้ดนี้ผมก็มีการเช็ค Error และนำข้อมูล ID ที่มีการอัปเดตมาแสดงด้วย
var user User
db.First(&user, 1)
db.Model(&user).Updates(User{Name: "Sirasit Boonklang"})
result := db.First(&user, 1)
if result.Error != nil {
panic(result.Error)
}
fmt.Println(user)
Delete Operation
13. สำหรับการลบข้อมูลในฐานข้อมูลเราสามารถใช้ Method Delete ของ GORM ได้เลยโดยใช้คำสั่ง db.Delete()
var user User
result := db.Find(&user, 1)
if result.Error != nil {
panic(result.Error)
}
result = db.Delete(&user)
if result.Error != nil {
panic(result.Error)
}
และแล้วตอนนี้เราก็ได้เรียนรู้พื้นฐานเบื้องต้นเกี่ยวกับ GORM ไปแล้วนะครับ แต่เรายังติดในส่วนของการใช้ gorm.Model กันนะครับ เดี๋ยวผมจะพาไปดูว่าการใช้ gorm.Model มันช่วยเรายังไงได้บ้างไปดูกันครับ
gorm.Model คืออะไร
gorm.Model เป็น Struct ที่มากับเจ้า GORM Lib ตัวนี้ โดย gorm.Model จะมาพร้อมกับฟิลด์ ID, CreateAt, UpdateAt, DeletedAt ซึ่งปกติแล้วฐานข้อมูลส่วนใหญ่ก็จะมีฟิลด์เหล่านี้อยู่
// gorm.Model definition
type Model struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
โดย ID จะเป็นฟิลด์ที่เป็น Primary Key ของโมเดล, CreateAt เอาไว้เก็บว่าเวลาที่ข้อมูลถูกสร้างขึ้นมา, UpdateAt สำหรับเก็บเวลาที่มีการอัปเดตล่าสุด และฟิลด์สุดท้ายคือ DeletedAt เป็นฟิลด์ที่จะบันทึกเวลาและทำเครื่องหมายว่าลบแล้วนั่นเองเป็นแบบ Soft Delete
เมื่อเราจะใช้ gorm.Model เราแค่แปะคำสั่งไว้ใน Struct ของตารางข้อมูลเรา เพียงเท่านี้เราก็จะได้ฟิลด์ของ gorm.Model มาใช้เรียบร้อยแล้ววว
type User struct {
gorm.Model
Name string `gorm:"not null"`
Email string `gorm:"unique"`
Age int
}
เป็นยังไงบ้างครับการใช้งาน GORM ไม่ยากเลยใช่มั้ยครับ หากเพื่อน ๆ อยากฝึกสกิลเพิ่มเติมเกี่ยวกับการใช้งาน GORM อ่านเพิ่มเติมได้จาก Docs ในลิงก์นี้ได้เลยนะครับ GORM Guides | GORM – The fantastic ORM library for Golang, aims to be developer friendly.
และหากอยากรู้ว่าถ้าเราไม่ใช้ GORM ทำ CRUD แบบปกติจาก Standard Library เลยมีวิธีการยังไงบ้างและแตกต่างกันยังไงสามารถดูตัวอย่างการทำได้ที่ (572) สอนทำ CRUD ด้วย Golang แบบไม่เกรงใจใคร ! – YouTube
- app = Flask(name): ที่ ส่วนในการสร้าง Flask Instance เริ่มต้น
- app.config[‘SECRET_KEY’] = ‘SECRET_KEY’ : แอตทริบิวต์ app.config เป็น dict ในการเก็บการ config ต่าง ๆ ของแอป จะตั้งค่าของตัวแปร config โดยใช้ SECRET_KEY เป็นสตริง ใช้เป็นคีย์ลับเพื่อเข้ารหัสคุกกี้และป้องกันการโจมตีต่างๆ เช่น การโจมตี CSRF
- CONNECTION_STRING = “” : ตัวแปร CONNECTION_STRING คือ Connection String ที่ใช้เชื่อมต่อกับบัญชี Azure Blob Storage ค่าของสตริงนี้รวมถึง AccountName, AccountKey, และ EndpointSuffix
- CONTAINER_NAME =””: คือ ชื่อคอนเทนเนอร์ในบัญชี Blob Storage ที่จะจัดเก็บไฟล์
ระบบฝึกทักษะ การเขียนโปรแกรม
ที่พร้อมตรวจผลงานคุณ 24 ชั่วโมง
- โจทย์ปัญหากว่า 200 ข้อ ที่รอท้าทายคุณอยู่
- รองรับ 9 ภาษาโปรแกรมหลัก ไม่ว่าจะ Java, Python, C ก็เขียนได้
- ใช้งานได้ฟรี ! ครบ 20 ข้อขึ้นไป รับ Certificate ไปเลย !!