这是我参与「第五届青训营 」伴学笔记创作活动的第8天。
上次讲了数据库安装和gorm连接数据库的方法,还使用了一个比较方便的mysql可视化管理工具——navicat。这次主要是接着上次的内容介绍gorm对数据库的操作方法。
一、定义连接
上篇文章我们已经简单使用了db.create插入了一个数据,完整代码如下。
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primarykey"`
Name string `gorm:"column:name"`
Age uint `gorm:"column:age"`
}
func (u User) TableName() string {
return "usertable"
}
func main() {
// 用户名:密码@tcp(ip:port)/数据库?charset=utf8 &parseTime=True&loc=Local
dsn := "root:160888@tcp(127.0.0.1:3306)/gorm?charset=utf8&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Println(err)
fmt.Println("failed to connect database")
}
user := User{Name:"test" ,Age: 20 ,ID: 1}
result := db.Create(&users)
fmt.Println(result.Error)
fmt.Println(user.ID)
这里还是要注意修改dsn中的参数”user:password”和”dbname”请替换为图中自己连接时输入的用户名密码以及数据库名称。比如你的用户名是root,密码是1234,数据库名称是前面设置的gorm(不是下图的连接名称test,也不是表名users),你的dsn设置为 "user:password@tcp(127.0.0.1:3306)/gorm?charset=utf8&parseTime=True&loc=Local"。
以下是介绍各部分代码的定义方式。
定义一个结构体User,其中column后面对应表格名称,primarykey指代主键,以下是代码和表信息。
type User struct {
ID uint `gorm:"primarykey"`
Name string `gorm:"column:name"`
Age uint `gorm:"column:age"`
}
这里可以用一个比较方便的方法去匹配数据库中的表名,不需要匹配蛇形复数。定义一个结构体方法TableName,return的string类型就是匹配数据库的表名称,比如说这里表名是”usertable”,这样在匹配user结构体时会去搜
func (u User) TableName() string {
return "usertable"
}
二、插入操作
插入一条数据,定义一个User结构体变量。这里我不知道为什么,我不能像课程视频那样缺省主键ID 输入。其中db.Create放入结构体对象的指针。
user := User{Name: "test", Age: 20, ID: 2}
result := db.Create(&user)
当然,db.Create可以放入结构体切片插入数据表。
users := []*User{{Name:"zhao" ,Age: 20 ,ID: 4},{Name:"li" ,Age: 20 ,ID: 5},{Name:"qian" ,Age: 20 ,ID: 6}}
result := db.Create(&users)
直接通过Model插入自定义User对象
result := db.Model(&User{}).Create(map[string]interface{}{
"Name": "jin", "Age": 18, "id": 9})
result := db.Model(&User{}).Create([]map[string]interface{}{
{"Name": "li", "Age": 18, "id": 9},
{"Name": "zhao", "Age": 20, "id": 9},
})
三、查询操作
查询数据表中第一条记录。这里查询对象如果为空会报错,
user := User{}
db.First(&user)//第一条记录
db.Last(&user)//最后一条记录
带条件使用First查询,返回Name结果为li的查询。
user := User{}
db.First(&user, "Name = ?", "li")
这里数据库语句相当于”SELECT * FROM usertable WHERE name = ‘li’”,不过只会返回第一条记录。
当我们需要返回多条记录时,我们可以使用Find。这里也是推荐使用Find去代替First
users := []*User{}
db.Where("Name LiKE ?", "%%e%").Find(&users)
for _, user := range users{
fmt.Println(user.Name)
}
这里数据库语句相当于”SELECT * FROM usertable WHERE name LIKE ‘%e%’”,会把所有Name列中带有字符e的结果返回给切片users。查询信息Where中第一个参数表示查询语句,第二个参数匹配查询中的?。这里由于%e有特殊含义,需要用%%表示%。
使用两个以上条件查询。
db.Where("Name LiKE ? AND Age = ?", "%%e%", 20).Find(&users)
这里数据库语句相当于”SELECT * FROM usertable WHERE name LIKE ‘%e%’ AND Age = 20”,查询语句每多一个问号,就要在Where里面加一个参数匹配问号。
当然也可以直接往Where里面放入结构体参数,直接匹配与该结构体相同的参数
db.Where(User{Name: "test",Age:20}).Find(&users)
这里数据库语句相当于”SELECT * FROM usertable WHERE name = ‘test’ AND age = 20”。
这里我们可以使用统计和的查询方式,这里我们统计name名字相同情况情况下age年龄之和。
首先定义一个新的结构体,存储统计之后的数据表。这里C存储的是age累加之和,也就是SELECT语句里带有SUM(age) as c
type NewUser struct{
Name string `gorm:"column:name"`
C int64 `gorm:"column:c"`
}
查询代码
users := []*NewUser{}
db.Table("usertable").Select("name, SUM(age) as c").Group("name").Find(&users)
for _, user := range users{
fmt.Println(user.Name,user.C)
}
查询语句”SELECT name,SUM(age) as c FROM usertable GROUP BY name”。其中Select方法跟随原句子中SELECT后面的选择,Table跟随FROM后面选择的表名,Group跟随GROUP BY的列名,最后将结果返回给users。
最后一个是有关join的用法,由于我没有创建多表,这里我直接复制官方的使用案例
结构体定义
type result struct {
Name string
Email string
}
代码
db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Scan(&results)
这里官方给出的语句应该是”SELECT users.name,emails.email FROM users left join emails on emails.user_id = users.id”,将users和emails表中id相同的记录连接起来,并保留其中的name和email信息。这里查询用的是Scan,而不是find。
四、更新操作
这里我只介绍两个比较简单的更新操作
db.Model(&User{}).Where("name = ?", "li").Update("age", "30")
这里表示”UPDATE usertable SET age=30 WHERE name=’li’”,会把名字为li的年龄修改为30岁,其中Model为并行条件(可以不用加上这个条件),也就是要满足Model的参数和Where的条件。如果代码改为“&User{ID:3}“说明除了名字为li还要ID为3。如果查询到多条记录名字为”li”,则他们的年龄都会改为30
db.Model(&User{}).Where("name = ?", "li").Updates(User{Age: 30})
这里可以直接把名字为li的这行参数换为结构体中的参数,当然也可以放入多个参数。这里要注意调用的方法是Updates而不是Update。
五、删除操作
db.Where("Name = ?", "test").Delete(&User{})
这里要注意多条满足条件的记录都会被删除,建议加上主键指定要删除的User。
如果定义User变量这里会返回一个空值。
参考
建议调用数据库的时候根据情况查看GORM 指南 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.,里面的介绍还是比较详细。