gorm学习 | 青训营笔记

70 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 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的注意事项

  1. 使用map的时候不会触发钩子
  2. 使用map的时候不会主键回填

2. 添加钩子

1. 钩子的类别主要包括以下几类:

  1. BeforeSave:在保存之前触发
  2. BeforeCreate:在创建之前触发
  3. BeforeUpdate:在更新之前
  4. BeforeDelete:在删除之前
  5. After...也是对应的写法,这里就不重复了
  6. 还有一个

2. 为什么需要钩子

钩子可以在我们执行CRUD之前自动执行,只要有一个钩子方法返回了error(也就是出现了错误),就会停止将来的操作,然后回滚到当前事务状态

3. 钩子的定义

除了函数名要是第一点所说的那几个以外,函数的接受者最好设置为指针,接收者名称根据需要设置,如果钩子里面用不到的话就不需要设置,用到的话就再设置。同时接收的参数必须是*gorm.DB,返回类型必须是err Error类型

4. 这里比较一下BeforeCreate\Save、AfterCreate\Save的执行顺序

假设某个实体类定义了这四个方法,并且执行了插入操作,那么最后这四个钩子的执行顺序就是:

  1. 保存前
  2. 创建前
  3. 创建后
  4. 保存后

5. 如何跳过钩子

假如说我们给某个实体类定义了钩子但是某次事务并不想触发,那么我们可以用SkipHooks跳过:

db.Session(&gorm.Session{SkipHooks: true}).Create(&user)

3. 关联值自动插入

如果一个结构体内嵌了另外一个结构体,比如说User类型的结构体内嵌了CreditCard结构体,那么在添加User类对象的时候也会在CreditCard中进行添加

4. 可以给字段指定默认值

0,'', false这类的字段不会插入到表中,如果想插入的话可以换成指针变量类型