Belongs To
理解:A属于B------>A依赖B,A要有外键映射到B
belongs to 会与另一个模型建立了一对一的连接。 这种模型的每一个实例都“属于”另一个模型的一个实例。(员工 属于 公司)
例如,您的应用包含 user 和 company,并且每个 user 能且只能被分配给一个 company。下面的类型就表示这种关系。 注意,在 User 对象中,有一个和 Company 一样的 CompanyID。 默认情况下, CompanyID 被隐含地用来在 User 和 Company 之间创建一个外键关系, 因此必须包含在 User 结构体中才能填充 Company 内部结构体。
关系主题是A,是员工User
type User struct { gorm.Model Name string CompanyID int Company Company } type Company struct { gorm.Model Name string }
这里自动迁移AutoMigrate的时候,只迁移User表,也会将Company表创建出来,因为user是依赖company的
这里创建wxf这个用户,会自动在公司表中将公司company1也创建出来
func main() { db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{}) db.AutoMigrate(&User{}) user:=User{ Name: "wxf", Company: Company{ Name: "company1", }, } db.Debug().Create(&user) }
2022/05/15 20:52:31 C:/Users/68725/Desktop/leetcode/main.go:29 [39.169ms] [rows:1] INSERT INTO `companies` (`created_at`,`updated_at`,`deleted_at`,`name`) VALUES ('2022-05-15 20:52:31.668','2022-05-15 20:52:31.668',NULL,'company1') ON DUPLICATE KEY UPDATE `id`=`id` 2022/05/15 20:52:31 C:/Users/68725/Desktop/leetcode/main.go:29 [42.952ms] [rows:1] INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`,`name`,`company_id`) VALUES ('2022-05-15 20:52:31.707','2022-05-15 20:52:31.707',NULL,'wxf',1)
Has One
理解:A有一个B------>A可有可无B,但一个存在B,必定B是属于A的,B依赖A,B要存在一个外键映射到A
has one 与另一个模型建立一对一的关联,但它和一对一关系有些许不同。 这种关联表明一个模型的每个实例都包含或拥有另一个模型的一个实例。
例如,您的应用包含 user 和 credit card 模型,且每个 user 只能有一张 credit card。
关系主体是A,是User
// User 有一张 CreditCard,UserID 是外键 type User struct { gorm.Model CreditCard CreditCard } type CreditCard struct { gorm.Model Number string UserID uint }
这里自动迁移AutoMigrate的时候,只迁移User表,不会自动创建CreditCard 表,因为User表不依赖于CreditCard 表
创建user的时候,会自动将creditcard也创建出来
// User 有一张 CreditCard,UserID 是外键 type User struct { gorm.Model CreditCard CreditCard } type CreditCard struct { gorm.Model Number string UserID uint } func main() { db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{}) db.AutoMigrate(&User{}, &CreditCard{}) user := User{ CreditCard: CreditCard{ Number: "111", }, } db.Debug().Create(&user) }
2022/05/15 21:12:34 C:/Users/68725/Desktop/leetcode/main.go:29 [0.510ms] [rows:1] INSERT INTO `credit_cards` (`created_at`,`updated_at`,`deleted_at`,`number`,`user_id`) VALUES ('2022-05-15 21:12:34.492','2022-05-15 21:12:34.492',NULL,'111',1) ON DUPLICATE KEY UPDATE `user_id`=VALUES(`user_id`) 2022/05/15 21:12:34 C:/Users/68725/Desktop/leetcode/main.go:29 [48.298ms] [rows:1] INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`) VALUES ('2022-05-15 21:12:34.445','2022-05-15 21:12:34.445',NULL)
预加载
预加载:可以知道身上挂着关系的具体结构的信息
在Has One模式中,我们想去查询user的信息,发现user的信息是有了,但是没有creditcard 的信息
func main() { db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{}) db.AutoMigrate(&User{}, &CreditCard{}) var user User db.Debug().First(&user) fmt.Printf("%+v\n", user) }
2022/05/15 21:19:13 C:/Users/68725/Desktop/leetcode/main.go:26 [42.711ms] [rows:1] SELECT * FROM `users` WHERE `users`.`deleted_at` IS NULL ORDER BY `users`.`id` LIMIT 1 {Model:{ID:1 CreatedAt:2022-05-15 21:12:34.445 +0800 CST UpdatedAt:2022-05-15 21:12:34.445 +0800 CST DeletedAt:{Time:0001-01-01 00:00:00 +0000 UTC Valid:false}} CreditCard:{Model:{ID:0 CreatedAt:0001-01-01 00:00:00 +0000 UTC UpdatedAt:0001-01-01 00:00:00 +0000 UTC DeletedAt:{Time:0001-01-01 00:00:00 +0000 UTC Valid:false}} Number: UserID:0}}
所以我们需要使用到预加载,只要我们的结构包含了另一个结构,不论是has one还是belongs to,还是many2many等关系,我们都可以用预加载把关系给带出来。
func main() { db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{}) db.AutoMigrate(&User{}, &CreditCard{}) var user User db.Debug().Preload("CreditCard").First(&user) fmt.Printf("%+v\n", user) }
2022/05/15 21:20:49 C:/Users/68725/Desktop/leetcode/main.go:26 [0.705ms] [rows:1] SELECT * FROM `credit_cards` WHERE `credit_cards`.`user_id` = 1 AND `credit_cards`.`deleted_at` IS NULL 2022/05/15 21:20:49 C:/Users/68725/Desktop/leetcode/main.go:26 [47.026ms] [rows:1] SELECT * FROM `users` WHERE `users`.`deleted_at` IS NULL ORDER BY `users`.`id` LIMIT 1 {Model:{ID:1 CreatedAt:2022-05-15 21:12:34.445 +0800 CST UpdatedAt:2022-05-15 21:12:34.445 +0800 CST DeletedAt:{Time:0001-01-01 00:00:00 +0000 UTC Valid:false}} CreditCard:{Model:{ID:1 CreatedAt:2022-05-15 21:12:34.492 +0800 CST UpdatedAt:2022-05-15 21:12:34.492 +0800 CST DeletedAt:{Time:0001-01-01 00:00:00 +0000 UTC Valid:false}} Number:111 UserID:1}}
关系操作
- 需要先确定关联模型Model,源模型的主键不能为空
- Find 查找
- Append 添加关系
- Delete 删除关系
- Replace 替换关系
- Clear 清楚所有关系
- Count 关联计数
以 has one 为例
确定关联模型
func main() { db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{}) db.AutoMigrate(&User{}, &CreditCard{}) // 开始关联模式 var user User // `user` 是源模型,它的主键不能为空 // 关系的字段名是 `CreditCard` // 如果匹配了上面两个要求,会开始关联模式,否则会返回错误 user.Model.ID=1 db.Model(&user).Association("CreditCard") fmt.Println(db.Model(&user).Association("CreditCard").Error) }
查找关联
查找所有匹配的关联记录
func main() { db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{}) db.AutoMigrate(&User{}, &CreditCard{}) var user User user.Model.ID = 1 var cc CreditCard db.Model(&user).Association("CreditCard").Find(&cc) fmt.Println(cc) }
添加关联
为 many to many、has many 添加新的关联;为 has one, belongs to 替换当前的关联
func main() { db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{}) db.AutoMigrate(&User{}, &CreditCard{}) var user User user.Model.ID = 1 cc2 := CreditCard{ Number: "222", } db.Debug().Model(&user).Association("CreditCard").Append(&cc2) }
2022/05/15 21:41:03 C:/Users/68725/Desktop/leetcode/main.go:32 [0.841ms] [rows:1] INSERT INTO `credit_cards` (`created_at`,`updated_at`,`deleted_at`,`number`,`user_id`) VALUES ('2022-05-15 21:41:03.851','2022-05-15 21:41:03.851',NULL,'222',1) ON DUPLICATE KEY UPDATE `user_id`=VALUES(`user_id`) 2022/05/15 21:41:03 C:/Users/68725/Desktop/leetcode/main.go:32 [54.519ms] [rows:1] UPDATE `users` SET `updated_at`='2022-05-15 21:41:03.8' WHERE `users`.`deleted_at` IS NULL AND `id` = 1 2022/05/15 21:41:03 C:/Users/68725/Desktop/leetcode/main.go:32 [1.544ms] [rows:1] UPDATE `credit_cards` SET `user_id`=NULL WHERE `credit_cards`.`id` <> 2 AND `credit_cards`.`user_id` = 1 AND `credit_cards`.`deleted_at` IS NULL
替换关联
用一个新的关联替换当前的关联
func main() { db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{}) db.AutoMigrate(&User{}, &CreditCard{}) var user User user.Model.ID = 1 cc2 := CreditCard{ Number: "222", } cc3 := CreditCard{ Number: "333", } db.Debug().Model(&user).Association("CreditCard").Replace(&cc3) }
2022/05/15 21:43:00 C:/Users/68725/Desktop/leetcode/main.go:33 [0.528ms] [rows:1] INSERT INTO `credit_cards` (`created_at`,`updated_at`,`deleted_at`,`number`,`user_id`) VALUES ('2022-05-15 21:43:00.089','2022-05-15 21:43:00.089',NULL,'333',1) ON DUPLICATE KEY UPDATE `user_id`=VALUES(`user_id`) 2022/05/15 21:43:00 C:/Users/68725/Desktop/leetcode/main.go:33 [56.931ms] [rows:1] UPDATE `users` SET `updated_at`='2022-05-15 21:43:00.035' WHERE `users`.`deleted_at` IS NULL AND `id` = 1 2022/05/15 21:43:00 C:/Users/68725/Desktop/leetcode/main.go:33 [2.768ms] [rows:1] UPDATE `credit_cards` SET `user_id`=NULL WHERE `credit_cards`.`id` <> 3 AND `credit_cards`.`user_id` = 1 AND `credit_cards`.`deleted_at` IS NULL
删除/清空 关联
删除关联:如果存在,则删除源模型与参数之间的关系,只会删除引用,不会从数据库中删除这些对象。
清空关联:删除源模型与关联之间的所有引用,但不会删除这些关联
func main() { db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{}) db.AutoMigrate(&User{}, &CreditCard{}) var user User user.Model.ID = 1 cc3 := CreditCard{ Number: "333", } db.Debug().Model(&user).Association("CreditCard").Delete(&cc3) db.Debug().Model(&user).Association("CreditCard").Clear() }