创建记录

user := User{Name: " Jinzhu " , Age: 18 , Birthday: time.Now()}

result := db.Create(&user) // 将数据指针传递给 Create

user.ID              // 返回插入数据的主键
result.Error         // 返回错误
result.RowsAffected // 返回插入记录数

使用选定字段创建记录

db.Select( "Name" , "Age" , "CreatedAt" ).Create(&user) 
// INSERT INTO `users` (`name`,`age`,`created_at`) VALUES ("jinzhu", 18, " 2020-07-04 11:05:21.775")

创建记录并忽略传递给 omit 的字段值。

db.Omit( "Name" , "Age" , "CreatedAt" ).Create(&user) 
// INSERT INTO `users` (`birthday`,`updated_at`) VALUES ("2020-01-01 00:00:00.000 ", "2020-07-04 11:05:21.775")

批量插入

要有效地插入大量记录,请将切片传递给该Create方法。GORM 将生成一条 SQL 语句来插入所有数据并回填主键值,也会调用钩子方法。

var users = []User{{Name: "jinzhu1" }, {Name: "jinzhu2" }, {Name: "jinzhu3" }} 
db.Create(&users)

for _, user := range users { 
  user.ID // 1,2,3
 }

您可以在创建时指定批量大小CreateInBatches,例如:

var users = []User{{Name: "jinzhu_1" }, ...., {Name: "jinzhu_10000" }}

// 批量大小 100
 db.CreateInBatches(users, 100 )
使用 UpsertCreate With Associations时也支持批量插入
注意使用 CreateBatchSize选项初始化 GORM, INSERT在创建记录和关联时都将遵循此选项
db, err := gorm.Open(sqlite.Open( "gorm.db" ), &gorm.Config{ 
  CreateBatchSize: 1000 , 
})

db := db.Session(&gorm.Session{CreateBatchSize: 1000 })

users = [ 5000 ]User{{Name: "jinzhu" , Pets: []Pet{pet1, pet2, pet3}}...}

db.Create(&users) 
// INSERT INTO users xxx (5 batches) 
// INSERT INTO pets xxx (15 batches)

创建钩子

GORM 允许为 BeforeSaveBeforeCreateAfterSave、实现用户定义的钩子 AfterCreate。这些钩子方法将在创建记录时调用,有关生命周期的详细信息,请参阅 钩子
 
func  (u *User)  BeforeCreate (tx *gorm.DB)  (err error) {
  u.UUID = uuid.New()

  if u.Role == "admin" { return errors.New( "invalid role" )   } return }

如果要跳过Hooks方法,可以使用SkipHooks会话模式,例如:

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

DB.Session(&gorm.Session{SkipHooks: true }).Create(&users)

DB.Session(&gorm.Session{SkipHooks: true }).CreateInBatches(users, 100 )

从地图创建

GORM 支持从 map[string]interface{}和创建 []map[string]interface{}{},例如:
db.Model(&User{}).Create( map [ string ] interface {}{ "Name" : "jinzhu" , "Age" : 18 , })
 

// 从 `[]map[string]interface{}{}`
 db.Model(&User{}).Create([] map [ string ] interface {}{ 
  { "Name" : "jinzhu_1" , "Age" : 18 }, 
  { "姓名" : "jinzhu_2" , "Age" : 20 }, 
})

从 SQL 表达式/上下文赋值器创建

GORM 允许使用 SQL 表达式插入数据,有两种方法可以实现这一目标, create frommap[string]interface{}Customized Data Types,例如:
// 从地图创建
db.Model(User{}).Create( map [ string ] interface {}{ "Name" : "jinzhu" , "Location" : clause.Expr{SQL: "ST_PointFromText(?)" , Vars : [] interface {}{ "POINT(100 100)" }}, }) // INSERT INTO `users` (`name`,`location`) VALUES ("jinzhu",ST_PointFromText("POINT(100 100)" ));

//从定制数据类型创建
type Location struct {
  X, Y int
}

// Scan 实现了 sql.Scanner interface 
func  (loc *Location)  Scan (v interface {})  error { // 从数据库驱动程序扫描一个值到 struct }
  
func  (loc Location)  GormDataType ()  string { return "geometry" }
   
func  (loc Location)  GormValue (ctx context.Context, db *gorm.DB) clause.Expr { return clause.Expr{    SQL:   "ST_PointFromText(?)" ,    Vars: [] interface {}{fmt.Sprintf( "POINT(%d %d)" , loc.X, loc.Y)},  }}
  
type User struct {
   Name     string
  Location Location
}

db.Create(&User{ 
  Name:      "jinzhu" , 
  Location: Location{X: 100 , Y: 100 }, 
}) 
// INSERT INTO `users` (`name`,`location`) VALUES ("jinzhu",ST_PointFromText (“点(100 100)”))

先进的

用关联创建

当创建一些带有关联的数据时,如果它的关联值不是零值,这些关联将被更新,并且它的Hooks方法将被调用。

type CreditCard struct { 
  gorm.Model 
  Number    string
   UserID    uint
 }

type User struct { 
  gorm.Model 
  Name        string
   CreditCard CreditCard 
}

db.Create(用户{
  Name       :“jinzhu”,
  CreditCard :CreditCard{Number:“411111111111” } 
})
// INSERT INTO`users` ... 
// INSERT INTO`credit_cards` ...

您可以跳过保存与Select, 的关联Omit,例如:

db.Omit( "CreditCard" ).Create(&user)

// 跳过所有关联
db.Omit(clause.Associations).Create(&user)

默认值

您可以为带有 tag 的字段定义默认值default,例如:

type User struct { 
  ID    int64
   Name string  `gorm:"default:galeone"`
   Age   int64   `gorm:"default:18"`
 }
然后在插入到数据库的零值字段时将使用默认值
注意任何像0'',一样的零值false都不会被保存到那些定义了默认值的字段的数据库中,您可能希望使用指针类型或扫描器/值器来避免这种情况,例如:
type User struct { 
  gorm.Model 
  Name string
   Age * int            `gorm:"default:18"`
   Active sql.NullBool `gorm:"default:true"`
 }

注意您必须为default数据库中具有默认值或虚拟/生成值的字段设置标签,如果您想在迁移时跳过默认值定义,您可以使用default:(-),例如:

type User struct { 
  ID         string  `gorm:"default:uuid_generate_v3()"`  // db func
   FirstName string
   LastName   string
   Age        uint8
   FullName   string  `gorm:"->;type:GENERATED ALWAYS AS (concat(firstname,' ',lastname ));默认值:(-);"`
 }
使用虚拟/生成值时,您可能需要禁用其创建/更新权限,请查看字段级权限
GORM 为不同的数据库提供兼容的 Upsert 支持
导入 “gorm.io/gorm/clause”

// 对冲突不做任何处理
db.Clauses(clause.OnConflict{DoNothing: true }).Create(&user)

// 在 `id` 冲突时将列更新为默认值
db.Clauses(clause.OnConflict{ 
  Columns: []clause.Column{{Name: "id" }}, 
  DoUpdates: clause.Assignments( map [ string ] interface {} { "role" : "user" }), 
}).Create(&users) 
// MERGE INTO "users" USING *** WHEN NOT MATCHED THEN INSERT *** WHEN MATCHED THEN UPDATE SET ***; SQL Server 
// INSERT INTO `users` *** ON DUPLICATE KEY UPDATE ***; MySQL

// 使用 SQL 表达式
db.Clauses(clause.OnConflict{ 
  Columns: []clause.Column{{Name: "id" }}, 
  DoUpdates: clause.Assignments( map [ string ] interface {}{ "count" : gorm. Expr( "GREATEST(count, VALUES(count))" )}), 
}).Create(&users) 
// INSERT INTO `users` *** ON DUPLICATE KEY UPDATE `count`=GREATEST(count, VALUES(count) );

// 在 `id` 冲突时将列更新为新值
db.Clauses(clause.OnConflict{ 
  Columns: []clause.Column{{Name: "id" }}, 
  DoUpdates: clause.AssignmentColumns([] string { "name" , "age" }), 
}).Create(&users) 
// 合并到 "users" 使用 *** WHEN NOT MATCHED THEN INSERT *** WHEN MATCHED THEN UPDATE SET "name"="excluded"."name"; SQL Server 
// INSERT INTO "users" *** ON CONFLICT ("id") DO UPDATE SET "name"="excluded"."name", "age"="excluded"."age"; PostgreSQL // INSERT INTO `users` *** ON DUPLICATE KEY UPDATE `name`=VALUES(name), `年龄=值(年龄); MySQL


// 将除主键之外的所有列更新为冲突时的新值
db.Clauses(clause.OnConflict{ 
  UpdateAll: true , 
}).Create(&users) 
// INSERT INTO "users" *** ON CONFLICT ("id" ) DO UPDATE SET "name"="excluded"."name", "age"="excluded"."age", ...;

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐