1. 概念
Gorm 官網:https://gorm.io/zh_CN/docs/
Gorm:The fantastic ORM library for Golang aims to be developer friendly
,這是官網的介紹,簡單來說 Gorm 就是一款高性能的 Golang ORM 庫,便于開發人員提高效率
那么 ORM(Object Relation Mapping) 又是什么呢?在 Golang 語言中,Object指的就是 struct 結構體對象,Relation 就是數據庫當中的關系,Mapping則表示兩者具有映射關系,具體表現如下:
- Go當中的結構體聲明 <-> 數據庫層面的表結構
- Go當中的結構體實例 <-> 數據庫層面的一條表記錄
2. 數據庫連接
2.1 安裝依賴
想要在 Go 代碼中使用 gorm 我們需要先引入對應的依賴:
- gorm 庫依賴:
gorm.io/gorm
- 特定數據庫驅動依賴:
gorm.io/driver/mysql
然后使用 go mod 包管理工具加載對應的依賴:
- go mod init first_gorm:初始化
- go mod tidy:加載依賴
然后就可以開始編寫代碼了!
2.2 連接數據庫
在操作數據庫之前,我們還需要與指定的數據庫建立連接,此處以 MySQL數據庫為例:
基本語法:db, err := gorm.Open(mysql.Open(dsn語句), &gorm.Config{})
- 其中 dsn 語句為特定的連接格式,形式如下:
user:pwd@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local
package mainimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm"
)func main() {var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})if err != nil {fmt.Println("數據庫連接失敗!", err)}fmt.Println(db)
}
程序運行結果:
控制臺打印出 db 對象,說明我們已經成功與數據庫建立連接(必須保證數據庫中存在指定的數據庫)
3. 數據庫基本操作
3.1 創建表(表關系映射)
3.1.1 基本使用
我們可以使用 gorm 提供的 API 來創建指定的表,需要關注的是 結構體聲明 <=> 數據庫表結構,因此我們想要創建一個表結構實則只需要定義一個結構體類型
-- 創建user表 --
create table t_user (user_id bigint primary key auto_increment,user_name varchar(32) not null,user_pwd varchar(128) not null,user_phone varchar(32) unique
)
使用上述 SQL 語句創建表的行為等價于在 Go 語言當中定義下列結構體對象:
// User 結構體聲明
type User struct {UserId int64 `gorm:"primaryKey;autoIncrement"`UserName string `gorm:"not null;type:varchar(32)"`UserPwd string `gorm:"not null;type:varchar(128)"`UserPhone string `gorm:"unique;type:varchar(32)"`
}
創建表基本語法:err := db.AutoMigrate(&特定結構體{})
package mainimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm"
)// User 結構體聲明
type User struct {UserId int64 `gorm:"primaryKey;autoIncrement"`UserName string `gorm:"not null;type:varchar(32)"`UserPwd string `gorm:"not null;type:varchar(128)"`UserPhone string `gorm:"unique;type:varchar(32)"`
}func main() {// 連接數據庫var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})if err != nil {fmt.Println("數據庫連接失敗!", err)}err = db.AutoMigrate(&User{})if err != nil {fmt.Println("數據庫表遷移失敗!", err)}
}
程序運行結果:
3.1.2 自定義表名
我們發現定義結構體名稱為 “User” 時會創建 “users” 的表名,但是如果我就希望叫做 “t_user” 應該怎么辦呢?我們可以定義一個名為 TableName
的方法接收器,格式如下:
func (*User) TableName() string {return "t_user"
}
刪除原先的表后再次運行,可以發現此時表名稱已經指定為t_user
了
3.2 新增記錄
我們還可以使用 gorm 提供的 API 進行表記錄的插入,這里我們需要關注** 結構體實例 <=> 表記錄** 之間的映射關系,也就意味著我們可以通過創建一個結構體實例,實現插入一條記錄的效果
3.2.1 單條數據插入
基本語法:db.Create(&結構體實例)
package mainimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm"
)// User 結構體聲明
type User struct {UserId int64 `gorm:"primaryKey;autoIncrement"`UserName string `gorm:"not null;type:varchar(32)"`UserPwd string `gorm:"not null;type:varchar(128)"`UserPhone string `gorm:"unique;type:varchar(32)"`
}func (*User) TableName() string {return "t_user"
}func main() {// 連接數據庫var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})if err != nil {fmt.Println("數據庫連接失敗!", err)}// 插入單條數據var user = User{UserName: "wjj", UserPwd: "123", UserPhone: "111"}db.Create(&user)// 再次打印userfmt.Println(user)
}
數據庫表結果:
程序運行結果:
💡 提示:從中我們還可以發現,插入數據之后,還會將數據庫表中記錄回顯到結構體實例當中!這也是為什么需要傳遞地址的原因!
3.2.2 批量插入數據
當我們需要批量插入多條數據的時候,循環調用 db.Create(&結構體實例)
這個方法效率就太低了!因為數據庫連接會話頻繁創建銷毀耗時比較高,更合適的方法就是進行批量插入
基本語法:db.Create(&結構體實例切片)
,仍舊是 Create 函數,但是參數我們可以傳遞結構體實例切片
package mainimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm"
)// User 結構體聲明
type User struct {UserId int64 `gorm:"primaryKey;autoIncrement"`UserName string `gorm:"not null;type:varchar(32)"`UserPwd string `gorm:"not null;type:varchar(128)"`UserPhone string `gorm:"unique;type:varchar(32)"`
}func (*User) TableName() string {return "t_user"
}func main() {// 連接數據庫var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})// 批量插入多條數據var users = []User{{UserName: "th", UserPwd: "123", UserPhone: "222"},{UserName: "lhf", UserPwd: "123", UserPhone: "333"},{UserName: "zcy", UserPwd: "123", UserPhone: "444"},}db.Create(&users)// 打印結果fmt.Println(users)
}
數據庫表結果:
程序運行結果:
3.3 查詢記錄
3.3.1 查詢所有記錄
基本語法:db.Find(&結構體實例切片)
package mainimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm"
)// User 結構體聲明
type User struct {UserId int64 `gorm:"primaryKey;autoIncrement"`UserName string `gorm:"not null;type:varchar(32)"`UserPwd string `gorm:"not null;type:varchar(128)"`UserPhone string `gorm:"unique;type:varchar(32)"`
}func (*User) TableName() string {return "t_user"
}func main() {// 連接數據庫var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})// 查詢全部記錄var users []Userdb.Find(&users)// 打印結果fmt.Println(users)
}
程序運行結果:
3.3.2 按照條件查詢
我們可以使用 Where 指定查詢條件進行過濾
基本語法:db.Where("user_id > ?", 2).Find()
表示想要查詢 user_id > 2 的所有記錄
package mainimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm"
)// User 結構體聲明
type User struct {UserId int64 `gorm:"primaryKey;autoIncrement"`UserName string `gorm:"not null;type:varchar(32)"`UserPwd string `gorm:"not null;type:varchar(128)"`UserPhone string `gorm:"unique;type:varchar(32)"`
}func (*User) TableName() string {return "t_user"
}func main() {// 連接數據庫var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})// 按照條件查詢var users []Userdb.Where("user_id > ?", 2).Find(&users)// 打印fmt.Println(users)
}
程序運行結果:
3.3.3 查詢單條記錄
查詢單條記錄有以下兩種情況:
- 查詢第一條記錄:
db.First(&結構體實例)
- 查詢最后一條記錄:
db.Last(&結構體實例)
package mainimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm"
)// User 結構體聲明
type User struct {UserId int64 `gorm:"primaryKey;autoIncrement"`UserName string `gorm:"not null;type:varchar(32)"`UserPwd string `gorm:"not null;type:varchar(128)"`UserPhone string `gorm:"unique;type:varchar(32)"`
}func (*User) TableName() string {return "t_user"
}
func main() {// 連接數據庫var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})// 查詢第一條記錄var firstUser Userdb.First(&firstUser)// 查詢最后一條記錄var lastUser Userdb.Last(&lastUser)fmt.Println(firstUser, lastUser)
}
程序運行結果:
3.3.4 查詢記錄總數
基本語法:db.Find(&結構體實例切片).Count(&整型變量)
package mainimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm"
)// User 結構體聲明
type User struct {UserId int64 `gorm:"primaryKey;autoIncrement"`UserName string `gorm:"not null;type:varchar(32)"`UserPwd string `gorm:"not null;type:varchar(128)"`UserPhone string `gorm:"unique;type:varchar(32)"`
}func (*User) TableName() string {return "t_user"
}func main() {// 連接數據庫var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})// 查詢總數var users []Uservar totalSize int64db.Find(&users).Count(&totalSize)fmt.Println("記錄總數:", totalSize)
}
程序運行結果:
3.4 修改記錄
3.4.1 按照默認主鍵修改
基本語法:db.Save(&結構體實例)
會按照結構體實例當中的主鍵字段找到對應數據庫記錄進行修改
package mainimport ("gorm.io/driver/mysql""gorm.io/gorm"
)// User 結構體聲明
type User struct {UserId int64 `gorm:"primaryKey;autoIncrement"`UserName string `gorm:"not null;type:varchar(32)"`UserPwd string `gorm:"not null;type:varchar(128)"`UserPhone string `gorm:"unique;type:varchar(32)"`
}func (*User) TableName() string {return "t_user"
}func main() {// 連接數據庫var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})// 查詢user_id為1的記錄var stu Userdb.Where("user_id = ?", 1).Find(&stu)// 修改stu姓名為wjj1stu.UserName = "wjj1"// 修改(按照主鍵修改)db.Save(&stu)
}
程序運行結果:
3.4.2 修改指定字段
上述按照默認主鍵修改的方式修改了全部字段,如果我們只想修改特定單個字段可以使用以下方式:
基本語法:db.Model(&結構體實例).Where(條件).Update(字段, 修改值)
package mainimport ("gorm.io/driver/mysql""gorm.io/gorm"
)// User 結構體聲明
type User struct {UserId int64 `gorm:"primaryKey;autoIncrement"`UserName string `gorm:"not null;type:varchar(32)"`UserPwd string `gorm:"not null;type:varchar(128)"`UserPhone string `gorm:"unique;type:varchar(32)"`
}func (*User) TableName() string {return "t_user"
}func main() {// 連接數據庫var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})// 修改user_id為1的記錄 user_name為wjjvar stu Userdb.Model(&stu).Where("user_id = ?", 1).Update("user_name", "wjj")
}
程序運行結果:
3.4.3 修改多個字段
我們還可以指定多個字段進行修改
基本語法:db.Model(&結構體實例).Where(條件).updates(修改實例)
,其中修改實例可以是結構體也可以是map對象
package mainimport ("gorm.io/driver/mysql""gorm.io/gorm"
)// User 結構體聲明
type User struct {UserId int64 `gorm:"primaryKey;autoIncrement"`UserName string `gorm:"not null;type:varchar(32)"`UserPwd string `gorm:"not null;type:varchar(128)"`UserPhone string `gorm:"unique;type:varchar(32)"`
}func (*User) TableName() string {return "t_user"
}func main() {// 連接數據庫var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})// 修改user_id為1的記錄 user_name為WJJ, user_pwd為"999"var stu Uservar fields = map[string]interface{}{"user_name": "WJJ", "user_pwd": "999"}db.Model(&stu).Where("user_id = ?", 1).Updates(fields)
}
程序運行結果:
3.5 刪除記錄
3.5.1 按照默認主鍵刪除
基本語法:db.Delete(&結構體實例)
會自動按照主鍵找到表中記錄,然后刪除
package mainimport ("gorm.io/driver/mysql""gorm.io/gorm"
)// User 結構體聲明
type User struct {UserId int64 `gorm:"primaryKey;autoIncrement"`UserName string `gorm:"not null;type:varchar(32)"`UserPwd string `gorm:"not null;type:varchar(128)"`UserPhone string `gorm:"unique;type:varchar(32)"`
}func (*User) TableName() string {return "t_user"
}func main() {// 連接數據庫var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})// 按照默認主鍵刪除var user = User{UserId: 1}db.Delete(&user)
}
程序運行結果:
3.5.2 指定條件刪除
我們想更加精細化的控制刪除條件就需要借助 Where 函數:
基本語法:db.Where(條件).Delete(&結構體實例)
package mainimport ("gorm.io/driver/mysql""gorm.io/gorm"
)// User 結構體聲明
type User struct {UserId int64 `gorm:"primaryKey;autoIncrement"`UserName string `gorm:"not null;type:varchar(32)"`UserPwd string `gorm:"not null;type:varchar(128)"`UserPhone string `gorm:"unique;type:varchar(32)"`
}func (*User) TableName() string {return "t_user"
}func main() {// 連接數據庫var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})// 按照條件刪除db.Where("user_id = ?", 10).Delete(&User{})
}
程序運行結果: