網(wǎng)站首頁(yè) 編程語言 正文
1.gorm介紹
1.1介紹
全功能 ORM 關(guān)聯(lián) (Has One,Has Many,Belongs To,Many To Many,多態(tài),單表繼承) Create,Save,Update,Delete,F(xiàn)ind 中鉤子方法 支持 Preload、Joins 的預(yù)加載 事務(wù),嵌套事務(wù),Save Point,Rollback To Saved Point Context,預(yù)編譯模式,DryRun 模式 批量插入,F(xiàn)indInBatches,F(xiàn)ind/Create with Map,使用 SQL 表達(dá)式、Context Valuer 進(jìn)行 CRUD SQL 構(gòu)建器,Upsert,數(shù)據(jù)庫(kù)鎖,Optimizer/Index/Comment Hint,命名參數(shù),子查詢 復(fù)合主鍵,索引,約束 Auto Migration 自定義 Logger 靈活的可擴(kuò)展插件 API:Database Resolver(多數(shù)據(jù)庫(kù),讀寫分離)、Prometheus… 每個(gè)特性都經(jīng)過了測(cè)試的重重考驗(yàn) 開發(fā)者友好
1.2安裝
go get -u gorm.io/gorm go get -u gorm.io/driver/sqlite
2.使用
2.1創(chuàng)建表
package main import ( "fmt" "gorm.io/driver/mysql" "gorm.io/gorm" ) //模型結(jié)構(gòu) type Student struct { Id int Name string Age int } type User struct { gorm.Model Name string `gorm:"type:varchar(20);not null"` Telephone string `gorm:"varchar(110;not null;unique"` Password string `gorm:"size:255;not null"` } func main() { //使用dsn連接到數(shù)據(jù)庫(kù),grom自帶的數(shù)據(jù)庫(kù)池 //賬號(hào):密碼@連接方式(ip地址:端口號(hào))/數(shù)據(jù)庫(kù)?語言方式,時(shí)區(qū)(未設(shè)置時(shí)區(qū)的話采用8小時(shí)制度) dsn := "root:mysql@tcp(127.0.0.1:3306)/gotest?charset=utf8mb4&parseTime=True&loc=Local" conn, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) //使用mysq連接數(shù)據(jù)庫(kù),第二個(gè)參數(shù)可以增加更多的配置(可有可無) if err != nil { fmt.Println(err) } conn.AutoMigrate(&Student{}) //創(chuàng)建表?判斷是否表結(jié)構(gòu)存在 } //多表創(chuàng)建 db.AutoMigrate(&Company{}, &Worker{})
2.2.添加數(shù)據(jù)
stu := &Student{ Id: 3, Name: "li333", Age: 30, } res := conn.Create(stu) //向數(shù)據(jù)庫(kù)中插入數(shù)據(jù) ,它的返回值只有一個(gè)類型,沒有error類型 //注:如果上面寫成stu := Student{...},則這里寫成Create(&stu) if res.Error != nil { //判斷是否插入數(shù)據(jù)出錯(cuò) fmt.Println(res.Error) }
2.3.查詢數(shù)據(jù)
var student Student //查詢First查詢一條 conn.First(&student) fmt.Println(student) fmt.Println(student.Id) //條件查詢 res := conn.First(&student, "name=? and id=?", "yang", 1) fmt.Println(res) //查詢所有 Find var stu []Student conn.Table("students").Find(&stu) for _, v := range stu { fmt.Println(v.Name) } // IN var students []Student conn.Table("students").Where("name IN ?", []string{"abc", "bili"}).Find(&students) fmt.Println(students) // LIKE db.Where("name LIKE ?", "%jin%").Find(&users) // AND db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users) // Time db.Where("updated_at > ?", time.Date(2022,05,20,0,0,0,0,&time.Location{})).Find(&users) // BETWEEN db.Where("created_at BETWEEN ? AND ?", time.Date(2022,05,20,0,0,0,0,&time.Location{}), time.Now()).Find(&users)
2.4更新數(shù)據(jù)
//更新數(shù)據(jù) conn.Table("students").Where("id=?", 1).Update("name", "ttt") conn.Table("students").Where("id=?", 2).Updates(&Student{Name: "bili", Age: 10}) //按主鍵更新,傳入結(jié)構(gòu)體對(duì)象,根據(jù)對(duì)應(yīng)主鍵更新相應(yīng)內(nèi)容 dbConn.Table("user").Save(&user1)
2.5刪除數(shù)據(jù)
conn.Table("students").Where("id=?", 1).Delete(&Student{})
2.6執(zhí)行原生sql
conn.Raw("select * from students where id=?", 3).Scan(&student) fmt.Println(student) db.Exec("DROP TABLE users") db.Exec("UPDATE orders SET shipped_at=? WHERE id IN ?", time.Now(), []int64{1,2,3})
3.一對(duì)一
3.1創(chuàng)建表
package main import ( "fmt" "gorm.io/driver/mysql" "gorm.io/gorm" ) type User struct { gorm.Model CreditCard CreditCard Name string } type CreditCard struct { gorm.Model Number string UserID uint } func main() { //使用dsn連接到數(shù)據(jù)庫(kù),grom自帶的數(shù)據(jù)庫(kù)池 //賬號(hào):密碼@連接方式(ip地址:端口號(hào))/數(shù)據(jù)庫(kù)?語言方式,時(shí)區(qū)(未設(shè)置時(shí)區(qū)的話采用8小時(shí)制度) dsn := "root:mysql@tcp(127.0.0.1:3306)/crow?charset=utf8mb4&parseTime=True&loc=Local" conn, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) //使用mysq連接數(shù)據(jù)庫(kù),第二個(gè)參數(shù)可以增加更多的配置(可有可無) if err != nil { fmt.Println(err) } conn.AutoMigrate(&User{}) conn.AutoMigrate(&CreditCard{}) //創(chuàng)建表?判斷是否表結(jié)構(gòu)存在 user := &User{ Name: "李四", } conn.Create(user) card := &CreditCard{ Number: "123", UserID: 1, } conn.Create(card) }
3.2多態(tài)關(guān)聯(lián)
//多態(tài)關(guān)聯(lián) //GORM 為 has one 和 has many 提供了多態(tài)關(guān)聯(lián)支持,它會(huì)將擁有者實(shí)體的表名、主鍵值都保存到多態(tài)類型的字段中。 type Cat struct { ID int Name string Toy Toy `gorm:"polymorphic:Owner;"` } type Dog struct { ID int Name string Toy Toy `gorm:"polymorphic:Owner;"` } type Toy struct { ID int Name string OwnerID int OwnerType string } db.Create(&Dog{Name: "dog1", Toy: Toy{Name: "toy1"}}) // INSERT INTO `dogs` (`name`) VALUES ("dog1") // INSERT INTO `toys` (`name`,`owner_id`,`owner_type`) VALUES ("toy1","1","dogs")
3.3外鍵約束
你可以通過為標(biāo)簽 constraint
配置 OnUpdate
、OnDelete
實(shí)現(xiàn)外鍵約束,在使用 GORM 進(jìn)行遷移時(shí)它會(huì)被創(chuàng)建,例如:
type User struct { gorm.Model Name string CompanyID int Company Company `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` } type Company struct { ID int Name string }
4.一對(duì)多
Has Many
has many 與另一個(gè)模型建立了一對(duì)多的連接。 不同于 has one,擁有者可以有零或多個(gè)關(guān)聯(lián)模型。
例如,您的應(yīng)用包含 user 和 credit card 模型,且每個(gè) user 可以有多張 credit card。
// User 有多張 CreditCard,UserID 是外鍵 type User struct { gorm.Model CreditCards []CreditCard } type CreditCard struct { gorm.Model Number string UserID uint }
package main import ( "fmt" "gorm.io/driver/mysql" "gorm.io/gorm" ) type User struct { gorm.Model MemberNumber string `gorm:"varchar(110;not null;unique"` CreditCards []CreditCard `gorm:"foreignKey:UserNumber;references:MemberNumber"` Name string } type CreditCard struct { gorm.Model Number string UserNumber string `gorm:"varchar(110;not null;unique"` } func main() { //使用dsn連接到數(shù)據(jù)庫(kù),grom自帶的數(shù)據(jù)庫(kù)池 //賬號(hào):密碼@連接方式(ip地址:端口號(hào))/數(shù)據(jù)庫(kù)?語言方式,時(shí)區(qū)(未設(shè)置時(shí)區(qū)的話采用8小時(shí)制度) dsn := "root:mysql@tcp(127.0.0.1:3306)/crow?charset=utf8mb4&parseTime=True&loc=Local" conn, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) //使用mysq連接數(shù)據(jù)庫(kù),第二個(gè)參數(shù)可以增加更多的配置(可有可無) if err != nil { fmt.Println(err) } conn.AutoMigrate(&User{}, &CreditCard{}) user := User{ Name: "ttt3", MemberNumber: "1003", } conn.Create(&user) card := CreditCard{ Number: "111", UserNumber: user.MemberNumber, } conn.Create(&card) }
5.多對(duì)多
Many To Many
Many to Many 會(huì)在兩個(gè) model 中添加一張連接表。
例如,您的應(yīng)用包含了 user 和 language,且一個(gè) user 可以說多種 language,多個(gè) user 也可以說一種 language。
// User 擁有并屬于多種 language,`user_languages` 是連接表 type User struct { gorm.Model Languages []Language `gorm:"many2many:user_languages;"` } type Language struct { gorm.Model Name string }
當(dāng)使用 GORM 的 AutoMigrate
為 User
創(chuàng)建表時(shí),GORM 會(huì)自動(dòng)創(chuàng)建連接表
反向引用
// User 擁有并屬于多種 language,`user_languages` 是連接表 type User struct { gorm.Model Languages []*Language `gorm:"many2many:user_languages;"` } type Language struct { gorm.Model Name string Users []*User `gorm:"many2many:user_languages;"` }
重寫外鍵
對(duì)于 many2many
關(guān)系,連接表會(huì)同時(shí)擁有兩個(gè)模型的外鍵,例如:
type User struct { gorm.Model Languages []Language `gorm:"many2many:user_languages;"` } type Language struct { gorm.Model Name string } // Join Table: user_languages // foreign key: user_id, reference: users.id // foreign key: language_id, reference: languages.id
若要重寫它們,可以使用標(biāo)簽 foreignKey
、reference
、joinforeignKey
、joinReferences
。當(dāng)然,您不需要使用全部的標(biāo)簽,你可以僅使用其中的一個(gè)重寫部分的外鍵、引用。
type User struct { gorm.Model Profiles []Profile `gorm:"many2many:user_profiles;foreignKey:Refer;joinForeignKey:UserReferID;References:UserRefer;JoinReferences:UserRefer"` Refer uint } type Profile struct { gorm.Model Name string UserRefer uint } // 會(huì)創(chuàng)建連接表:user_profiles // foreign key: user_refer_id, reference: users.refer // foreign key: profile_refer, reference: profiles.user_refer
自引用 Many2Many
自引用 many2many 關(guān)系
type User struct { gorm.Model Friends []*User `gorm:"many2many:user_friends"` } // 會(huì)創(chuàng)建連接表:user_friends // foreign key: user_id, reference: users.id // foreign key: friend_id, reference: users.id
6.獲取多表數(shù)據(jù)
預(yù)加載
GORM 允許在 Preload
的其它 SQL 中直接加載關(guān)系,例如:
type User struct { gorm.Model Username string Orders []Order } type Order struct { gorm.Model UserID uint Price float64 } // 查找 user 時(shí)預(yù)加載相關(guān) Order db.Preload("Orders").Find(&users) // SELECT * FROM users; // SELECT * FROM orders WHERE user_id IN (1,2,3,4); db.Preload("Orders").Preload("Profile").Preload("Role").Find(&users) // SELECT * FROM users; // SELECT * FROM orders WHERE user_id IN (1,2,3,4); // has many // SELECT * FROM profiles WHERE user_id IN (1,2,3,4); // has one // SELECT * FROM roles WHERE id IN (4,5,6); // belongs to
Joins 預(yù)加載
Preload
在一個(gè)單獨(dú)查詢中加載關(guān)聯(lián)數(shù)據(jù)。而 Join Preload
會(huì)使用 inner join 加載關(guān)聯(lián)數(shù)據(jù),例如:
db.Joins("Company").Joins("Manager").Joins("Account").First(&user, 1) db.Joins("Company").Joins("Manager").Joins("Account").First(&user, "users.name = ?", "jinzhu") db.Joins("Company").Joins("Manager").Joins("Account").Find(&users, "users.id IN ?", []int{1,2,3,4,5})
注意
Join Preload
適用于一對(duì)一的關(guān)系,例如:has one
,belongs to
預(yù)加載全部
與創(chuàng)建、更新時(shí)使用 Select
類似,clause.Associations
也可以和 Preload
一起使用,它可以用來 預(yù)加載
全部關(guān)聯(lián),例如:
type User struct { gorm.Model Name string CompanyID uint Company Company Role Role } db.Preload(clause.Associations).Find(&users)
帶條件的預(yù)加載
GORM 允許帶條件的 Preload 關(guān)聯(lián),類似于內(nèi)聯(lián)條件
// 帶條件的預(yù)加載 Order db.Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users) // SELECT * FROM users; // SELECT * FROM orders WHERE user_id IN (1,2,3,4) AND state NOT IN ('cancelled'); db.Where("state = ?", "active").Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users) // SELECT * FROM users WHERE state = 'active'; // SELECT * FROM orders WHERE user_id IN (1,2) AND state NOT IN ('cancelled');
自定義預(yù)加載 SQL
您可以通過 func(db *gorm.DB) *gorm.DB
實(shí)現(xiàn)自定義預(yù)加載 SQL,例如:
db.Preload("Orders", func(db *gorm.DB) *gorm.DB { return db.Order("orders.amount DESC") }).Find(&users) // SELECT * FROM users; // SELECT * FROM orders WHERE user_id IN (1,2,3,4) order by orders.amount DESC;
嵌套預(yù)加載
GORM 支持嵌套預(yù)加載,例如:
db.Preload("Orders.OrderItems.Product").Preload("CreditCard").Find(&users) // 自定義預(yù)加載 `Orders` 的條件 // 這樣,GORM 就不會(huì)加載不匹配的 order 記錄 db.Preload("Orders", "state = ?", "paid").Preload("Orders.OrderItems").Find(&users)
原文鏈接:https://blog.csdn.net/CADN_F/article/details/128446025
相關(guān)推薦
- 2022-05-17 springboot打包為jar
- 2023-01-09 Spark處理trick總結(jié)分析_相關(guān)技巧
- 2022-09-27 詳解Django中CSRF和CORS的區(qū)別_python
- 2022-02-14 centos7系統(tǒng)部署k8s集群詳細(xì)介紹_Linux
- 2022-06-01 python中的mock接口開發(fā)示例詳解_python
- 2023-01-31 python中的%?是什么意思,起到什么作用呢_python
- 2022-05-26 詳解redis腳本命令執(zhí)行問題(redis.call)_Redis
- 2022-06-25 Gitlab-runner+Docker實(shí)現(xiàn)自動(dòng)部署SpringBoot項(xiàng)目_docker
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支