type User struct { ID int64 Username string`gorm:"column:username"` Password string`gorm:"column:password"` CreateTime int64`gorm:"column:createtime"` }
funcGetById(id int64) User { var user User err := DB.Where("id=?", id).First(&user).Error if err != nil { log.Println("get user by id fail : ", err) } return user }
1 2 3 4
funcGetUser(c *gin.Context) { user := dao.GetById(1) c.JSON(200, user) }
type Good struct { Id int//表字段名为:id Name string//表字段名为:name Price float64//表字段名为:price TypeId int//表字段名为:type_id CreateTime int64`gorm:"column:createtime"`//表字段名为:createtime }
如果想要保存 UNIX(毫/纳)秒时间戳,而不是 time,只需简单地将 time.Time 修改为 int 即可。
例子:
1 2 3 4 5 6 7
type User struct { CreatedAt time.Time // 默认创建时间字段, 在创建时,如果该字段值为零值,则使用当前时间填充 UpdatedAt int// 默认更新时间字段, 在创建时该字段值为零值或者在更新时,使用当前时间戳秒数填充 Updated int64`gorm:"autoUpdateTime:nano"`// 自定义字段, 使用时间戳填纳秒数充更新时间 Updated int64`gorm:"autoUpdateTime:milli"`//自定义字段, 使用时间戳毫秒数填充更新时间 Created int64`gorm:"autoCreateTime"`//自定义字段, 使用时间戳秒数填充创建时间 }
可以将它嵌入到您的结构体中,以包含这几个字段,比如
1 2 3 4 5 6 7 8 9 10 11 12
type User struct { gorm.Model Name string } // 等效于 type User struct { ID uint`gorm:"primaryKey"` CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` Name string }
对于正常的结构体字段,你也可以通过标签 embedded 将其嵌入,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
type Author struct { Name string Email string }
type Blog struct { ID int Author Author `gorm:"embedded"` Upvotes int32 } // 等效于 type Blog struct { ID int64 Name string Email string Upvotes int32 }
可以使用标签 embeddedPrefix 来为 db 中的字段名添加前缀,例如:
1 2 3 4 5 6 7 8 9 10 11 12
type Blog struct { ID int Author Author `gorm:"embedded;embeddedPrefix:author_"` Upvotes int32 } // 等效于 type Blog struct { ID int64 AuthorName string AuthorEmail string Upvotes int32 }
5. 数据库连接
GORM 官方支持的数据库类型有: MySQL, PostgreSQL, SQlite, SQL Server
db.Where("id in (?)", []int{1,2,5,6}).Take(&goods)
4.3 select
设置select子句, 指定返回的字段
1 2
var goods Goods DB.Select("id", "title").Find(&goods)
也可以写聚合函数
1 2 3
var total int DB.Model(&Goods{}).Select("count(*) as total").Pluck("total", &total) fmt.Println(total)
4.4 order
排序
1 2
var goods []Goods DB.Order("id desc").Find(&goods)
4.5 分页
通过limit和Offset实现
1 2
var goods []Goods DB.Order("create_time desc").Limit(10).Offset(10).Find(&goods)
4.6 count
返回查询匹配的行数
1 2 3
var total int64 = 0 DB.Model(Goods{}).Count(&total) fmt.Println(total)
4.7 分组
1 2 3 4 5 6 7 8 9 10 11 12
//统计每个商品分类下面有多少个商品 //定一个Result结构体类型,用来保存查询结果 type Result struct { Type int Total int } var results []Result //等价于: SELECT type, count(*) as total FROM `goods` GROUP BY type HAVING (total > 0) db.Model(Goods{}).Select("type, count(*) as total").Group("type").Having("total > 0").Scan(&results)
sql := "SELECT type, count(*) as total FROM `goods` where create_time > ? GROUP BY type HAVING (total > 0)" //因为sql语句使用了一个问号(?)作为绑定参数, 所以需要传递一个绑定参数(Raw第二个参数). //Raw函数支持绑定多个参数 db.Raw(sql, "2022-11-06 00:00:00").Scan(&results) fmt.Println(results)
db.Where("amount > (?)", db.Table("orders").Select("AVG(amount)")).Find(&orders) // SELECT * FROM "orders" WHERE amount > (SELECT AVG(amount) FROM "orders");
from子查询
1 2 3 4 5 6
db.Table("(?) as u", db.Model(&User{}).Select("name", "age")).Where("age = ?", 18).Find(&User{}) // SELECT * FROM (SELECT `name`,`age` FROM `users`) as u WHERE `age` = 18
subQuery1 := db.Model(&User{}).Select("name") subQuery2 := db.Model(&Pet{}).Select("name") db.Table("(?) as u, (?) as p", subQuery1, subQuery2).Find(&User{})
type User struct { ID int64 Username string`gorm:"column:username"` Password string`gorm:"column:password"` CreateTime int64`gorm:"column:createtime"` UserProfile UserProfile }
保存User
1 2 3 4 5 6 7 8 9 10
var user = User{ Username: "ms", Password: "ms", CreateTime: time.Now().UnixMilli(), UserProfile: UserProfile{ Sex: 0, Age: 20, }, } DB.Save(&user)
会产生两条sql,users表和user_profiles表都有数据
这是因为默认的外键是结构体名字+下划线+id,即UserId或者表字段是user_id
如果将user_profiles表中的user_id改为other_id就会失败。
1 2 3 4 5 6 7 8
type User struct { ID int64 Username string`gorm:"column:username"` Password string`gorm:"column:password"` CreateTime int64`gorm:"column:createtime"` UserProfile UserProfile `gorm:"foreignKey:OtherId"` }
只要给UserProfile添加上相应的tag即可。
关联标签
标签
描述
foreignKey
指定当前模型的列作为连接表的外键
references
指定引用表的列名,其将被映射为连接表外键
polymorphic
指定多态类型,比如模型名
polymorphicValue
指定多态值、默认表名
many2many
指定连接表表名
joinForeignKey
指定连接表的外键列名,其将被映射到当前表
joinReferences
指定连接表的外键列名,其将被映射到引用表
constraint
关系约束,例如:OnUpdate、OnDelete
4.1 查询
1 2 3 4
var users []User err := DB.Preload("UserProfile").Find(&users).Error fmt.Println(err) fmt.Println(users)
Preload预加载,直接加载关联关系
也可以使用joins进行加载关联数据:
1 2 3 4
var users []User err := DB.Joins("UserProfile").Find(&users).Error fmt.Println(err) fmt.Println(users)
从sql中能看的出来,使用了left join。
如果不想要User的数据,只想要关联表的数据,可以这么做:
1 2 3 4 5 6
var user User DB.Where("id=?", 25).Take(&user) var userProfile UserProfile err := DB.Model(&user).Association("UserProfile").Find(&userProfile) fmt.Println(err) fmt.Println(userProfile)