建表语句:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(23) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`birthday` timestamp NULL DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
gorm有一个比较不好的默认设置,就是会把结构体名的复数当作数据库的表名,解决方法:实现TableName方法。
type User struct {
ID uint64
Name string
Age int8
Birthday time.Time
CreatedAt time.Time
UpdatedAt time.Time
}
// 去除默认的表名复数,以user作为表名
func (User) TableName() string {
return "user"
}
插入记录:
func Create() {
user := model.User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}
result := Db.Create(&user)
//默认将表的主键赋值回结构体的ID字段
fmt.Println(user.ID)
printLine()
fmt.Println(result.Error)
printLine()
fmt.Println(result.RowsAffected)
}
运行结果:
gorm约定,数据表的列名使用的是 struct 字段名的 蛇形命名,如:
type User struct {
ID uint // 列名是 `id`
Name string // 列名是 `name`
Birthday time.Time // 列名是 `birthday`
CreatedAt time.Time // 列名是 `created_at`
}
我们也可以配置结构体字段与数据库列名的映射关系:
type Animal struct {
AnimalID int64 `gorm:"column:beast_id"` // 将列名设为 `beast_id`
Birthday time.Time `gorm:"column:day_of_the_beast"` // 将列名设为 `day_of_the_beast`
Age int64 `gorm:"column:age_of_the_beast"` // 将列名设为 `age_of_the_beast`
}
只插入部分字段:
func Create2() {
user := model.User{
Name: "空阿道夫",
Birthday: time.Now(),
Age: 22,
}
//birthday字段将被忽略,不会写入到数据库
Db.Select("Name", "Age", "CreatedAt").Create(&user)
}
创建一个记录且一同忽略传递给略去的字段值。
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")
批量插入
func genMockUser(n int) []*model.User {
var res = make([]*model.User, n)
for i := 0; i < n; i++ {
res[i] = &model.User{
Name: "北包包",
Age: int8(i),
Birthday: time.Now(), //一定要赋值,不然gorm会为它赋值为'0000-00-00',mysql会报错
}
}
return res
}
func BatchInset() error {
mockUsers := genMockUser(10)
// 传递切片
tx := Db.Create(&mockUsers)
return tx.Error
}
但是出现了一个问题:Birthday属性是time.Time类型,所以插入时一定要为它赋值,不然会出现这样的错误:
Error 1292: Incorrect datetime value: '0000-00-00' for column 'birthday' at row 1
假如一定就是不想为Birthday字段赋值,有什么办法吗?
方法就是把Birthday类型由time.Time类型转为sql.NullTime类型。
高级批量插入
使用 CreateInBatches 分批创建时,你可以指定每批的数量,例如:
var users = []User{{name: "warson_1"}, ...., {Name: "warson_10000"}}
db.CreateInBatches(users, 100) // 每次批量插入100条记录
Upsert 和 Create With Associations 也支持批量插入
注意 使用
CreateBatchSize选项初始化 GORM 时,所有的创建& 关联INSERT都将遵循该选项
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
CreateBatchSize: 1000,
})