iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0

GORM

在介紹 GORM 之前,先來看看什麼是 ORM~
官網:https://gorm.io/index.html


ORM 是什麼?

ORM 是 Object Relational Mapping(物件關聯對映)。目的就是「 用物件導向的方式來操作資料庫 」,而不寫 SQL。

  1. Object(物件)
    對應到 Go 的話,就是 struct ,可以理解為程式的物件模型,例如 To-do List 的 Task:

    type Task struct {
        ID    uint
        Item string
        Status  bool
    }
    
  2. Relational(關聯)
    SQLite / MySQL / Postgres 都是關聯式資料庫!
    資料是用 表格(Table) 來表示的:

    CREATE TABLE tasks (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        item TEXT,
        status BOOLEAN
    );
    
  3. Mapping(對映)
    ORM 就是把 程式中的物件資料庫中的表格 做「一對一的映射」。
    意思就是:

    • struct 的欄位 → table 的 column
    • struct 的一筆資料 → table 的一列 row
      Mapping 之後就可以直接用物件操作資料庫,而不需要自己寫 SQL。

我們來看看以一般的 SQL 操作和使用 ORM 操作的差別:

  1. 一般 SQL

    每一次的查詢、更新、新增 都要寫 SQL 才能完成。且每次都要自己拼 SQL,容易出錯之外,只要欄位改變,SQL + Scan() 也都要改。最重要的是 SQL 跟程式綁死了,非常不好閱讀!
    例如:

    // 新增 task
    stmt, _ := db.Prepare("INSERT INTO tasks(item, status) VALUES (?, ?)")
    stmt.Exec("買牛奶", false)
    
    // 查詢
    rows, _ := db.Query("SELECT id, item, status FROM tasks")
    for rows.Next() {
        var id int
        var item string
        var status bool
        rows.Scan(&id, &item, &status)
        fmt.Println(id, item, status)
    }
    
  2. ORM(GORM)
    我們一樣新增、查詢 Task,同樣的操作,用 ORM 寫就變得簡單很多,原因是我們不用再多寫 SQL,而是直接用物件來存取資料,剩下的 GORM 會自動幫你完成。
    例如:

    // 定義 struct
        type Task struct {
            id    uint
            item string
            status  bool
        }
    
    // 新增 task
    db.Create(&Task{item: "買牛奶", status: false})
    
    // 查詢
    var tasks []Task
    db.Find(&tasks)
    fmt.Println(tasks)
    

那為什麼要用 GORM 呢?

因為 GORM 是目前 Go 最熱門的 ORM,原因是它把「 程式中的物件 」和「 資料庫 」整合得很好。
以下是 GOR

  1. CRUD(Create/Read/Update/Delete)

    db.Create(&tasks)                        // 新增
    db.First(&tasks, 1)                      // 讀取 (id=1)
    db.Model(&tasks).Update("status", true)  // 更新
    db.Delete(&tasks)                        // 刪除
    
  2. Migration
    可以自動建表或更新欄位。

    db.AutoMigrate(&Task{})
    
  3. 條件查詢

    db.Where("status = ?", false).Find(&tasks)
    
  4. 關聯模型

    • One-to-One
    • One-to-Many
    • Many-to-Many。例如:User 可以有多個 Tasks。
  5. 跨資料庫支援
    換成 MySQL、Postgres 資料庫也幾乎不用改程式碼。


常用指令對照表:

Create:

動作 SQL GORM
新增一筆資料 INSERT INTO users (id, item, status) VALUES (1, "寫鐵人賽文章", false); db.Create(&Task{ID: 1, Item: "寫鐵人賽文章", Status: false})

Read:

動作 SQL GORM
查第一筆 (id=1) SELECT * FROM tasks WHERE id = 1 LIMIT 1; db.First(&tasks, 1)
查第一筆符合條件 SELECT * FROM tasks WHERE item = "鐵人賽" LIMIT 1; db.First(&tasks, "item = ?", "鐵人賽")
查全部 SELECT * FROM tasks; db.Find(&tasks)
條件查詢 SELECT * FROM tasks WHERE id > 18; db.Where("id > ?", 18).Find(&tasks)
排序 SELECT * FROM tasks ORDER BY id DESC; db.Order("id desc").Find(&tasks)
限制筆數 SELECT * FROM tasks LIMIT 10; db.Limit(10).Find(&tasks)
分頁 SELECT * FROM tasks LIMIT 10 OFFSET 20; db.Limit(10).Offset(20).Find(&tasks)

Update:

動作 SQL GORM
更新單一欄位 UPDATE tasks SET status = true WHERE id = 1; db.Model(&tasks).Update("status", true)
更新多個欄位 UPDATE tasks SET item = "寫日記", status = false WHERE id = 1; db.Model(&tasks).Updates(Task{Item: "寫日記", Status: false})
條件更新 UPDATE tasks SET status = false WHERE item = "寫日記"; db.Model(&Task{}).Where("item = ?", "寫日記").Update("id", 40)

Delete:

動作 SQL GORM
刪除一筆 DELETE FROM tasks WHERE id = 1; db.Delete(&tasks)
條件刪除 DELETE FROM tasks WHERE id < 5; db.Where("id < ?", 5).Delete(&Task{})

但即便如此方便,也不是每個人都會使用~ 畢竟它還是有一些缺點在:

  • 效能稍差:GORM 會自動轉換 SQL,所以會多一些 overhead。但在高效能系統中,直接寫 SQL 可能會比較快。
  • 學習曲線高:因為功能很多,所以對於初學者來說會覺得「比 SQL 更複雜」!
  • 對於複雜的查詢,還是要寫 SQL:像是 JOIN 很多表、複雜的 aggregate,GORM 也不一定比較好用。

明天開始就會一步步的修改 To-do List ,讓它可以直接把資料存入資料庫中。


上一篇
Day17 - Go 與資料庫:SQLite
下一篇
Day19 - Go 與資料庫:用 GORM 操作 SQLite
系列文
Go,一起成為全端吧!—— 給前端工程師的 Golang 後端學習筆記24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言