深圳 网站建设设计,软件开发制作公司,网站 备案,wordpress扫描器GORM 指南 | GORM - The fantastic ORM library for Golang, aims to be developer friendly. 一 对多入门 比如要开发cmdb的系统#xff0c;无论是硬件还是软件。硬件对应的就是对应的哪个开发在用。或者服务对应的是哪个业务模块在使用#xff0c;或者应用谁在使用。那么这…GORM 指南 | GORM - The fantastic ORM library for Golang, aims to be developer friendly. 一 对多入门 比如要开发cmdb的系统无论是硬件还是软件。硬件对应的就是对应的哪个开发在用。或者服务对应的是哪个业务模块在使用或者应用谁在使用。那么这就是一对多的关系。 has many介绍 has many 关联就是创建和另一个模型的一对多关系数据库里面是一对多然后struct里面也是一对多例如 例如每一个用户都拥有多张信用卡这样就是生活中一个简单的一对多关系 在设计表的时候不可能将所有的信息都放在一个表里面那么表就会非常非常的宽。这样字段就会非常的多性能就会受到影响。
在设计的时候这里其实就可以设置为两张表。一个是用户的详情表和信用卡的详情表用户表里面加上卡的id和他做一个关联那么这就是一对多的关系。
当一个数据库存储了很多数据的时候就需要分库分表上面也类似将一张表分为两张表。
creditcar的外键是userid。
package mainimport (gorm.io/driver/mysqlgorm.io/gorm
)type User struct {gorm.Model //默认创建三个时间字段和一个id字段create_at update_at delete_at这样可以知道创建时间/更新时间/删除时间CreditCards []*CreditCard66
}//用户有多张信用卡UserID是外键
type CreditCard struct {gorm.ModelNumber stringUserId int //默认会在CreditCard表中生成User66Id字段作为与user表关联的外键id//默认会在CreditCard表中生成UserID字段作为与User表关联的外键ID
}func main() {dsn : root:7PXjAkY!nlRtcp(192.168.11.128:3306)/test_db?charsetutf8mb4parseTimeTruelocLocaldb, _ : gorm.Open(mysql.Open(dsn66), gorm.Config{})db.AutoMigrate(User{}, CreditCard{})
}
mysql show tables;
-------------------
| Tables_in_test_db |
-------------------
| credit_cards |
| users |
-------------------
2 rows in set (0.00 sec)mysql desc users;
-----------------------------------------------------------------
| Field | Type | Null | Key | Default | Extra |
-----------------------------------------------------------------
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| created_at | datetime(3) | YES | | NULL | |
| updated_at | datetime(3) | YES | | NULL | |
| deleted_at | datetime(3) | YES | MUL | NULL | |
-----------------------------------------------------------------mysql desc credit_cards;
-----------------------------------------------------------------
| Field | Type | Null | Key | Default | Extra |
-----------------------------------------------------------------
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| created_at | datetime(3) | YES | | NULL | |
| updated_at | datetime(3) | YES | | NULL | |
| deleted_at | datetime(3) | YES | MUL | NULL | |
| number | bigint | YES | | NULL | |
| user_id | bigint unsigned | YES | MUL | NULL | |
-----------------------------------------------------------------mysql drop table users;
ERROR 3730 (HY000): Cannot drop table users referenced by a foreign key constraint fk_users_credit_cards on table credit_cards. 二 外键 为了定义一对多关系外键是必须存在的默认外键的名字是所有者类型的名字加上它的主键 (UserId) 。 就像上面的例子为了定义一个属于User 的模型外键就应该为 UserID 。 使用其他的字段名作为外键你可以通过 foreignkey 来定制它例如 : type User struct{gorm.ModelCreditCards []CreditCard gorm:foreignKey:UserRefer
}type CreditCard struct{gorm.ModelNumber stringUserRefer uint
}gorm:foreignKey:UserRefer 可以使用这个字段来去改它的外键。 import (gorm.io/driver/mysqlgorm.io/gorm
)type User struct {gorm.ModelCreditCards []*CreditCard gorm:foreignKey:UserRefer
}type CreditCard struct {gorm.ModelNumber intUserRefer int
}func main() {dsn6 : root:7PXjAkY!nlRtcp(192.168.11.128:3306)/test_db?charsetutf8mb4parseTimeTruelocLocaldb, _ : gorm.Open(mysql.Open(dsn6), gorm.Config{})db.AutoMigrate(User{}, CreditCard{})
}mysql desc users;
-----------------------------------------------------------------
| Field | Type | Null | Key | Default | Extra |
-----------------------------------------------------------------
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| created_at | datetime(3) | YES | | NULL | |
| updated_at | datetime(3) | YES | | NULL | |
| deleted_at | datetime(3) | YES | MUL | NULL | |
-----------------------------------------------------------------mysql desc credit_cards;
-----------------------------------------------------------------
| Field | Type | Null | Key | Default | Extra |
-----------------------------------------------------------------
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| created_at | datetime(3) | YES | | NULL | |
| updated_at | datetime(3) | YES | | NULL | |
| deleted_at | datetime(3) | YES | MUL | NULL | |
| number | bigint | YES | | NULL | |
| user_refer | bigint unsigned | YES | MUL | NULL | |
-----------------------------------------------------------------mysql drop tables users;
ERROR 3730 (HY000): Cannot drop table users referenced by a foreign key constraint fk_users_credit_cards on table credit_cards. 一般不推荐使用这种方式还是推荐使用Userid的方式。 三 外键关联 GORM 通常使用所有者的主键作为外键的值在上面的例子中它就是 User 的 ID 。当你分配信用卡给一个用户GORM 将保存用户 ID 到信用卡表的 UserID 字段中。 你能通过association_foreignkey来改变它。 type User struct {gorm.ModelMemberNumber string
// 默认CreditCard会使用User表的Id作为外键association_foreignkey:MemberNumber
// 指定使用MemberNumber 作为外键关联
CreditCards []CreditCard
gorm:foreignkey:UserMemberNumber;association_foreignkey:MemberNumber
}type CreditCard struct {gorm.ModelNumber stringUserMemberNumber string
}
其实就是creditcard外键UserMemberNumber直接去找user的 MemberNumber。
上面其实也就是改变了外键的默认值默认外键是Userid那么现在变为了MemberNumber。
一般使用默认id的外键就能够覆盖很多场景上面这种只是举例。
package mainimport (gorm.io/driver/mysqlgorm.io/gorm
)type User struct {gorm.ModelMemberNumber stringCreditCards []*CreditCard gorm:foreignKey:UserMemberNumber;association_foreignKey:MemberNumber
}type CreditCard struct {gorm.ModelNumber intUserMemberNumber string
}func main() {dsn6 : root:7PXjAkY!nlRtcp(192.168.11.128:3306)/test_db?charsetutf8mb4parseTimeTruelocLocaldb, _ : gorm.Open(mysql.Open(dsn6), gorm.Config{})db.AutoMigrate(User{}, CreditCard{})
}mysql desc users;
--------------------------------------------------------------------
| Field | Type | Null | Key | Default | Extra |
--------------------------------------------------------------------
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| created_at | datetime(3) | YES | | NULL | |
| updated_at | datetime(3) | YES | | NULL | |
| deleted_at | datetime(3) | YES | MUL | NULL | |
| member_number | longtext | YES | | NULL | |
--------------------------------------------------------------------mysql desc credit_cards;
-------------------------------------------------------------------------
| Field | Type | Null | Key | Default | Extra |
-------------------------------------------------------------------------
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| created_at | datetime(3) | YES | | NULL | |
| updated_at | datetime(3) | YES | | NULL | |
| deleted_at | datetime(3) | YES | MUL | NULL | |
| number | bigint | YES | | NULL | |
| user_member_number | bigint unsigned | YES | MUL | NULL | |
------------------------------------------------------------------------- 四 创建一对多表 1. 表结构定义 /*
constraint:OnUpdate:CASCADE 【当User表更新也会同步给CreditCards】 // 外键约束
OnDelete:SET NULL 【当User中数据被删除时CreditCard关联设置为 NULL不删除记录】
*/type User struct {gorm.ModelUsername string json:username gorm:column:usernameCreditCards []CreditCard gorm:constraint:OnUpdate:CASCADE,OnDelete:SET NULL;
}type CreditCard struct {gorm.ModelNumber stringUserID uint
}func main() {// 0、连接数据库dsn : root:1tcp(127.0.0.1:3306)/test_db?charsetutf8mb4parseTimeTruelocLocaldb, _ : gorm.Open(mysql.Open(dsn), gorm.Config{})// 创建表结构db.AutoMigrate(User{}, CreditCard{})// 1、创建一对多user : User{Username: zhangsan,CreditCards: []CreditCard{{Number: 0001},{Number: 0002},},
}db.Create(user)// 2、为已存在用户添加信用卡u : User{Username: zhangsan}db.First(u)//fmt.Println(u.Username)} 上面如果要查询的话是没有去做关联查询的只能查到user表相关的信息并不能查到creditcard信息。 2. 创建结果说明 我们没有指定 foreignkey 所以会与 UserID 字段自动建立外键关联关系 3. 一对多Association 查找关联 使用 Association 方法, 需要把把 User 查询好, 然后根据 User 定义中指定的 AssociationForeignKey 去查找 CreditCard import (fmtgorm.io/driver/mysqlgorm.io/gorm
)type User struct {gorm.ModelUserName string json:username gorm:column:usernameCreditCards []CreditCard gorm:constraint:OnUpdate:CASCADE,OnDelete:SET NULL;
}type CreditCard struct {gorm.ModelNumber stringUserID int
}func main() {dsn6 : root:7PXjAkY!nlRtcp(192.168.11.128:3306)/test_db?charsetutf8mb4parseTimeTruelocLocaldb, _ : gorm.Open(mysql.Open(dsn6), gorm.Config{})db.AutoMigrate(User{}, CreditCard{})/*u : User{Model: gorm.Model{},UserName: lucas,CreditCards: []*CreditCard{{Number: 0001, UserID: 1},{Number: 0002, UserID: 2},},}db.Create(u)*/// 1、查找 用户名为 lucas 的所有信用卡信息u1 : User{UserName: lucas}// Association必须要先查出User才能关联查询对应的CreditCarddb.First(u1)db.Model(u1).Association(CreditCards).Find(u1.CreditCards)fmt.Println(u1)} 追加 package mainimport (encoding/jsonfmtgorm.io/driver/mysqlgorm.io/gorm
)type User struct {gorm.ModelUserName string json:username gorm:column:usernameCreditCards []CreditCard gorm:constraint:OnUpdate:CASCADE,OnDelete:SET NULL;
}type CreditCard struct {gorm.ModelNumber stringUserID int
}func main() {dsn6 : root:7PXjAkY!nlRtcp(192.168.11.128:3306)/test_db?charsetutf8mb4parseTimeTruelocLocaldb, _ : gorm.Open(mysql.Open(dsn6), gorm.Config{})db.AutoMigrate(User{}, CreditCard{})u : User{Model: gorm.Model{},UserName: lucas,CreditCards: []CreditCard{{Number: 0001, UserID: 0},{Number: 0002, UserID: 1},},}db.Create(u)u1 : User{UserName: lucas}db.First(u1)db.Model(u1).Association(CreditCards).Find(u1.CreditCards)fmt.Println(u1)db.Model(u1).Association(CreditCards).Append([]CreditCard{{Number: 0008, UserID: 1},})fmt.Println(u1)strUser, _ : json.Marshal(u1)fmt.Println(string(strUser))
}{{1 2023-04-16 10:48:54.423 0800 CST 2023-04-16 14:12:45.825 0800 CST {0001-01-01 00:00:00 0000 UTC false}} lucas []}{{1 2023-04-16 10:48:54.423 0800 CST 2023-04-16 14:15:51.44 0800 CST {0001-01-01 00:00:00 0000 UTC false}} lucas [{{17 2023-04-16 14:15:51.4450800 CST 2023-04-16 14:15:51.445 0800 CST {0001-01-01 00:00:00 0000 UTC false}} 0008 1}]}{ID:1,CreatedAt:2023-04-16T10:48:54.42308:00,UpdatedAt:2023-04-16T14:15:51.4408:00,DeletedAt:null,username:lucas,CreditCards:[
{ID:17,CreatedAt:2023-04-16T14:15:51.44508:00,UpdatedAt:2023-04-16T14:15:51.44508:00,DeletedAt:null,Number:0008,UserID:1}]} 4. 一对多Preload 预加载
使用 Preload 方法, 在查询 User 时先去获取 CreditCard 的记录 和上面associate不一样他们两个最大的区别是执行的顺序是不一样的associate是先去获取user再去获取creditcard。
preload是先去获取creditcard再去获取user。
package main
import (
encoding/json
fmt
gorm.io/driver/mysql
gorm.io/gorm
)
/*
constraint:OnUpdate:CASCADE 【当User表更新也会同步给CreditCards】
OnDelete:SET NULL 【当User中数据被删除时CreditCard关联设置为 NULL不删除记录】
*/
type User struct {
gorm.Model
Username string json:username gorm:column:username
CreditCards []CreditCard gorm:constraint:OnUpdate:CASCADE,OnDelete:SET
NULL;
}
type CreditCard struct {
gorm.Model
Number string
UserID uint
}
func main() {
// 0、连接数据库
dsn : root:1tcp(127.0.0.1:3306)/test_db?
charsetutf8mb4parseTimeTruelocLocal
db, _ : gorm.Open(mysql.Open(dsn), gorm.Config{})
// 1、预加载: 查找 user 时预加载相关 CreditCards
//users : User{Username: zhangsan} // 只查找张三用户的信用卡信息
users : []User{}
db.Preload(CreditCards).Find(users)
查询结果[
{
ID:1,
username:zhangsan,
CreditCards:[
{
ID:1,
Number:0001,
UserID:1
},
...
]
}
]