创建记录
user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()} |
我们还可以使用 Create()
创建多项记录:
users := []*User{ |
NOTE 你无法向 ‘create’ 传递结构体,所以你应该传入数据的指针.
用指定的字段创建记录
创建记录并为指定字段赋值。
db.Select("Name", "Age", "CreatedAt").Create(&user) |
创建记录并忽略传递给 ‘Omit’ 的字段值
db.Omit("Name", "Age", "CreatedAt").Create(&user) |
批量插入
要高效地插入大量记录,请将切片传递给Create
方法。 GORM 将生成一条 SQL 来插入所有数据,以返回所有主键值,并触发 Hook
方法。 当这些记录可以被分割成多个批次时,GORM会开启一个事务</0>来处理它们。
var users = []User{{Name: "jinzhu1"}, {Name: "jinzhu2"}, {Name: "jinzhu3"}} |
你可以通过db.CreateInBatches
方法来指定批量插入的批次大小
var users = []User{{Name: "jinzhu_1"}, ...., {Name: "jinzhu_10000"}} |
Upsert 和 Create With Associations同样支持批量插入
注意 使用
CreateBatchSize
选项初始化GORM实例后,此后进行创建& 关联操作时所有的INSERT
行为都会遵循初始化时的配置。
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{ |
创建钩子
GORM允许用户通过实现这些接口 BeforeSave
, BeforeCreate
, AfterSave
, AfterCreate
来自定义钩子。 这些钩子方法会在创建一条记录时被调用,关于钩子的生命周期请参阅Hooks。
func (u *User) BeforeCreate(tx *gorm.DB) (err error) { |
如果你想跳过Hooks
方法,可以使用SkipHooks
会话模式,例子如下
DB.Session(&gorm.Session{SkipHooks: true}).Create(&user) |
根据 Map 创建
GORM支持通过 map[string]interface{}
与 []map[string]interface{}{}
来创建记录。
db.Model(&User{}).Create(map[string]interface{}{ |
注意当使用map来创建时,钩子方法不会执行,关联不会被保存且不会回写主键。
使用 SQL 表达式、Context Valuer 创建记录
GORM允许使用SQL表达式来插入数据,有两种方法可以达成该目的,使用map[string]interface{}
或者 Customized Data Types, 示例如下:
// Create from map |
高级选项
关联创建
创建关联数据时,如果关联值非零,这些关联会被upsert,并且它们的Hooks
方法也会被调用。
type CreditCard struct { |
你可以通过Select
, Omit
方法来跳过关联更新,示例如下:
db.Omit("CreditCard").Create(&user) |
默认值
你可以通过结构体Tag default
来定义字段的默认值,示例如下:
type User struct { |
这些默认值会被当作结构体字段的零值插入到数据库中
注意,当结构体的字段默认值是零值的时候比如
0
,''
,false
,这些字段值将不会被保存到数据库中,你可以使用指针类型或者Scanner/Valuer来避免这种情况。
type User struct { |
注意,若要让字段在数据库中拥有默认值则必须使用
default
Tag来为结构体字段设置默认值。如果想要在数据库迁移的时候跳过默认值,可以使用default:(-)
,示例如下:
type User struct { |
注意 SQLite 不支持批量插入的时候使用默认值。 前往 SQLite Insert stmt了解。 下面是一个使用案例:
type Pet struct {
Name string `gorm:"default:cat"`
}
// 在SqlLite中,这是不允许的, 所以GORM会通过构建错误的SQL来返回错误:
// INSERT INTO `pets` (`name`) VALUES ("dog"),(DEFAULT) RETURNING `name`
db.Create(&[]Pet{{Name: "dog"}, {}})一个可行的替代方案是通过钩子方法来设置默认字段
func (p *Pet) BeforeCreate(tx *gorm.DB) (err error) {
if p.Name == "" {
p.Name = "cat"
}
}你可以在issues#6335了解到更多有关信息。
当使用virtual/generated value时,你可能需要禁用它的创建/更新权限,前往Field-Level Permission了解字段权限。
Upsert 及冲突
GORM为不同数据库提供了对Upsert的兼容性支持。
import "gorm.io/gorm/clause" |
前往Advanced Query了解有关FirstOrInit
, FirstOrCreate
的信息。
查看 Raw SQL and SQL Builder获取详情