1. 程式人生 > 其它 >Golang ORM類庫:GORM的使用總結

Golang ORM類庫:GORM的使用總結

Golang ORM類庫:GORM的使用總結

技術概述

ORM(Object Relation Mapping 關係物件對映),就是把物件模型表示的物件對映到基於SQL的關係模型資料庫結構中,在具體的操作實體物件的時候,不需要直接與複雜的 SQL語句打交道,只需簡單的操作實體物件的屬性和方法。而GORM就是基於Go語言實現的ORM庫。在使用Go語言開發專案的時候,我們可以利用GORM來實現對資料庫的操作,進行簡單的CRUD操作。

技術詳述

使用流程

使用GORM

1.匯入GROM和資料庫驅動

可以使用一下命令安裝GROM和資料庫驅動

go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql

但是這是一種比較傳統的方法。我們還可以在專案中使用go.mod檔案設定專案需要新增的依賴包:

go 1.15

require (
	gorm.io/driver/mysql v1.0.5
	gorm.io/gorm v1.21.8
)

像上面這樣定義好需要新增的依賴包之後,就可以直接執行下面這一條指令讓go.mod檔案自動引入所有依賴包:

go mod download

執行完上述指令若沒有任何反應則說明已經成功將GORM和資料庫驅動的依賴包匯入了

2.定義資料庫連線資訊

在專案中的.env檔案中編寫資料庫連線的資訊,可以大致按照如下格式編寫,但需要根據具體專案要求修改具體資訊,比如這裡使用的資料庫是MySQL的,如果使用的是其他資料庫(PostgreSQL等),則需要修改MYSQL_DSN的內容:

MYSQL_DSN="root:12345678@tcp(localhost:3306)/pingleme?charset=utf8&parseTime=True&loc=Local"
REDIS_ADDR="pingleme.top:6379"
REDIS_PW="Test1234"
REDIS_DB=""
SESSION_SECRET="setOnProducation"
GIN_MODE="debug"
LOG_LEVEL="debug"
LOG_PATH="./.log/system.log"
LOG_MAX_SIZE="50"
LOG_MAX_AGE="30"
LOG_MAX_BACKUP="0"
LOG_COMPRESS="false"
LOG_JSON_FORMAT="false"
LOG_SHOW_LINES="true"
LOG_SHOW_IN_CONSOLE="true"
DB_LOG_LEVEL="info"

在這裡可能會遇到一些連線問題,會在之後的“遇到的問題和解決過程”模組解釋

3.獲取資料庫連線

完成以上準備工作後,需要先獲取資料庫的連線:

package main

import (
  "gorm.io/gorm"
  "gorm.io/driver/mysql"
)

func main() {
  db, err := gorm.Open("mysql", &gorm.Config{})
  if err != nil {
    panic("failed to connect database")
  }
  defer db.Close()
  db.SingularTable(true)
}

4.定義資料庫模型

GORM 傾向於約定,而不是配置。預設情況下,GORM 使用 ID 作為主鍵,使用結構體名的 蛇形複數 作為表名,欄位名的 蛇形 作為列名,並使用 CreatedAt、UpdatedAt 欄位追蹤建立、更新時間。

定義資料庫模型就是將資料庫的表結構對應到struct中,比如如下的使用者表表結構:

CREATE TABLE `users` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `uid` varchar(191) NOT NULL,
  `password_digest` longtext NOT NULL,
  `user_name` varchar(20) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uid` (`uid`),
) ENGINE=InnoDB AUTO_INCREMENT=48 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

可以定義對應的struct:

// User 使用者模型
type User struct {
	gorm.Model
	UID            string `gorm:"not null;unique"`
	PasswordDigest string `gorm:"not null"`
	UserName       string `gorm:"type:varchar(20);not null"`
}

struct的每個欄位都對應著資料庫表中的欄位,而資料庫欄位的屬性則由gorm宣告的結構標記來定義。比如,"type:varchar(20)"定義了欄位的型別與長度、"not null"則聲明瞭欄位是非空的,這些都與資料庫中的宣告一一對應。更多的屬性定義可以檢視官方文件給出的GORM模型定義

5.CRUD操作

5.1 建立
user := User{UID: "221801114", PasswordDigest: "123456", UserName: "silicon"}

result := db.Create(&user) // 通過資料的指標來建立

user.ID             // 返回插入資料的主鍵
result.Error        // 返回 error
result.RowsAffected // 返回插入記錄的條數
5.2 查詢
// 獲取第一條記錄(主鍵升序)
db.First(&user)
// SELECT * FROM users ORDER BY id LIMIT 1;

// 獲取一條記錄,沒有指定排序欄位
db.Take(&user)
// SELECT * FROM users LIMIT 1;

// 獲取最後一條記錄(主鍵降序)
db.Last(&user)
// SELECT * FROM users ORDER BY id DESC LIMIT 1;

// 獲取全部記錄
result := db.Find(&users)
// SELECT * FROM users;

result := db.First(&user)
result.RowsAffected // 返回找到的記錄數
result.Error        // returns error

// 檢查 ErrRecordNotFound 錯誤
errors.Is(result.Error, gorm.ErrRecordNotFound)
5.3 更新
db.First(&user)

user.PasswordDigest = "12345678"
db.Save(&user)
// UPDATE users SET uid='221801114', passworddigest="12345678", birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=1;
5.4 刪除

刪除記錄時需要帶主鍵,否則會導致批量刪除:

// user 的 ID 是 `1`
db.Delete(&user)
// DELETE from users where id = 1;

// 帶額外條件的刪除
db.Where("uid = ?", "221801114").Delete(&user)
// DELETE from users where id = 1 AND uid = "221801114";

遇到的問題和解決過程

1. 資料庫連線字串出錯

問題描述

當時配置資料庫資訊的時候沒有按照規範書寫連線串,導致資料庫連線失敗,錯誤程式碼如下:

MYSQL_DSN="root:12345678/pingleme?charset=utf8&parseTime=True&loc=Local"

解決

應當要將埠號等資訊放在“@tcp()”的括號中,具體可以按照如下格式修改:

MYSQL_DSN="user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"

2.資料庫欄位包含sql的關鍵字

問題描述

我在設計一個數據庫表結構的時候,誤將sql語句的關鍵字"index"作為資料庫欄位的名字:

CREATE TABLE `scoring_items` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `created_at` datetime(3) DEFAULT NULL,
  `updated_at` datetime(3) DEFAULT NULL,
  `deleted_at` datetime(3) DEFAULT NULL,
  `homework_id` bigint unsigned NOT NULL,
  `description` varchar(255) NOT NULL,
  `score` bigint NOT NULL DEFAULT '-1',
  `option` tinyint NOT NULL,
  `note` varchar(255) DEFAULT NULL,
  `assistant_id` bigint NOT NULL,
  `level` bigint NOT NULL DEFAULT '0',
  `index` bigint NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_scoring_items_deleted_at` (`deleted_at`),
  KEY `fk_homeworks_scoring_items` (`homework_id`),
  CONSTRAINT `fk_homeworks_scoring_items` FOREIGN KEY (`homework_id`) REFERENCES `homeworks` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

以致於我對這一個資料庫表的如下查詢操作屢次失敗,找不出原因:

result = Repo.DB.Order("index desc").Where("homework_id = ?", ID).Find(&items)

解決

在使用該欄位進行查詢時,應該將該欄位的名稱包含在``之間,就可以避免與sql的衝突。比如,可以將上面的查詢操作改為如下形式:

result = Repo.DB.Order("`index` desc").Where("homework_id = ?", ID).Find(&items)

總結

通過上述的介紹,就可以大致地使用GO提供的ORM類庫GORM輕鬆的進行簡單的CRUD操作了。學會了GORM,就不需要自己維護sql語句了。

參考文獻

GORM指南