GO的数据库操作(GORM)
数据库连接
这边主要是使用记录mysq数据库的操作,这边使用gorm是v2.0,所以注意扩展的引入地址
- 首先引入扩展包
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
- 连接数据
dsn := "用户名:密码@tcp(IP地址:3306)/tar?charset=utf8mb4&parseTime=True&loc=Local"
dbconn, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic(err)//打印错误
}
数据库的查询
1.首先定义2个结构体,1个是对应数据库表的需要引入gorm.Model,一个是用来存储查询结果的
2.然后对应手册看需要用到的对应函数方法
简单示例:获取表中全部数据并返回json格式数据
//供应商类型结构体定义
type (
Supplier struct {
gorm.Model
ID uint `json:"id"`
SupplierName string `json:"supplier_name"`
SourceName string `json:"source_name"`
DockingName string `json:"docking_name"`
Tel string `json:"tel"`
CompanyProfile string `json:"company_profile"`
}
TransformedSupplier struct {
ID uint `json:"id"`
SupplierName string `json:"supplier_name"`
SourceName string `json:"source_name"`
DockingName string `json:"docking_name"`
Tel string `json:"tel"`
CompanyProfile string `json:"company_profile"`
}
)
//自定义表名称,数据库操作时给结构体指定对应的表名
func (Supplier) TableName() string {
return "qc_suppliers"
}
//连接数据库
dsn := "用户名:密码@tcp(IP地址:3306)/tar?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic(err)//打印错误
}
//定义存储查询结果的变量
var result []*TransformedSupplier
//指定查询model(对应的数据结构体名称),FIND(存储查询结果的变量地址)
db.Model(&Supplier{}).Find(&result)
//返回json格式数据
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": result})
相关其他查询函数的应用
- db.First(&user)// 获取第一条记录(主键升序) db.First(&user)
- db.Take(&user)// 获取一条记录,没有指定排序字段
- db.Model(&User{}).First(&result) // SELECT * FROM
users
ORDER BYusers
.id
LIMIT 1 - db.Find(&users, []int{1,2,3}) // SELECT * FROM users WHERE id IN (1,2,3);
- db.First(&user, “10”) // SELECT * FROM users WHERE id = 10;
- db.Where(“name = ? AND age >= ?”, “jinzhu”, “22”).Find(&users)// SELECT * FROM users WHERE name = ‘jinzhu’ AND age >= 22;
- db.Where(“role = ?”, “admin”).Or(“role = ?”, “super_admin”).Find(&users)// SELECT * FROM users WHERE role = ‘admin’ OR role = ‘super_admin’;
- db.Select(“name”, “age”).Find(&users) // SELECT name, age FROM users;
- db.Order(“age desc, name”).Find(&users) // SELECT * FROM users ORDER BY age desc, name;
- db.Limit(10).Offset(5).Find(&users) // SELECT * FROM users OFFSET 5 LIMIT 10;
- db.Model(&User{}).Select(“name, sum(age) as total”).Group(“name”).Having(“name = ?”, “group”).Find(&result) // SELECT name, sum(age) as total FROM
users
GROUP BYname
HAVING name = “group”
相关常用函数,自己随意整理
函数名称 | 大概含义 |
First(&user) | 获取根据主键升序得第一条记录 |
Take(&user) | 获取一条记录,没有指定排序字段 |
Last(&user) | 获取最后一条记录(主键降序) |
Model(&User{}) | 指定表名Model(&结构体) |
Find(&users) | // 获取全部记录result.RowsAffected // 返回找到的记录数,相当于 |
Where(“name = ?”, “jinzhu”) | Where(“条件语句”,问号标识得具体值) |
Where(&User{Name: “jinzhu”, Age: 20}). | 也可以用结构体 |
db.Find(&user, “name = ?”, “jinzhu”) | 也可以和where相似用法 |
db.Find(&users) | 直接写不带参,获取全部 |
Where().Or(). | 左右2边写2条件,例如Where(“role = ?”, “admin”).Or(“role = ?”, “super_admin”) |
Select(“字段一”, “字段2”). | Select(“name”, “age”)读取指定字段 |
Order(“排序条件”) | Order(“age desc, name”)//指定排序条件 |
Limit(10).Offset(5) | Limit(每页数量),Offset(起始位置) |
Group(指定分组字段) | .Group(“date(created_at)”) |
Having(分组条件). | Having(“sum(amount) > ?”, 100). |
Table(“orders”) | 直接指定操作数据库表名 |
Distinct(“name”, “age”). | 去重 |
Joins(关联条件) | db.Model(&User{}).Select(“users.name, emails.email”).Joins(“left join emails on emails.user_id = users.id”).Scan(&result{}) |
Scan(结构体) | Scan 结果至 struct,用法与 |
新增数据
Create函数,引入结构体指针,单个插入
supplier := Supplier{SupplierName: "Jinzhu", SourceName: "测试", DockingName: "YW"}
result := db.Create(&supplier) // 通过数据的指针来创建
//user.ID 返回插入数据的主键
//result.Error 返回 error
//result.RowsAffected 返回插入记录的条数
批量插入操作
var suppliers = []Supplier{{SupplierName: "jinzhu1"}, {SupplierName: "jinzhu2"}, {SupplierName: "jinzhu3"}}
db.Create(&suppliers)
for _, user := range users {
user.ID // 1,2,3 生成得自增id
}
指定插入数量
var 用户 = []Supplier{SupplierName: "jinzhu_1"}, ...., {SupplierName: "jinzhu_10000"}}
// 数量为 100
db.CreateInBatches(用户, 100)
还可以根据map创建
db.Model(&Supplier{}).Create(map[string]interface{}{
"Name": "jinzhu", "Age": 18,
})
// batch insert from `[]map[string]interface{}{}`
db.Model(&Supplier{}).Create([]map[string]interface{}{
{"SupplierName": "jinzhu_1"},
{"SupplierName": "jinzhu_2"},
})
数据更新
更新指定字段数据
db.First(&user)
Supplier.SupplierName = "jinzhu 2"
Supplier.SourceName = "gg 2"
db.Save(&Supplier)
指定条件更新
// 条件更新
db.Model(&Supplier{}).Where("score = ?", 10).Update("supplier_name", "hello")
// UPDATE supplier SET supplier_name='hello', updated_at='2022-05-09 21:34:10' WHERE score=10;
// 根据 `struct` 更新属性,只会更新非零值的字段
db.Model(&Supplier).Where("id = ?", 111).Updates(Supplier{SupplierName: "hello", SourceName: "boss"})
// UPDATE users SET supplier_name='hello', score=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;
批量更新
// 通过 `RowsAffected` 得到更新的记录数
result := db.Model(Supplier{}).Where("role = ?", "admin").Updates(Supplier{SupplierName: "hello", SourceName: "boss"})
// UPDATE users SET score=18 WHERE supplier_name = 'admin;
result.RowsAffected // 更新的记录数
result.Error // 更新的错误
删除数据
删除指定数据
// 带额外条件的删除
db.Where("supplier_name = ?", "jinzhu").Delete(&email)
// DELETE from supplier where id = 10 AND supplier_name = "jinzhu";
db.Delete(&User{}, 10)
// DELETE FROM supplier WHERE id = 10;
db.Delete(&Supplier{}, "10")
// DELETE FROM supplier WHERE id = 10;
db.Delete(&Supplier, []int{1,2,3})
// DELETE FROM supplier WHERE id IN (1,2,3);
软删除
如果您的模型包含了一个
gorm.deletedat
字段(gorm.Model
已经包含了该字段),它将自动获得软删除的能力!拥有软删除能力的模型调用
Delete
时,记录不会被从数据库中真正删除。但 GORM 会将DeletedAt
置为当前时间, 并且你不能再通过正常的查询方法找到该记录。
// user 的 ID 是 `111`
db.Delete(&Supplier)
// UPDATE supplier SET deleted_at="2022-04-29 10:23" WHERE id = 111;
// 批量删除
db.Where("age = ?", 20).Delete(&Supplier{})
// UPDATE supplier SET deleted_at="2022-04-29 10:23" WHERE score = 20;
// 在查询时会忽略被软删除的记录
db.Where("age = 20").Find(&Supplier)
// SELECT * FROM supplier WHERE score = 20 AND deleted_at IS NULL;
查看软删除和永久的删除
db.Unscoped().Where("score = 20").Find(&Supplier)
// SELECT * FROM supplier WHERE score = 20;
db.Unscoped().Delete(&Supplier)
// DELETE FROM supplier WHERE id=10;