这是我参与「第五届青训营 」伴学笔记创作活动的第 12 天
1. 添加一个实体
1. 通过结构体变量进行添加
1. 添加一个实体
type User struct {
ID uint
Name string
Age uint8
}
// 首先创建一个实体
user := User{"Name": "zhangsan"}
// 然后调用db.Create方法,注意传递的是结构体变量的引用,这样才能获取回填的主键还有其它数据
result = db.Create(&user)
// user.ID可以获取回填的主键
// result.Error获取错误信息
// result.RowsAffected获取影响的行数
// 可以通过Select函数选定需要添加的字段
db.Select("Name", "Age").Create(&user)
// 可以通过Omit函数忽略要添加的字段
db.Omit("ID").Create(&user)
2. 添加多个实体
var users = []User{{"Name": "zhangsan"}, {"Name": "zhangsan1"}, {"Name": "zhangsan2"}}
db.Create(&users)
for _, user := range users {
fmt.Println(user.ID)
}
2. 通过Map进行添加
1. map[string]interface{}添加一个map类对象
// 使用Map的时候需要指定对应的结构体
db.Model(&User{}).Create(map[string]interface{}{
"Name": "wyb",
"Age": 12
})
2. []map[string]interface{}添加多个map类对象
db.Model(&User{}).Create([]map[string]interface{}{
{"Name": "zhangsan", "Age": 12},
{"Name": "zhangsan1", "Age": 13}
})
3. 使用map的注意事项
- 使用map的时候不会触发钩子
- 使用map的时候不会主键回填
2. 添加钩子
1. 钩子的类别主要包括以下几类:
- BeforeSave:在保存之前触发
- BeforeCreate:在创建之前触发
- BeforeUpdate:在更新之前
- BeforeDelete:在删除之前
- After...也是对应的写法,这里就不重复了
- 还有一个
2. 为什么需要钩子
钩子可以在我们执行CRUD之前自动执行,只要有一个钩子方法返回了error(也就是出现了错误),就会停止将来的操作,然后回滚到当前事务状态
3. 钩子的定义
除了函数名要是第一点所说的那几个以外,函数的接受者最好设置为指针,接收者名称根据需要设置,如果钩子里面用不到的话就不需要设置,用到的话就再设置。同时接收的参数必须是*gorm.DB,返回类型必须是err Error类型
4. 这里比较一下BeforeCreate\Save、AfterCreate\Save的执行顺序
假设某个实体类定义了这四个方法,并且执行了插入操作,那么最后这四个钩子的执行顺序就是:
- 保存前
- 创建前
- 创建后
- 保存后
5. 如何跳过钩子
假如说我们给某个实体类定义了钩子但是某次事务并不想触发,那么我们可以用SkipHooks跳过:
db.Session(&gorm.Session{SkipHooks: true}).Create(&user)
3. 关联值自动插入
如果一个结构体内嵌了另外一个结构体,比如说User类型的结构体内嵌了CreditCard结构体,那么在添加User类对象的时候也会在CreditCard中进行添加
4. 可以给字段指定默认值
0,'', false这类的字段不会插入到表中,如果想插入的话可以换成指针变量类型